diff options
-rw-r--r-- | mod/ci-common.cxx | 41 | ||||
-rw-r--r-- | mod/ci-common.hxx | 35 | ||||
-rw-r--r-- | mod/mod-build-force.cxx | 6 |
3 files changed, 82 insertions, 0 deletions
diff --git a/mod/ci-common.cxx b/mod/ci-common.cxx index 5191d46..11d55af 100644 --- a/mod/ci-common.cxx +++ b/mod/ci-common.cxx @@ -14,6 +14,8 @@ #include <libbutl/process-io.hxx> // operator<<(ostream, process_args) #include <libbutl/manifest-serializer.hxx> +#include <libbrep/build.hxx> +#include <libbrep/build-odb.hxx> #include <libbrep/build-package.hxx> #include <libbrep/build-package-odb.hxx> @@ -815,4 +817,43 @@ namespace brep return true; } + + optional<build_state> ci_start:: + rebuild (odb::core::database& db, const build_id& id) const + { + using namespace odb::core; + + // NOTE: don't forget to update build_force::handle() if changing anything + // here. + // + transaction t (db.begin ()); + + package_build pb; + if (!db.query_one<package_build> (query<package_build>::build::id == id, + pb) || + pb.archived) + { + return nullopt; + } + + const shared_ptr<build>& b (pb.build); + build_state s (b->state); + + if (s != build_state::queued) + { + force_state force (s == build_state::built + ? force_state::forced + : force_state::forcing); + + if (b->force != force) + { + b->force = force; + db.update (b); + } + } + + t.commit (); + + return s; + } } diff --git a/mod/ci-common.hxx b/mod/ci-common.hxx index df580e4..d155398 100644 --- a/mod/ci-common.hxx +++ b/mod/ci-common.hxx @@ -9,6 +9,7 @@ #include <libbrep/types.hxx> #include <libbrep/utility.hxx> +#include <libbrep/build.hxx> #include <libbrep/common.hxx> #include <mod/diagnostics.hxx> @@ -170,6 +171,40 @@ namespace brep odb::core::database&, const string& tenant_id) const; + // Schedule the re-build of the package build and return the build object + // current state. + // + // Specifically: + // + // - If the build has expired (build or package object doesn't exist or + // the package is archived or is not buildable anymore, etc), then do + // nothing and return nullopt. + // + // Note, however, that this function doesn't check if the build + // configuration still exists in the buildtab. It is supposed that the + // caller has already checked for that if necessary (see + // build_force::handle() for an example of this check). And if not + // then a re-build will be scheduled and later cleaned by the cleaner + // (without notifications). + // + // - Otherwise, if the build object is in the queued state, then do + // nothing and return build_state::queued. It is assumed that a build + // object in such a state is already about to be built. + // + // - Otherwise (the build object is in the building or built state), + // schedule the object for the rebuild and return the current state. + // + // Note that in contrast to the build-force handler, this function doesn't + // send the build_queued() notification to the tenant-associated service + // if the object is in the building state (which is done as soon as + // possible to avoid races). Instead, it is assumed the service will + // perform any equivalent actions directly based on the returned state. + // + // Note: should be called out of the database transaction. + // + optional<build_state> + rebuild (odb::core::database&, const build_id&) const; + // Helpers. // diff --git a/mod/mod-build-force.cxx b/mod/mod-build-force.cxx index ea921e9..8666889 100644 --- a/mod/mod-build-force.cxx +++ b/mod/mod-build-force.cxx @@ -198,6 +198,9 @@ handle (request& rq, response& rs) // connection_ptr conn (build_db_->connection ()); + // NOTE: don't forget to update ci_start::rebuild() if changing anything + // here. + // { transaction t (conn->begin ()); @@ -206,8 +209,11 @@ handle (request& rq, response& rs) if (!build_db_->query_one<package_build> ( query<package_build>::build::id == id, pb) || + pb.archived || (b = move (pb.build))->state == build_state::queued) + { config_expired ("no package build"); + } force_state force (b->state == build_state::built ? force_state::forced |