mirror of
https://github.com/XRPLF/clio.git
synced 2025-12-06 17:27:58 +00:00
feat: Block clio if migration is blocking (#1834)
Add: - Block server if migration is blocking - Initialise the migration related table when server starts against empty DB Add MigrationInspectorInterface. server uses inspector to check the migrators status.
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
#include "etl/LoadBalancer.hpp"
|
||||
#include "etl/NetworkValidatedLedgers.hpp"
|
||||
#include "feed/SubscriptionManager.hpp"
|
||||
#include "migration/MigrationInspectorFactory.hpp"
|
||||
#include "rpc/Counters.hpp"
|
||||
#include "rpc/RPCEngine.hpp"
|
||||
#include "rpc/WorkQueue.hpp"
|
||||
@@ -103,6 +104,16 @@ ClioApplication::run(bool const useNgWebServer)
|
||||
// Interface to the database
|
||||
auto backend = data::makeBackend(config_);
|
||||
|
||||
{
|
||||
auto const migrationInspector = migration::makeMigrationInspector(config_, backend);
|
||||
// Check if any migration is blocking Clio server starting.
|
||||
if (migrationInspector->isBlockingClio() and backend->hardFetchLedgerRangeNoThrow()) {
|
||||
LOG(util::LogService::error())
|
||||
<< "Existing Migration is blocking Clio, Please complete the database migration first.";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
// Manages clients subscribed to streams
|
||||
auto subscriptions = feed::SubscriptionManager::makeSubscriptionManager(config_, backend);
|
||||
|
||||
|
||||
@@ -5,4 +5,4 @@ target_sources(
|
||||
cassandra/impl/ObjectsAdapter.cpp cassandra/impl/TransactionsAdapter.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(clio_migration PRIVATE clio_util clio_etl)
|
||||
target_link_libraries(clio_migration PRIVATE clio_util clio_data)
|
||||
|
||||
65
src/migration/MigrationInspectorFactory.hpp
Normal file
65
src/migration/MigrationInspectorFactory.hpp
Normal file
@@ -0,0 +1,65 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2025, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "data/BackendInterface.hpp"
|
||||
#include "migration/MigrationInspectorInterface.hpp"
|
||||
#include "migration/MigratiorStatus.hpp"
|
||||
#include "migration/cassandra/CassandraMigrationManager.hpp"
|
||||
#include "util/Assert.hpp"
|
||||
#include "util/log/Logger.hpp"
|
||||
#include "util/newconfig/ConfigDefinition.hpp"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace migration {
|
||||
|
||||
/**
|
||||
* @brief A factory function that creates migration inspector instance and initializes the migration table if needed.
|
||||
*
|
||||
* @param config The config.
|
||||
* @param backend The backend instance. It should be initialized before calling this function.
|
||||
* @return A shared_ptr<MigrationInspectorInterface> instance
|
||||
*/
|
||||
inline std::shared_ptr<MigrationInspectorInterface>
|
||||
makeMigrationInspector(
|
||||
util::config::ClioConfigDefinition const& config,
|
||||
std::shared_ptr<BackendInterface> const& backend
|
||||
)
|
||||
{
|
||||
ASSERT(backend != nullptr, "Backend is not initialized");
|
||||
|
||||
auto inspector = std::make_shared<migration::cassandra::CassandraMigrationInspector>(backend);
|
||||
|
||||
// Database is empty, we need to initialize the migration table if it is a writeable backend
|
||||
if (not config.get<bool>("read_only") and not backend->hardFetchLedgerRangeNoThrow()) {
|
||||
migration::MigratorStatus migrated(migration::MigratorStatus::Migrated);
|
||||
for (auto const& name : inspector->allMigratorsNames()) {
|
||||
backend->writeMigratorStatus(name, migrated.toString());
|
||||
}
|
||||
}
|
||||
return inspector;
|
||||
}
|
||||
|
||||
} // namespace migration
|
||||
79
src/migration/MigrationInspectorInterface.hpp
Normal file
79
src/migration/MigrationInspectorInterface.hpp
Normal file
@@ -0,0 +1,79 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2025, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "migration/MigratiorStatus.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
namespace migration {
|
||||
|
||||
/**
|
||||
* @brief The interface for the migration inspector.The Clio server application will use this interface to inspect
|
||||
* the migration status.
|
||||
*/
|
||||
struct MigrationInspectorInterface {
|
||||
virtual ~MigrationInspectorInterface() = default;
|
||||
|
||||
/**
|
||||
* @brief Get the status of all the migrators
|
||||
* @return A vector of tuple, the first element is the migrator's name, the second element is the status of the
|
||||
*/
|
||||
virtual std::vector<std::tuple<std::string, MigratorStatus>>
|
||||
allMigratorsStatusPairs() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Get all registered migrators' names
|
||||
*
|
||||
* @return A vector of migrators' names
|
||||
*/
|
||||
virtual std::vector<std::string>
|
||||
allMigratorsNames() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Get the status of a migrator by its name
|
||||
*
|
||||
* @param name The migrator's name
|
||||
* @return The status of the migrator
|
||||
*/
|
||||
virtual MigratorStatus
|
||||
getMigratorStatusByName(std::string const& name) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Get the description of a migrator by its name
|
||||
*
|
||||
* @param name The migrator's name
|
||||
* @return The description of the migrator
|
||||
*/
|
||||
virtual std::string
|
||||
getMigratorDescriptionByName(std::string const& name) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Return if Clio server is blocked
|
||||
*
|
||||
* @return True if Clio server is blocked by migration, false otherwise
|
||||
*/
|
||||
virtual bool
|
||||
isBlockingClio() const = 0;
|
||||
};
|
||||
|
||||
} // namespace migration
|
||||
@@ -19,59 +19,23 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "migration/MigratiorStatus.hpp"
|
||||
#include "migration/MigrationInspectorInterface.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
namespace migration {
|
||||
|
||||
/**
|
||||
* @brief The interface for the migration manager. This interface is tend to be implemented for specific database. The
|
||||
* application layer will use this interface to run the migrations.
|
||||
* @brief The interface for the migration manager. The migration application layer will use this interface to run the
|
||||
* migrations. Unlike the MigrationInspectorInterface which only provides the status of migration, this interface
|
||||
* contains the acutal migration running method.
|
||||
*/
|
||||
struct MigrationManagerInterface {
|
||||
virtual ~MigrationManagerInterface() = default;
|
||||
|
||||
struct MigrationManagerInterface : virtual public MigrationInspectorInterface {
|
||||
/**
|
||||
* @brief Run the the migration according to the given migrator's name
|
||||
*/
|
||||
virtual void
|
||||
runMigration(std::string const&) = 0;
|
||||
|
||||
/**
|
||||
* @brief Get the status of all the migrators
|
||||
* @return A vector of tuple, the first element is the migrator's name, the second element is the status of the
|
||||
*/
|
||||
virtual std::vector<std::tuple<std::string, MigratorStatus>>
|
||||
allMigratorsStatusPairs() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Get all registered migrators' names
|
||||
*
|
||||
* @return A vector of migrators' names
|
||||
*/
|
||||
virtual std::vector<std::string>
|
||||
allMigratorsNames() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Get the status of a migrator by its name
|
||||
*
|
||||
* @param name The migrator's name
|
||||
* @return The status of the migrator
|
||||
*/
|
||||
virtual MigratorStatus
|
||||
getMigratorStatusByName(std::string const& name) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Get the description of a migrator by its name
|
||||
*
|
||||
* @param name The migrator's name
|
||||
* @return The description of the migrator
|
||||
*/
|
||||
virtual std::string
|
||||
getMigratorDescriptionByName(std::string const& name) const = 0;
|
||||
};
|
||||
|
||||
} // namespace migration
|
||||
|
||||
@@ -40,9 +40,11 @@ A migrator satisfies the `MigratorSpec`(impl/Spec.hpp) concept.
|
||||
|
||||
It contains:
|
||||
|
||||
- A `name` which will be used to identify the migrator. User will refer this migrator in command-line tool by this name. The name needs to be different with other migrators, otherwise a compilation error will be raised.
|
||||
- A `kNAME` which will be used to identify the migrator. User will refer this migrator in command-line tool by this name. The name needs to be different with other migrators, otherwise a compilation error will be raised.
|
||||
|
||||
- A `description` which is the detail information of the migrator.
|
||||
- A `kDESCRIPTION` which is the detail information of the migrator.
|
||||
|
||||
- An optional `kCAN_BLOCK_CLIO` which indicates whether the migrator can block the Clio server. If it's absent, the migrator can't block server. If there is a blocking migrator not completed, the Clio server will fail to start.
|
||||
|
||||
- A static function `runMigration`, it will be called when user run `--migrate name`. It accepts two parameters: backend, which provides the DB operations interface, and cfg, which provides migration-related configuration. Each migrator can have its own configuration under `.migration` session.
|
||||
|
||||
@@ -65,8 +67,8 @@ Most indexes are based on either ledger states or transactions. We provide the `
|
||||
If you need to do full scan against other table, you can follow below steps:
|
||||
- Describe the table which needs full scan in a struct. It has to satisfy the `TableSpec`(cassandra/Spec.hpp) concept, containing static member:
|
||||
- Tuple type `Row`, it's the type of each field in a row. The order of types should match what database will return in a row. Key types should come first, followed by other field types sorted in alphabetical order.
|
||||
- `PARTITION_KEY`, it's the name of the partition key of the table.
|
||||
- `TABLE_NAME`
|
||||
- `kPARTITION_KEY`, it's the name of the partition key of the table.
|
||||
- `kTABLE_NAME`
|
||||
|
||||
- Inherent from `FullTableScannerAdapterBase`.
|
||||
- Implement `onRowRead`, its parameter is the `Row` we defined. It's the callback function when a row is read.
|
||||
|
||||
@@ -19,20 +19,32 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "data/BackendInterface.hpp"
|
||||
#include "migration/cassandra/CassandraMigrationBackend.hpp"
|
||||
#include "migration/impl/MigrationInspectorBase.hpp"
|
||||
#include "migration/impl/MigrationManagerBase.hpp"
|
||||
#include "migration/impl/MigratorsRegister.hpp"
|
||||
|
||||
namespace migration::cassandra {
|
||||
namespace {
|
||||
|
||||
// Register migrators here
|
||||
// MigratorsRegister<BackendType, ExampleMigrator>
|
||||
template <typename BackendType>
|
||||
using CassandraSupportedMigrators = migration::impl::MigratorsRegister<BackendType>;
|
||||
|
||||
// Register with MigrationBackend which proceeds the migration
|
||||
using MigrationProcesser = CassandraSupportedMigrators<CassandraMigrationBackend>;
|
||||
// Instantiates with the backend which supports actual migration running
|
||||
using MigrationProcesser = CassandraSupportedMigrators<migration::cassandra::CassandraMigrationBackend>;
|
||||
|
||||
// Instantiates with backend interface, it doesn't support actual migration. But it can be used to inspect the migrators
|
||||
// status
|
||||
using MigrationQuerier = CassandraSupportedMigrators<data::BackendInterface>;
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace migration::cassandra {
|
||||
|
||||
using CassandraMigrationInspector = migration::impl::MigrationInspectorBase<MigrationQuerier>;
|
||||
|
||||
// The Cassandra migration manager
|
||||
using CassandraMigrationManager = migration::impl::MigrationManagerBase<MigrationProcesser>;
|
||||
|
||||
} // namespace migration::cassandra
|
||||
|
||||
121
src/migration/impl/MigrationInspectorBase.hpp
Normal file
121
src/migration/impl/MigrationInspectorBase.hpp
Normal file
@@ -0,0 +1,121 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2025, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "migration/MigrationInspectorInterface.hpp"
|
||||
#include "migration/MigratiorStatus.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <ranges>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
namespace migration::impl {
|
||||
|
||||
/**
|
||||
* @brief The migration inspector implementation for Cassandra. It will report the migration status for Cassandra
|
||||
* database.
|
||||
*
|
||||
* @tparam SupportedMigrators The migrators resgister that contains all the migrators
|
||||
*/
|
||||
template <typename SupportedMigrators>
|
||||
class MigrationInspectorBase : virtual public MigrationInspectorInterface {
|
||||
protected:
|
||||
SupportedMigrators migrators_;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new Cassandra Migration Inspector object
|
||||
*
|
||||
* @param backend The backend of the Cassandra database
|
||||
*/
|
||||
explicit MigrationInspectorBase(std::shared_ptr<typename SupportedMigrators::BackendType> backend)
|
||||
: migrators_{std::move(backend)}
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the status of all the migrators
|
||||
*
|
||||
* @return A vector of tuple, the first element is the migrator's name, the second element is the status of the
|
||||
* migrator
|
||||
*/
|
||||
std::vector<std::tuple<std::string, MigratorStatus>>
|
||||
allMigratorsStatusPairs() const override
|
||||
{
|
||||
return migrators_.getMigratorsStatus();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the status of a migrator by its name
|
||||
*
|
||||
* @param name The name of the migrator
|
||||
* @return The status of the migrator
|
||||
*/
|
||||
MigratorStatus
|
||||
getMigratorStatusByName(std::string const& name) const override
|
||||
{
|
||||
return migrators_.getMigratorStatus(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get all registered migrators' names
|
||||
*
|
||||
* @return A vector of string, the names of all the migrators
|
||||
*/
|
||||
std::vector<std::string>
|
||||
allMigratorsNames() const override
|
||||
{
|
||||
auto const names = migrators_.getMigratorNames();
|
||||
return std::vector<std::string>{names.begin(), names.end()};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the description of a migrator by its name
|
||||
*
|
||||
* @param name The name of the migrator
|
||||
* @return The description of the migrator
|
||||
*/
|
||||
std::string
|
||||
getMigratorDescriptionByName(std::string const& name) const override
|
||||
{
|
||||
return migrators_.getMigratorDescription(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return if there is uncomplete migrator blocking the server
|
||||
*
|
||||
* @return True if server is blocked, false otherwise
|
||||
*/
|
||||
bool
|
||||
isBlockingClio() const override
|
||||
{
|
||||
return std::ranges::any_of(migrators_.getMigratorNames(), [&](auto const& migrator) {
|
||||
if (auto canBlock = migrators_.canMigratorBlockClio(migrator); canBlock.has_value() and *canBlock and
|
||||
migrators_.getMigratorStatus(std::string(migrator)) == MigratorStatus::Status::NotMigrated) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace migration::impl
|
||||
@@ -20,14 +20,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "migration/MigrationManagerInterface.hpp"
|
||||
#include "migration/MigratiorStatus.hpp"
|
||||
#include "migration/impl/MigrationInspectorBase.hpp"
|
||||
#include "util/newconfig/ObjectView.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace migration::impl {
|
||||
|
||||
@@ -38,8 +36,7 @@ namespace migration::impl {
|
||||
* @tparam SupportedMigrators The migrators resgister that contains all the migrators
|
||||
*/
|
||||
template <typename SupportedMigrators>
|
||||
class MigrationManagerBase : public MigrationManagerInterface {
|
||||
SupportedMigrators migrators_;
|
||||
class MigrationManagerBase : public MigrationManagerInterface, public MigrationInspectorBase<SupportedMigrators> {
|
||||
// contains only migration related settings
|
||||
util::config::ObjectView config_;
|
||||
|
||||
@@ -54,7 +51,7 @@ public:
|
||||
std::shared_ptr<typename SupportedMigrators::BackendType> backend,
|
||||
util::config::ObjectView config
|
||||
)
|
||||
: migrators_{backend}, config_{std::move(config)}
|
||||
: MigrationInspectorBase<SupportedMigrators>{std::move(backend)}, config_{std::move(config)}
|
||||
{
|
||||
}
|
||||
|
||||
@@ -66,55 +63,7 @@ public:
|
||||
void
|
||||
runMigration(std::string const& name) override
|
||||
{
|
||||
migrators_.runMigrator(name, config_);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the status of all the migrators
|
||||
*
|
||||
* @return A vector of tuple, the first element is the migrator's name, the second element is the status of the
|
||||
* migrator
|
||||
*/
|
||||
std::vector<std::tuple<std::string, MigratorStatus>>
|
||||
allMigratorsStatusPairs() const override
|
||||
{
|
||||
return migrators_.getMigratorsStatus();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the status of a migrator by its name
|
||||
*
|
||||
* @param name The name of the migrator
|
||||
* @return The status of the migrator
|
||||
*/
|
||||
MigratorStatus
|
||||
getMigratorStatusByName(std::string const& name) const override
|
||||
{
|
||||
return migrators_.getMigratorStatus(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get all registered migrators' names
|
||||
*
|
||||
* @return A vector of string, the names of all the migrators
|
||||
*/
|
||||
std::vector<std::string>
|
||||
allMigratorsNames() const override
|
||||
{
|
||||
auto const names = migrators_.getMigratorNames();
|
||||
return std::vector<std::string>{names.begin(), names.end()};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the description of a migrator by its name
|
||||
*
|
||||
* @param name The name of the migrator
|
||||
* @return The description of the migrator
|
||||
*/
|
||||
std::string
|
||||
getMigratorDescriptionByName(std::string const& name) const override
|
||||
{
|
||||
return migrators_.getMigratorDescription(name);
|
||||
this->migrators_.runMigrator(name, config_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "data/BackendInterface.hpp"
|
||||
#include "migration/MigratiorStatus.hpp"
|
||||
#include "migration/impl/Spec.hpp"
|
||||
#include "util/Assert.hpp"
|
||||
#include "util/Concepts.hpp"
|
||||
#include "util/log/Logger.hpp"
|
||||
#include "util/newconfig/ObjectView.hpp"
|
||||
@@ -30,10 +31,12 @@
|
||||
#include <array>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <ranges>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace migration::impl {
|
||||
@@ -47,6 +50,11 @@ concept MigrationBackend = requires { requires std::same_as<typename MigratorTyp
|
||||
template <typename Backend, typename... MigratorType>
|
||||
concept BackendMatchAllMigrators = (MigrationBackend<Backend, MigratorType> && ...);
|
||||
|
||||
template <typename T>
|
||||
concept HasCanBlockClio = requires(T t) {
|
||||
{ t.kCAN_BLOCK_CLIO };
|
||||
};
|
||||
|
||||
/**
|
||||
*@brief The register of migrators. It will dispatch the migration to the corresponding migrator. It also
|
||||
*hold the shared pointer of backend, which is used by the migrators.
|
||||
@@ -81,6 +89,23 @@ class MigratorsRegister {
|
||||
return (T::kNAME == targetName) ? T::kDESCRIPTION : "";
|
||||
}
|
||||
|
||||
template <typename First, typename... Rest>
|
||||
static constexpr bool
|
||||
canBlockClioHelper(std::string_view targetName)
|
||||
{
|
||||
if (targetName == First::kNAME) {
|
||||
if constexpr (HasCanBlockClio<First>) {
|
||||
return First::kCAN_BLOCK_CLIO;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if constexpr (sizeof...(Rest) > 0) {
|
||||
return canBlockClioHelper<Rest...>(targetName);
|
||||
}
|
||||
ASSERT(false, "The migrator name is not found");
|
||||
std::unreachable();
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief The backend type which is used by the migrators
|
||||
@@ -179,6 +204,27 @@ public:
|
||||
return result.empty() ? "No Description" : result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return if the given migrator can block Clio server
|
||||
*
|
||||
* @param name The migrator's name
|
||||
* @return std::nullopt if the migrator name is not found, or a boolean value indicating whether the migrator is
|
||||
* blocking Clio server.
|
||||
*/
|
||||
std::optional<bool>
|
||||
canMigratorBlockClio(std::string_view name) const
|
||||
{
|
||||
if constexpr (sizeof...(MigratorType) == 0) {
|
||||
return std::nullopt;
|
||||
} else {
|
||||
auto const migratiors = getMigratorNames();
|
||||
if (std::ranges::find(migratiors, name) == migratiors.end())
|
||||
return std::nullopt;
|
||||
|
||||
return canBlockClioHelper<MigratorType...>(name);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace migration::impl
|
||||
|
||||
Reference in New Issue
Block a user