aboutsummaryrefslogtreecommitdiff
path: root/mod
diff options
context:
space:
mode:
Diffstat (limited to 'mod')
-rw-r--r--mod/ci-common.cxx9
-rw-r--r--mod/ci-common.hxx12
-rw-r--r--mod/database-module.cxx20
-rw-r--r--mod/database-module.hxx14
-rw-r--r--mod/mod-build-force.cxx5
-rw-r--r--mod/mod-build-result.cxx9
-rw-r--r--mod/mod-build-task.cxx26
-rw-r--r--mod/mod-ci-github.cxx57
-rw-r--r--mod/mod-ci-github.hxx32
-rw-r--r--mod/mod-ci.cxx29
-rw-r--r--mod/mod-ci.hxx24
-rw-r--r--mod/tenant-service.hxx32
12 files changed, 176 insertions, 93 deletions
diff --git a/mod/ci-common.cxx b/mod/ci-common.cxx
index cba421b..e720914 100644
--- a/mod/ci-common.cxx
+++ b/mod/ci-common.cxx
@@ -955,7 +955,8 @@ namespace brep
rebuild (odb::core::database& db,
size_t retry,
const build_id& id,
- function<optional<string> (const tenant_service&,
+ function<optional<string> (const string& tenant_id,
+ const tenant_service&,
build_state)> uf) const
{
using namespace odb::core;
@@ -1002,7 +1003,7 @@ namespace brep
tenant_service& ts (*t->service);
- if (optional<string> data = uf (ts, s))
+ if (optional<string> data = uf (t->id, ts, s))
{
ts.data = move (*data);
db.update (t);
@@ -1030,7 +1031,7 @@ namespace brep
return s;
}
- optional<pair<tenant_service, bool>> ci_start::
+ optional<ci_start::tenant_data> ci_start::
find (odb::core::database& db,
const string& type,
const string& id) const
@@ -1052,6 +1053,6 @@ namespace brep
if (t == nullptr || !t->service)
return nullopt;
- return pair<tenant_service, bool> (move (*t->service), t->archived);
+ return tenant_data {move (t->id), move (*t->service), t->archived};
}
}
diff --git a/mod/ci-common.hxx b/mod/ci-common.hxx
index b32d397..a38ac54 100644
--- a/mod/ci-common.hxx
+++ b/mod/ci-common.hxx
@@ -242,7 +242,8 @@ namespace brep
rebuild (odb::core::database&,
size_t retry,
const build_id&,
- function<optional<string> (const tenant_service&,
+ function<optional<string> (const string& tenant_id,
+ const tenant_service&,
build_state)> = nullptr) const;
// Find the tenant given the tenant service type and id and return the
@@ -251,7 +252,14 @@ namespace brep
//
// Note: should be called out of the database transaction.
//
- optional<pair<tenant_service, bool /*archived*/>>
+ struct tenant_data
+ {
+ string tenant_id;
+ tenant_service service;
+ bool archived;
+ };
+
+ optional<tenant_data>
find (odb::core::database&,
const string& type,
const string& id) const;
diff --git a/mod/database-module.cxx b/mod/database-module.cxx
index bce8c93..629e393 100644
--- a/mod/database-module.cxx
+++ b/mod/database-module.cxx
@@ -79,8 +79,10 @@ namespace brep
optional<string> database_module::
update_tenant_service_state (
const connection_ptr& conn,
- const string& tid,
- const function<optional<string> (const tenant_service&)>& f)
+ const string& type,
+ const string& id,
+ const function<optional<string> (const string& tenant_id,
+ const tenant_service&)>& f)
{
assert (f != nullptr); // Shouldn't be called otherwise.
@@ -96,13 +98,21 @@ namespace brep
{
transaction tr (conn->begin ());
- shared_ptr<build_tenant> t (build_db_->find<build_tenant> (tid));
+ using query = query<build_tenant>;
- if (t != nullptr && t->service)
+ shared_ptr<build_tenant> t (
+ build_db_->query_one<build_tenant> (query::service.id == id &&
+ query::service.type == type));
+
+ if (t != nullptr)
{
+ // Shouldn't be here otherwise.
+ //
+ assert (t->service);
+
tenant_service& s (*t->service);
- if (optional<string> data = f (s))
+ if (optional<string> data = f (t->id, s))
{
s.data = move (*data);
build_db_->update (t);
diff --git a/mod/database-module.hxx b/mod/database-module.hxx
index 298afbf..76f13d4 100644
--- a/mod/database-module.hxx
+++ b/mod/database-module.hxx
@@ -61,16 +61,18 @@ namespace brep
// and nullopt otherwise.
//
// Specifically, start the database transaction, query the service state,
- // and call the callback-returned function on this state. If this call
- // returns the data string (rather than nullopt), then update the service
- // state with this data and persist the change. Repeat all the above steps
- // on the recoverable database failures (deadlocks, etc).
+ // and, if present, call the callback-returned function on this state. If
+ // this call returns the data string (rather than nullopt), then update
+ // the service state with this data and persist the change. Repeat all the
+ // above steps on the recoverable database failures (deadlocks, etc).
//
optional<string>
update_tenant_service_state (
const odb::core::connection_ptr&,
- const string& tid,
- const function<optional<string> (const tenant_service&)>&);
+ const string& type,
+ const string& id,
+ const function<optional<string> (const string& tenant_id,
+ const tenant_service&)>&);
protected:
size_t retry_ = 0; // Max of all retries.
diff --git a/mod/mod-build-force.cxx b/mod/mod-build-force.cxx
index 8666889..d37674f 100644
--- a/mod/mod-build-force.cxx
+++ b/mod/mod-build-force.cxx
@@ -314,14 +314,15 @@ handle (request& rq, response& rs)
//
conn.reset ();
- if (auto f = tsq->build_queued (ss,
+ if (auto f = tsq->build_queued (qbs.back ().tenant,
+ ss,
qbs,
build_state::building,
qhs,
log_writer_))
{
conn = build_db_->connection ();
- update_tenant_service_state (conn, qbs.back ().tenant, f);
+ update_tenant_service_state (conn, ss.type, ss.id, f);
}
}
diff --git a/mod/mod-build-result.cxx b/mod/mod-build-result.cxx
index bc44bd2..cc058b5 100644
--- a/mod/mod-build-result.cxx
+++ b/mod/mod-build-result.cxx
@@ -545,14 +545,15 @@ handle (request& rq, response&)
//
conn.reset ();
- if (auto f = tsq->build_queued (ss,
+ if (auto f = tsq->build_queued (qbs.back ().tenant,
+ ss,
qbs,
build_state::building,
qhs,
log_writer_))
{
conn = build_db_->connection ();
- update_tenant_service_state (conn, qbs.back ().tenant, f);
+ update_tenant_service_state (conn, ss.type, ss.id, f);
}
}
@@ -572,10 +573,10 @@ handle (request& rq, response&)
//
conn.reset ();
- if (auto f = tsb->build_built (ss, b, log_writer_))
+ if (auto f = tsb->build_built (b.tenant, ss, b, log_writer_))
{
conn = build_db_->connection ();
- update_tenant_service_state (conn, b.tenant, f);
+ update_tenant_service_state (conn, ss.type, ss.id, f);
}
}
diff --git a/mod/mod-build-task.cxx b/mod/mod-build-task.cxx
index 2ae1237..c8b1bb2 100644
--- a/mod/mod-build-task.cxx
+++ b/mod/mod-build-task.cxx
@@ -499,10 +499,14 @@ handle (request& rq, response& rs)
//
conn.reset ();
- if (auto f = tsu->build_unloaded (move (*t->service), log_writer_))
+ tenant_service& ts (*t->service);
+ string type (ts.type);
+ string id (ts.id);
+
+ if (auto f = tsu->build_unloaded (t->id, move (ts), log_writer_))
{
conn = build_db_->connection ();
- update_tenant_service_state (conn, t->id, f);
+ update_tenant_service_state (conn, type, id, f);
}
}
}
@@ -2350,7 +2354,8 @@ handle (request& rq, response& rs)
//
conn.reset ();
- if (auto f = tsq->build_queued (ss,
+ if (auto f = tsq->build_queued (qbs.back ().tenant,
+ ss,
qbs,
nullopt /* initial_state */,
qhs,
@@ -2359,7 +2364,7 @@ handle (request& rq, response& rs)
conn = build_db_->connection ();
if (optional<string> data =
- update_tenant_service_state (conn, qbs.back ().tenant, f))
+ update_tenant_service_state (conn, ss.type, ss.id, f))
ss.data = move (data);
}
}
@@ -2382,7 +2387,8 @@ handle (request& rq, response& rs)
//
conn.reset ();
- if (auto f = tsq->build_queued (ss,
+ if (auto f = tsq->build_queued (qbs.back ().tenant,
+ ss,
qbs,
initial_state,
qhs,
@@ -2391,7 +2397,7 @@ handle (request& rq, response& rs)
conn = build_db_->connection ();
if (optional<string> data =
- update_tenant_service_state (conn, qbs.back ().tenant, f))
+ update_tenant_service_state (conn, ss.type, ss.id, f))
ss.data = move (data);
}
}
@@ -2418,12 +2424,12 @@ handle (request& rq, response& rs)
//
conn.reset ();
- if (auto f = tsb->build_building (ss, b, log_writer_))
+ if (auto f = tsb->build_building (b.tenant, ss, b, log_writer_))
{
conn = build_db_->connection ();
if (optional<string> data =
- update_tenant_service_state (conn, b.tenant, f))
+ update_tenant_service_state (conn, ss.type, ss.id, f))
ss.data = move (data);
}
}
@@ -2546,12 +2552,12 @@ handle (request& rq, response& rs)
//
conn.reset ();
- if (auto f = tsb->build_built (ss, b, log_writer_))
+ if (auto f = tsb->build_built (b.tenant, ss, b, log_writer_))
{
conn = build_db_->connection ();
if (optional<string> data =
- update_tenant_service_state (conn, b.tenant, f))
+ update_tenant_service_state (conn, ss.type, ss.id, f))
ss.data = move (data);
}
}
diff --git a/mod/mod-ci-github.cxx b/mod/mod-ci-github.cxx
index 56f703e..113da2e 100644
--- a/mod/mod-ci-github.cxx
+++ b/mod/mod-ci-github.cxx
@@ -599,10 +599,9 @@ namespace brep
{
kind = service_data::remote;
- if (optional<pair<tenant_service, bool>> p =
- find (*build_db_, "ci-github", sid))
+ if (optional<tenant_data> d = find (*build_db_, "ci-github", sid))
{
- tenant_service& ts (p->first);
+ tenant_service& ts (d->service);
try
{
@@ -801,10 +800,9 @@ namespace brep
//
string sid (repo_node_id + ':' + head_sha);
- if (optional<pair<tenant_service, bool>> p =
- find (*build_db_, "ci-github", sid))
+ if (optional<tenant_data> d = find (*build_db_, "ci-github", sid))
{
- if (p->second) // Tenant is archived
+ if (d->archived) // Tenant is archived
{
// Fail (re-create) the check runs.
//
@@ -860,7 +858,7 @@ namespace brep
return true;
}
- tenant_service& ts (p->first);
+ tenant_service& ts (d->service);
try
{
@@ -1017,7 +1015,8 @@ namespace brep
// only if the build is actually restarted).
//
auto update_sd = [&error, &new_iat, &race,
- &cr, &bcr, &ccr] (const tenant_service& ts,
+ &cr, &bcr, &ccr] (const string& /*tenant_id*/,
+ const tenant_service& ts,
build_state) -> optional<string>
{
// NOTE: this lambda may be called repeatedly (e.g., due to transaction
@@ -1321,8 +1320,10 @@ namespace brep
return true;
}
- function<optional<string> (const tenant_service&)> ci_github::
- build_unloaded (tenant_service&& ts,
+ function<optional<string> (const string& tenant_id,
+ const tenant_service&)> ci_github::
+ build_unloaded (const string& /*tenant_id*/,
+ tenant_service&& ts,
const diag_epilogue& log_writer) const noexcept
{
// NOTE: this function is noexcept and should not throw.
@@ -1345,7 +1346,8 @@ namespace brep
: build_unloaded_load (move (ts), move (sd), log_writer);
}
- function<optional<string> (const tenant_service&)> ci_github::
+ function<optional<string> (const string& tenant_id,
+ const tenant_service&)> ci_github::
build_unloaded_pre_check (tenant_service&& ts,
service_data&& sd,
const diag_epilogue& log_writer) const noexcept
@@ -1545,7 +1547,8 @@ namespace brep
return nullptr;
}
- function<optional<string> (const tenant_service&)> ci_github::
+ function<optional<string> (const string& tenant_id,
+ const tenant_service&)> ci_github::
build_unloaded_load (tenant_service&& ts,
service_data&& sd,
const diag_epilogue& log_writer) const noexcept
@@ -1750,7 +1753,8 @@ namespace brep
return [&error,
iat = move (new_iat),
cni = move (conclusion_node_id)]
- (const tenant_service& ts) -> optional<string>
+ (const string& /*tenant_id*/,
+ const tenant_service& ts) -> optional<string>
{
// NOTE: this lambda may be called repeatedly (e.g., due to
// transaction being aborted) and so should not move out of its
@@ -1887,8 +1891,10 @@ namespace brep
// if we have node_id, then we update, otherwise, we create (potentially
// overriding the check run created previously).
//
- function<optional<string> (const tenant_service&)> ci_github::
- build_queued (const tenant_service& ts,
+ function<optional<string> (const string& tenant_id,
+ const tenant_service&)> ci_github::
+ build_queued (const string& /*tenant_id*/,
+ const tenant_service& ts,
const vector<build>& builds,
optional<build_state> istate,
const build_queued_hints& hs,
@@ -2017,7 +2023,8 @@ namespace brep
iat = move (new_iat),
crs = move (crs),
error = move (error),
- warn = move (warn)] (const tenant_service& ts) -> optional<string>
+ warn = move (warn)] (const string& /*tenant_id*/,
+ const tenant_service& ts) -> optional<string>
{
// NOTE: this lambda may be called repeatedly (e.g., due to transaction
// being aborted) and so should not move out of its captures.
@@ -2070,8 +2077,10 @@ namespace brep
return nullptr;
}
- function<optional<string> (const tenant_service&)> ci_github::
- build_building (const tenant_service& ts,
+ function<optional<string> (const string& tenant_id,
+ const tenant_service&)> ci_github::
+ build_building (const string& /*tenant_id*/,
+ const tenant_service& ts,
const build& b,
const diag_epilogue& log_writer) const noexcept
try
@@ -2181,7 +2190,8 @@ namespace brep
return [iat = move (new_iat),
cr = move (*cr),
error = move (error),
- warn = move (warn)] (const tenant_service& ts) -> optional<string>
+ warn = move (warn)] (const string& /*tenant_id*/,
+ const tenant_service& ts) -> optional<string>
{
// NOTE: this lambda may be called repeatedly (e.g., due to transaction
// being aborted) and so should not move out of its captures.
@@ -2231,8 +2241,10 @@ namespace brep
return nullptr;
}
- function<optional<string> (const tenant_service&)> ci_github::
- build_built (const tenant_service& ts,
+ function<optional<string> (const string& tenant_id,
+ const tenant_service&)> ci_github::
+ build_built (const string& /*tenant_id*/,
+ const tenant_service& ts,
const build& b,
const diag_epilogue& log_writer) const noexcept
try
@@ -2561,7 +2573,8 @@ namespace brep
cr = move (cr),
completed = completed,
error = move (error),
- warn = move (warn)] (const tenant_service& ts) -> optional<string>
+ warn = move (warn)] (const string& /*tenant_id*/,
+ const tenant_service& ts) -> optional<string>
{
// NOTE: this lambda may be called repeatedly (e.g., due to transaction
// being aborted) and so should not move out of its captures.
diff --git a/mod/mod-ci-github.hxx b/mod/mod-ci-github.hxx
index c38462a..9b9814e 100644
--- a/mod/mod-ci-github.hxx
+++ b/mod/mod-ci-github.hxx
@@ -42,33 +42,45 @@ namespace brep
virtual const cli::options&
cli_options () const {return options::ci_github::description ();}
- virtual function<optional<string> (const tenant_service&)>
- build_unloaded (tenant_service&&,
+ virtual function<optional<string> (const string& tenant_id,
+ const tenant_service&)>
+ build_unloaded (const string& tenant_id,
+ tenant_service&&,
const diag_epilogue& log_writer) const noexcept override;
- function<optional<string> (const tenant_service&)>
+ function<optional<string> (const string& tenant_id,
+ const tenant_service&)>
build_unloaded_pre_check (tenant_service&&,
service_data&&,
const diag_epilogue&) const noexcept;
- function<optional<string> (const tenant_service&)>
+ function<optional<string> (const string& tenant_id,
+ const tenant_service&)>
build_unloaded_load (tenant_service&&,
service_data&&,
const diag_epilogue&) const noexcept;
- virtual function<optional<string> (const tenant_service&)>
- build_queued (const tenant_service&,
+ virtual function<optional<string> (const string& tenant_id,
+ const tenant_service&)>
+ build_queued (const string& tenant_id,
+ 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&)>
- build_building (const tenant_service&, const build&,
+ virtual function<optional<string> (const string& tenant_id,
+ const tenant_service&)>
+ build_building (const string& tenant_id,
+ const tenant_service&,
+ const build&,
const diag_epilogue& log_writer) const noexcept override;
- virtual function<optional<string> (const tenant_service&)>
- build_built (const tenant_service&, const build&,
+ virtual function<optional<string> (const string& tenant_id,
+ const tenant_service&)>
+ build_built (const string& tenant_id,
+ const tenant_service&,
+ const build&,
const diag_epilogue& log_writer) const noexcept override;
private:
diff --git a/mod/mod-ci.cxx b/mod/mod-ci.cxx
index 52f4644..46fbf6a 100644
--- a/mod/mod-ci.cxx
+++ b/mod/mod-ci.cxx
@@ -422,8 +422,10 @@ handle (request& rq, response& rs)
}
#ifdef BREP_CI_TENANT_SERVICE
-function<optional<string> (const brep::tenant_service&)> brep::ci::
-build_queued (const tenant_service&,
+function<optional<string> (const string& tenant_id,
+ const brep::tenant_service&)> brep::ci::
+build_queued (const string& /*tenant_id*/,
+ const tenant_service&,
const vector<build>& bs,
optional<build_state> initial_state,
const build_queued_hints& hints,
@@ -437,7 +439,8 @@ build_queued (const tenant_service&,
<< hints.single_package_version << ' '
<< hints.single_package_config;});
- return [&bs, initial_state] (const tenant_service& ts)
+ return [&bs, initial_state] (const string& tenant_id,
+ const tenant_service& ts)
{
optional<string> r (ts.data);
@@ -446,6 +449,7 @@ build_queued (const tenant_service&,
string s ((!initial_state
? "queued "
: "queued " + to_string (*initial_state) + ' ') +
+ tenant_id + '/' +
b.package_name.string () + '/' +
b.package_version.string () + '/' +
b.target.string () + '/' +
@@ -467,14 +471,18 @@ build_queued (const tenant_service&,
};
}
-function<optional<string> (const brep::tenant_service&)> brep::ci::
-build_building (const tenant_service&,
+function<optional<string> (const string& tenant_id,
+ const brep::tenant_service&)> brep::ci::
+build_building (const string& /*tenant_id*/,
+ const tenant_service&,
const build& b,
const diag_epilogue&) const noexcept
{
- return [&b] (const tenant_service& ts)
+ return [&b] (const string& tenant_id,
+ const tenant_service& ts)
{
string s ("building " +
+ tenant_id + '/' +
b.package_name.string () + '/' +
b.package_version.string () + '/' +
b.target.string () + '/' +
@@ -487,14 +495,17 @@ build_building (const tenant_service&,
};
}
-function<optional<string> (const brep::tenant_service&)> brep::ci::
-build_built (const tenant_service&,
+function<optional<string> (const string& tenant_id,
+ const brep::tenant_service&)> brep::ci::
+build_built (const string& /*tenant_id*/,
+ const tenant_service&,
const build& b,
const diag_epilogue&) const noexcept
{
- return [&b] (const tenant_service& ts)
+ return [&b] (const string& tenant_id, const tenant_service& ts)
{
string s ("built " +
+ tenant_id + '/' +
b.package_name.string () + '/' +
b.package_version.string () + '/' +
b.target.string () + '/' +
diff --git a/mod/mod-ci.hxx b/mod/mod-ci.hxx
index e4a343c..132b5b0 100644
--- a/mod/mod-ci.hxx
+++ b/mod/mod-ci.hxx
@@ -71,26 +71,34 @@ namespace brep
cli_options () const override {return options::ci::description ();}
#ifdef BREP_CI_TENANT_SERVICE
- virtual function<optional<string> (const tenant_service&)>
- build_queued (const tenant_service&,
+ virtual function<optional<string> (const string& tenant_id,
+ const tenant_service&)>
+ build_queued (const string& tenant_id,
+ 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&)>
- build_building (const tenant_service&,
+ virtual function<optional<string> (const string& tenant_id,
+ const tenant_service&)>
+ build_building (const string& tenant_id,
+ const tenant_service&,
const build&,
const diag_epilogue& log_writer) const noexcept override;
- virtual function<optional<string> (const tenant_service&)>
- build_built (const tenant_service&,
+ virtual function<optional<string> (const string& tenant_id,
+ const tenant_service&)>
+ build_built (const string& tenant_id,
+ const tenant_service&,
const build&,
const diag_epilogue& log_writer) const noexcept override;
#ifdef BREP_CI_TENANT_SERVICE_UNLOADED
- virtual function<optional<string> (const tenant_service&)>
- build_unloaded (tenant_service&&,
+ virtual function<optional<string> (const string& tenant_id,
+ const tenant_service&)>
+ build_unloaded (const string& tenant_id,
+ tenant_service&&,
const diag_epilogue& log_writer) const noexcept override;
#endif
#endif
diff --git a/mod/tenant-service.hxx b/mod/tenant-service.hxx
index 8ba199a..5564a56 100644
--- a/mod/tenant-service.hxx
+++ b/mod/tenant-service.hxx
@@ -74,9 +74,11 @@ namespace brep
// If the returned function is not NULL, it is called to update the
// service data. It should return the new data or nullopt if no update is
// necessary. Note: tenant_service::data passed to the callback and to the
- // returned function may not be the same. Also, the returned function may
- // be called multiple times (on transaction retries). Note that the passed
- // log_writer is valid during the calls to the returned function.
+ // returned function may not be the same. Furthermore, tenant_ids may not
+ // be the same either, in case the tenant was replaced. Also, the returned
+ // function may be called multiple times (on transaction retries). Note
+ // that the passed log_writer is valid during the calls to the returned
+ // function.
//
// The passed initial_state indicates the logical initial state and is
// either absent, `building` (interrupted), or `built` (rebuild). Note
@@ -101,8 +103,10 @@ namespace brep
bool single_package_config;
};
- virtual function<optional<string> (const tenant_service&)>
- build_queued (const tenant_service&,
+ virtual function<optional<string> (const string& tenant_id,
+ const tenant_service&)>
+ build_queued (const string& tenant_id,
+ const tenant_service&,
const vector<build>&,
optional<build_state> initial_state,
const build_queued_hints&,
@@ -112,8 +116,10 @@ namespace brep
class tenant_service_build_building: public virtual tenant_service_base
{
public:
- virtual function<optional<string> (const tenant_service&)>
- build_building (const tenant_service&,
+ virtual function<optional<string> (const string& tenant_id,
+ const tenant_service&)>
+ build_building (const string& tenant_id,
+ const tenant_service&,
const build&,
const diag_epilogue& log_writer) const noexcept = 0;
};
@@ -121,8 +127,10 @@ namespace brep
class tenant_service_build_built: public virtual tenant_service_base
{
public:
- virtual function<optional<string> (const tenant_service&)>
- build_built (const tenant_service&,
+ virtual function<optional<string> (const string& tenant_id,
+ const tenant_service&)>
+ build_built (const string& tenant_id,
+ const tenant_service&,
const build&,
const diag_epilogue& log_writer) const noexcept = 0;
};
@@ -140,8 +148,10 @@ namespace brep
class tenant_service_build_unloaded: public virtual tenant_service_base
{
public:
- virtual function<optional<string> (const tenant_service&)>
- build_unloaded (tenant_service&&,
+ virtual function<optional<string> (const string& tenant_id,
+ const tenant_service&)>
+ build_unloaded (const string& tenant_id,
+ tenant_service&&,
const diag_epilogue& log_writer) const noexcept = 0;
};