aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2024-03-22 18:00:37 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2024-03-25 11:37:24 +0300
commit39a7404e6cddb2053a87f86935cda566c54bd4e6 (patch)
tree2a03c27435b6e37b395167cd49bd85be3a9a9ad9
parenta7e49dbeab6c1a0500ca8fa3a1a6261b3740b6b0 (diff)
Add tenant_service_hints
-rw-r--r--mod/mod-build-force.cxx35
-rw-r--r--mod/mod-build-result.cxx25
-rw-r--r--mod/mod-build-task.cxx35
-rw-r--r--mod/mod-ci.cxx6
-rw-r--r--mod/mod-ci.hxx1
-rw-r--r--mod/tenant-service.hxx19
6 files changed, 101 insertions, 20 deletions
diff --git a/mod/mod-build-force.cxx b/mod/mod-build-force.cxx
index 2eddb10..bdae356 100644
--- a/mod/mod-build-force.cxx
+++ b/mod/mod-build-force.cxx
@@ -10,6 +10,8 @@
#include <libbrep/build.hxx>
#include <libbrep/build-odb.hxx>
+#include <libbrep/build-package.hxx>
+#include <libbrep/build-package-odb.hxx>
#include <mod/module-options.hxx>
#include <mod/tenant-service.hxx>
@@ -184,10 +186,11 @@ handle (request& rq, response& rs)
// If the incomplete package build is being forced to rebuild and the
// tenant_service_build_queued callback is associated with the package
// tenant, then stash the state, the build object, and the callback pointer
- // for the subsequent service `queued` notification.
+ // and calculate the hints for the subsequent service `queued` notification.
//
const tenant_service_build_queued* tsq (nullptr);
optional<pair<tenant_service, shared_ptr<build>>> tss;
+ tenant_service_build_queued::build_queued_hints qhs;
connection_ptr conn (build_db_->connection ());
{
@@ -244,13 +247,27 @@ handle (request& rq, response& rs)
tsq = dynamic_cast<const tenant_service_build_queued*> (
i->second.get ());
+ // If we ought to call the
+ // tenant_service_build_queued::build_queued() callback, then also
+ // set the package tenant's queued timestamp to the current time
+ // to prevent the notifications race (see tenant::queued_timestamp
+ // for details).
+ //
if (tsq != nullptr)
{
- // If we ought to call the
- // tenant_service_build_queued::build_queued() callback, then
- // also set the package tenant's queued timestamp to the current
- // time to prevent the notifications race (see
- // tenant::queued_timestamp for details).
+ // Calculate the tenant service hints.
+ //
+ buildable_package_count tpc (
+ build_db_->query_value<buildable_package_count> (
+ query<buildable_package_count>::build_tenant::id == t->id));
+
+ shared_ptr<build_package> p (
+ build_db_->load<build_package> (b->id.package));
+
+ qhs = tenant_service_build_queued::build_queued_hints {
+ tpc == 1, p->configs.size () == 1};
+
+ // Set the package tenant's queued timestamp.
//
t->queued_timestamp = system_clock::now ();
build_db_->update (t);
@@ -280,7 +297,11 @@ handle (request& rq, response& rs)
vector<build> qbs;
qbs.push_back (move (b));
- if (auto f = tsq->build_queued (ss, qbs, build_state::building, log_writer_))
+ if (auto f = tsq->build_queued (ss,
+ qbs,
+ build_state::building,
+ qhs,
+ log_writer_))
update_tenant_service_state (conn, qbs.back ().tenant, f);
}
diff --git a/mod/mod-build-result.cxx b/mod/mod-build-result.cxx
index 605f83d..ccce17f 100644
--- a/mod/mod-build-result.cxx
+++ b/mod/mod-build-result.cxx
@@ -199,12 +199,13 @@ handle (request& rq, response&)
//
// If the package build is interrupted and the tenant_service_build_queued
// callback is associated with the package tenant, then stash the state, the
- // build object, and the callback pointer for the subsequent service
- // `queued` notification.
+ // build object, and the callback pointer and calculate the hints for the
+ // subsequent service `queued` notification.
//
const tenant_service_build_built* tsb (nullptr);
const tenant_service_build_queued* tsq (nullptr);
optional<pair<tenant_service, shared_ptr<build>>> tss;
+ tenant_service_build_queued::build_queued_hints qhs;
// Note that if the session authentication fails (probably due to the
// authentication settings change), then we log this case with the warning
@@ -342,6 +343,20 @@ handle (request& rq, response&)
//
if (tsq != nullptr)
{
+ // Calculate the tenant service hints.
+ //
+ buildable_package_count tpc (
+ build_db_->query_value<buildable_package_count> (
+ query<buildable_package_count>::build_tenant::id == t->id));
+
+ shared_ptr<build_package> p (
+ build_db_->load<build_package> (b->id.package));
+
+ qhs = tenant_service_build_queued::build_queued_hints {
+ tpc == 1, p->configs.size () == 1};
+
+ // Set the package tenant's queued timestamp.
+ //
t->queued_timestamp = system_clock::now ();
build_db_->update (t);
}
@@ -503,7 +518,11 @@ handle (request& rq, response&)
vector<build> qbs;
qbs.push_back (move (*tss->second));
- if (auto f = tsq->build_queued (ss, qbs, build_state::building, log_writer_))
+ if (auto f = tsq->build_queued (ss,
+ qbs,
+ build_state::building,
+ qhs,
+ log_writer_))
update_tenant_service_state (conn, qbs.back ().tenant, f);
}
diff --git a/mod/mod-build-task.cxx b/mod/mod-build-task.cxx
index 0892638..7373ffe 100644
--- a/mod/mod-build-task.cxx
+++ b/mod/mod-build-task.cxx
@@ -1006,12 +1006,13 @@ handle (request& rq, response& rs)
// Also, if the tenant_service_build_queued callback is registered, then
// create, persist, and stash the queued build objects for all the
// unbuilt by the current toolchain and not yet queued configurations of
- // the package the build task is created for. Note that for the task
- // build, we need to make sure that the third-party service receives the
- // `queued` notification prior to the `building` notification (see
- // mod/tenant-service.hxx for valid transitions). The `queued`
- // notification is assumed to be already sent for the build if the
- // respective object exists and any of the following is true for it:
+ // the package the build task is created for and calculate the hints.
+ // Note that for the task build, we need to make sure that the
+ // third-party service receives the `queued` notification prior to the
+ // `building` notification (see mod/tenant-service.hxx for valid
+ // transitions). The `queued` notification is assumed to be already sent
+ // for the build if the respective object exists and any of the
+ // following is true for it:
//
// - It is in the queued state (initial_state is build_state::queued).
//
@@ -1025,6 +1026,7 @@ handle (request& rq, response& rs)
const tenant_service_build_queued* tsq (nullptr);
optional<pair<tenant_service, shared_ptr<build>>> tss;
vector<build> qbs;
+ tenant_service_build_queued::build_queued_hints qhs;
optional<build_state> initial_state;
bool rebuild_forced_build (false);
bool rebuild_interrupted_rebuild (false);
@@ -1096,6 +1098,16 @@ handle (request& rq, response& rs)
return r;
};
+ auto queue_hints = [this] (const build_package& p)
+ {
+ buildable_package_count tpc (
+ build_db_->query_value<buildable_package_count> (
+ query<buildable_package_count>::build_tenant::id == p.id.tenant));
+
+ return tenant_service_build_queued::build_queued_hints {
+ tpc == 1, p.configs.size () == 1};
+ };
+
// Collect the auxiliary machines required for testing of the specified
// package configuration and the external test packages, if present for
// the specified target configuration (task_auxiliary_machines),
@@ -1767,6 +1779,8 @@ handle (request& rq, response& rs)
(*initial_state != build_state::queued &&
!rebuild_forced_build))
{
+ qhs = queue_hints (*p);
+
t->queued_timestamp = system_clock::now ();
build_db_->update (t);
}
@@ -1990,6 +2004,8 @@ handle (request& rq, response& rs)
//
if (!qbs.empty () || !rebuild_interrupted_rebuild)
{
+ qhs = queue_hints (*p);
+
t->queued_timestamp = system_clock::now ();
build_db_->update (t);
}
@@ -2063,6 +2079,7 @@ handle (request& rq, response& rs)
if (auto f = tsq->build_queued (ss,
qbs,
nullopt /* initial_state */,
+ qhs,
log_writer_))
update_tenant_service_state (conn, qbs.back ().tenant, f);
}
@@ -2079,7 +2096,11 @@ handle (request& rq, response& rs)
qbs.push_back (move (b));
restore_build = true;
- if (auto f = tsq->build_queued (ss, qbs, initial_state, log_writer_))
+ if (auto f = tsq->build_queued (ss,
+ qbs,
+ initial_state,
+ qhs,
+ log_writer_))
update_tenant_service_state (conn, qbs.back ().tenant, f);
}
diff --git a/mod/mod-ci.cxx b/mod/mod-ci.cxx
index 94a6882..c067f70 100644
--- a/mod/mod-ci.cxx
+++ b/mod/mod-ci.cxx
@@ -392,12 +392,16 @@ function<optional<string> (const brep::tenant_service&)> brep::ci::
build_queued (const tenant_service&,
const vector<build>& bs,
optional<build_state> initial_state,
+ const build_queued_hints& hints,
const diag_epilogue& log_writer) const noexcept
{
NOTIFICATION_DIAG (log_writer);
l2 ([&]{trace << "initial_state: "
- << (initial_state ? to_string (*initial_state) : "none");});
+ << (initial_state ? to_string (*initial_state) : "none")
+ << ", hints "
+ << static_cast<size_t> (hints.single_package_version) << ' '
+ << static_cast<size_t> (hints.single_package_config);});
return [&bs, initial_state] (const tenant_service& ts)
{
diff --git a/mod/mod-ci.hxx b/mod/mod-ci.hxx
index 48d42ee..1e2ee15 100644
--- a/mod/mod-ci.hxx
+++ b/mod/mod-ci.hxx
@@ -62,6 +62,7 @@ namespace brep
build_queued (const tenant_service&,
const vector<build>&,
optional<build_state> initial_state,
+ const build_queued_hints&,
const diag_epilogue& log_writer) const noexcept override;
virtual function<optional<string> (const tenant_service&)>
diff --git a/mod/tenant-service.hxx b/mod/tenant-service.hxx
index 46f2822..9205f76 100644
--- a/mod/tenant-service.hxx
+++ b/mod/tenant-service.hxx
@@ -62,7 +62,7 @@ namespace brep
// Each build notification is in its own interface since a service may not
// be interested in all of them while computing the information to pass is
// expensive.
- //
+
class tenant_service_build_queued: public virtual tenant_service_base
{
public:
@@ -74,17 +74,32 @@ namespace brep
//
// The passed initial_state indicates the logical initial state and is
// either absent, `building` (interrupted), or `built` (rebuild). Note
- // that all the passed build objects have the same initial state.
+ // that all the passed build objects are for the same package version and
+ // have the same initial state.
//
// The implementation of this and the below functions should normally not
// need to make any decisions based on the passed build::state. Rather,
// the function name suffix (_queued, _building, _built) signify the
// logical end state.
//
+ // The build_queued_hints can be used to omit certain components from the
+ // build id. If single_package_version is true, then this tenant contains
+ // a single (non-test) package version and this package name and package
+ // version can be omitted. If single_package_config is true, then the
+ // package version being built only has the default package configuration
+ // and thus it can be omitted.
+ //
+ struct build_queued_hints
+ {
+ bool single_package_version;
+ bool single_package_config;
+ };
+
virtual function<optional<string> (const tenant_service&)>
build_queued (const tenant_service&,
const vector<build>&,
optional<build_state> initial_state,
+ const build_queued_hints&,
const diag_epilogue& log_writer) const noexcept = 0;
};