diff options
-rw-r--r-- | libbrep/common.hxx | 2 | ||||
-rw-r--r-- | mod/ci-common.cxx | 11 | ||||
-rw-r--r-- | mod/ci-common.hxx | 41 |
3 files changed, 48 insertions, 6 deletions
diff --git a/libbrep/common.hxx b/libbrep/common.hxx index 8312b61..d2009f5 100644 --- a/libbrep/common.hxx +++ b/libbrep/common.hxx @@ -541,6 +541,8 @@ namespace brep // Third-party service state which may optionally be associated with a // tenant (see also mod/tenant-service.hxx for background). // + // Note that the {id, type} pair must be unique. + // #pragma db value struct tenant_service { diff --git a/mod/ci-common.cxx b/mod/ci-common.cxx index c0ef89f..b3fc432 100644 --- a/mod/ci-common.cxx +++ b/mod/ci-common.cxx @@ -534,14 +534,15 @@ namespace brep s.next ("", ""); // End of manifest. } - optional<string> ci_start:: + pair<optional<string>, ci_start::duplicate_tenant_result> ci_start:: create (const basic_mark& error, const basic_mark&, const basic_mark* trace, odb::core::database& db, tenant_service&& service, duration notify_interval, - duration notify_delay) const + duration notify_delay, + duplicate_tenant_mode) const { using namespace odb::core; @@ -556,7 +557,7 @@ namespace brep catch (const system_error& e) { error << "unable to generate request id: " << e; - return nullopt; + return {nullopt, duplicate_tenant_result::ignored}; // @@ TODO HACKED AROUND } // Use the generated request id if the tenant service id is not specified. @@ -604,7 +605,7 @@ namespace brep *trace << "unloaded CI request " << t.id << " for service " << t.service->id << ' ' << t.service->type << " is created"; - return move (t.id); + return {move (t.id), duplicate_tenant_result::created}; // @@ TODO HACKED AROUND } optional<ci_start::start_result> ci_start:: @@ -707,6 +708,8 @@ namespace brep if (t == nullptr) return nullopt; + // @@ Why not remove it if unloaded (and below)? + optional<tenant_service> r (move (t->service)); t->service = nullopt; t->archived = true; diff --git a/mod/ci-common.hxx b/mod/ci-common.hxx index 6a07154..d01e251 100644 --- a/mod/ci-common.hxx +++ b/mod/ci-common.hxx @@ -72,16 +72,39 @@ namespace brep // created tenant and set the initial delay for the first notification. // See also the build_unloaded() tenant services notification. // + // The duplicate_tenant_mode argument specifies the behavior in case of + // the duplicate tenant_service type/id pair. The default is to fail by + // throwing an exception. Alternatively, this can be ignored or the + // previous tenant can be canceled (thus freeing the type/id pair; see + // below) and a new tenant with the same type/id created. In both these + // modes (ignore and replace), the second half of the returned pair + // indicates whether there was a duplicate. If there were, then for the + // ignore mode the returned reference corresponds to the old tenant and + // for the replace mode -- to the new tenant. + // + // The replace_archived mode is a variant of replace that replaces if the + // tenant is already archived and ignores it otherwise (with the result + // having the same semantics as in the replace and ignore modes). + // + // Note also that the duplicate_tenant_mode::replace modes are not the + // same as separate calls to create() and then to cancel() since the + // latter would happen in two separate transactions and will thus be + // racy. @@@ TODO + // // Note: should be called out of the database transaction. // - optional<string> + enum class duplicate_tenant_mode {fail, ignore, replace, replace_archived}; + enum class duplicate_tenant_result {created, ignored, replaced}; + + pair<optional<string>, duplicate_tenant_result> create (const basic_mark& error, const basic_mark& warn, const basic_mark* trace, odb::core::database&, tenant_service&&, duration notify_interval, - duration notify_delay) const; + duration notify_delay, + duplicate_tenant_mode = duplicate_tenant_mode::fail) const; // Load (and start) previously created (as unloaded) CI request. Similarly // to the start() function, return nullopt on an internal error. @@ -101,6 +124,12 @@ namespace brep // Cancel previously created or started CI request. Return the service // state or nullopt if there is no tenant for such a type/id pair. // + // Specifically, this function clears the tenant service state (thus + // allowing reusing the same service type/id pair in another tenant) and + // archives the tenant, unless the tenant is unloaded, in which case it is + // dropped (@@@ TODO). Note that the latter allow using unloaded tenants + // as a relatively cheap asynchronous execution mechanism. + // // Note: should be called out of the database transaction. // optional<tenant_service> @@ -115,6 +144,14 @@ namespace brep // is no tenant for the specified tenant id. Note that the reason argument // is only used for tracing. // + // @@@ Is tenant id here and reference above the same thing? Maybe use + // "tenant id" and "service id" terminology throughout? + // + // Similarly to above, this function archives the tenant, unless the + // tenant is unloaded, in which case it is dropped (@@@ TODO). Note, + // however, that this version does not touch the service state (use the + // above version if you want to clear it). + // // Note: should be called out of the database transaction. // bool |