diff options
-rw-r--r-- | mod/mod-build-force.cxx | 35 | ||||
-rw-r--r-- | mod/mod-build-result.cxx | 25 | ||||
-rw-r--r-- | mod/mod-build-task.cxx | 35 | ||||
-rw-r--r-- | mod/mod-ci.cxx | 6 | ||||
-rw-r--r-- | mod/mod-ci.hxx | 1 | ||||
-rw-r--r-- | mod/tenant-service.hxx | 19 |
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; }; |