diff options
Diffstat (limited to 'mod/mod-build-task.cxx')
-rw-r--r-- | mod/mod-build-task.cxx | 94 |
1 files changed, 72 insertions, 22 deletions
diff --git a/mod/mod-build-task.cxx b/mod/mod-build-task.cxx index c8b1bb2..e769f6a 100644 --- a/mod/mod-build-task.cxx +++ b/mod/mod-build-task.cxx @@ -989,8 +989,8 @@ handle (request& rq, response& rs) pq += "ORDER BY"; - // If the interactive mode is both, then order the packages so that ones - // from the interactive build tenants appear first. + // If the interactive mode is `both`, then order the packages so that + // ones from the interactive build tenants appear first. // if (imode == interactive_mode::both) pq += pkg_query::build_tenant::interactive + "NULLS LAST,"; @@ -1657,9 +1657,8 @@ handle (request& rq, response& rs) // Collect the potential build configurations as all combinations // of the tenant's packages build configurations and the - // non-excluded (by the packages) build target - // configurations. Note that here we ignore the machines from the - // task request. + // non-excluded (by the packages) build target configurations. + // Note that here we ignore the machines from the task request. // struct build_config { @@ -1800,9 +1799,9 @@ handle (request& rq, response& rs) pkg_config = pc.name; - // Iterate through the built configurations and erase them from the - // build configuration map. All those configurations that remained - // can be built. We will take the first one, if present. + // Iterate through the built configurations and erase them from + // the build configuration map. All those configurations that + // remained can be built. We will take the first one, if present. // // Also save the built configurations for which it's time to be // rebuilt. @@ -2005,10 +2004,21 @@ handle (request& rq, response& rs) qbs = queue_builds (*p, *b); // 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). + // tenant_service_build_queued::build_queued() callback + // for the queued builds (qbs is not empty), then we + // also set the package tenant's queued timestamp to the + // current time to prevent any concurrently running task + // handlers from picking any of these queued builds now + // and so potentially interfering with us by sending + // their `building` notification before we send our + // `queued` notification (see tenant::queued_timestamp + // for details). Note that the `queued` notification for + // the being built configuration doesn't require setting + // this timestamp, since after the respective build + // object is changed and updated in the database it may + // not be picked by any task handler in the foreseeable + // future and so our {`queued`, `building`} notification + // sequence may not be interfered. // if (!qbs.empty () || !initial_state || @@ -2017,8 +2027,11 @@ handle (request& rq, response& rs) { qhs = queue_hints (*p); - t->queued_timestamp = system_clock::now (); - build_db_->update (t); + if (!qbs.empty ()) + { + t->queued_timestamp = system_clock::now (); + build_db_->update (t); + } } } @@ -2261,17 +2274,20 @@ handle (request& rq, response& rs) // 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). + // callback for the queued builds, then also set the + // package tenant's queued timestamp to the current + // time to prevent the notifications race (see above + // building from scratch for details). // if (!qbs.empty () || !rebuild_interrupted_rebuild) { qhs = queue_hints (*p); - t->queued_timestamp = system_clock::now (); - build_db_->update (t); + if (!qbs.empty ()) + { + t->queued_timestamp = system_clock::now (); + build_db_->update (t); + } } } @@ -2311,6 +2327,13 @@ handle (request& rq, response& rs) agent_fp = move (b->agent_fingerprint); challenge = move (b->agent_challenge); task_response = task_response_manifest (); + + // Also cleanup the tenant-associated third-party service data. + // + tsb = nullptr; + tsq = nullptr; + tss = nullopt; + qbs.clear (); } // If the task manifest is prepared, then bail out from the package @@ -2372,6 +2395,10 @@ handle (request& rq, response& rs) // Send the `queued` notification for the task build, unless it is // already sent, and update the service state, if requested. // + // Why don't we join this notification with the previous one? We + // cannot do this since the initial_state argument differs for the + // respective build_queued() function calls. + // if (initial_state && *initial_state != build_state::queued && !rebuild_interrupted_rebuild && @@ -2407,7 +2434,7 @@ handle (request& rq, response& rs) } // If a third-party service needs to be notified about the package - // build, then call the tenant_service_build_built::build_building() + // build, then call the tenant_service_build_building::build_building() // callback function and, if requested, update the tenant-associated // service state. // @@ -2556,9 +2583,32 @@ handle (request& rq, response& rs) { conn = build_db_->connection (); + bool build_completed (false); + if (optional<string> data = - update_tenant_service_state (conn, ss.type, ss.id, f)) + update_tenant_service_state ( + conn, ss.type, ss.id, + [&f, &build_completed] (const string& tid, + const tenant_service& ts) + { + auto r (f (tid, ts)); + build_completed = r.second; + return move (r.first); + })) + { ss.data = move (data); + } + + if (build_completed) + { + // Release the database connection since the build_completed() + // notification can potentially be time-consuming (e.g., it may + // perform an HTTP request). + // + conn.reset (); + + tsb->build_completed (b.tenant, ss, log_writer_); + } } } } |