Clio  develop
The XRP Ledger API server.
Loading...
Searching...
No Matches
MigratorsRegister.hpp
1#pragma once
2
3#include "data/BackendInterface.hpp"
4#include "migration/MigratiorStatus.hpp"
5#include "migration/impl/Spec.hpp"
6#include "util/Assert.hpp"
7#include "util/Concepts.hpp"
8#include "util/config/ObjectView.hpp"
9#include "util/log/Logger.hpp"
10
11#include <algorithm>
12#include <array>
13#include <iterator>
14#include <memory>
15#include <optional>
16#include <ranges>
17#include <string>
18#include <string_view>
19#include <tuple>
20#include <utility>
21#include <vector>
22
23namespace migration::impl {
24
28template <typename BackendType, typename MigratorType>
30 requires { requires std::same_as<typename MigratorType::Backend, BackendType>; };
31
32template <typename Backend, typename... MigratorType>
34
35template <typename T>
36concept HasCanBlockClio = requires(T t) {
37 { t.kCAN_BLOCK_CLIO };
38};
39
48template <typename Backend, typename... MigratorType>
49 requires AllMigratorSpec<MigratorType...>
51 static_assert(util::hasNoDuplicateNames<MigratorType...>());
52
53 util::Logger log_{"Migration"};
54 std::shared_ptr<Backend> backend_;
55
56 template <typename Migrator>
57 void
58 callMigration(std::string const& name, util::config::ObjectView const& config)
59 {
60 if (name == Migrator::kNAME) {
61 LOG(log_.info()) << "Running migration: " << name;
62 Migrator::runMigration(backend_, config);
63 backend_->writeMigratorStatus(
64 name, MigratorStatus(MigratorStatus::Migrated).toString()
65 );
66 LOG(log_.info()) << "Finished migration: " << name;
67 }
68 }
69
70 template <typename T>
71 static constexpr std::string_view
72 getDescriptionIfMatch(std::string_view targetName)
73 {
74 return (T::kNAME == targetName) ? T::kDESCRIPTION : "";
75 }
76
77 template <typename First, typename... Rest>
78 static constexpr bool
79 canBlockClioHelper(std::string_view targetName)
80 {
81 if (targetName == First::kNAME) {
82 if constexpr (HasCanBlockClio<First>) {
83 return First::kCAN_BLOCK_CLIO;
84 }
85 return false;
86 }
87 if constexpr (sizeof...(Rest) > 0) {
88 return canBlockClioHelper<Rest...>(targetName);
89 }
90 ASSERT(false, "The migrator name is not found");
91 std::unreachable();
92 }
93
94public:
98 using BackendType = Backend;
99
105 MigratorsRegister(std::shared_ptr<BackendType> backend) : backend_{std::move(backend)}
106 {
107 }
108
115 void
116 runMigrator(std::string const& name, util::config::ObjectView const& config)
117 requires BackendMatchAllMigrators<BackendType, MigratorType...>
118 {
119 (callMigration<MigratorType>(name, config), ...);
120 }
121
128 std::vector<std::tuple<std::string, MigratorStatus>>
130 {
131 auto const fullList = getMigratorNames();
132
133 std::vector<std::tuple<std::string, MigratorStatus>> status;
134
135 std::ranges::transform(fullList, std::back_inserter(status), [&](auto const& migratorName) {
136 auto const migratorNameStr = std::string(migratorName);
137 return std::make_tuple(migratorNameStr, getMigratorStatus(migratorNameStr));
138 });
139 return status;
140 }
141
149 getMigratorStatus(std::string const& name) const
150 {
151 auto const fullList = getMigratorNames();
152 if (std::ranges::find(fullList, name) == fullList.end()) {
153 return MigratorStatus::NotKnown;
154 }
155 auto const statusStringOpt = data::synchronous([&](auto yield) {
156 return backend_->fetchMigratorStatus(name, yield);
157 });
158
159 return statusStringOpt ? MigratorStatus::fromString(statusStringOpt.value())
160 : MigratorStatus::NotMigrated;
161 }
162
168 constexpr auto
170 {
171 return std::array<std::string_view, sizeof...(MigratorType)>{MigratorType::kNAME...};
172 }
173
180 std::string
181 getMigratorDescription(std::string const& name) const
182 {
183 if constexpr (sizeof...(MigratorType) == 0) {
184 return "No Description";
185 } else {
186 // Fold expression to search through all types
187 std::string const result = ([](std::string const& name) {
188 return std::string(getDescriptionIfMatch<MigratorType>(name));
189 }(name) + ...);
190
191 return result.empty() ? "No Description" : result;
192 }
193 }
194
202 std::optional<bool>
203 canMigratorBlockClio(std::string_view name) const
204 {
205 if constexpr (sizeof...(MigratorType) == 0) {
206 return std::nullopt;
207 } else {
208 auto const migratiors = getMigratorNames();
209 if (std::ranges::find(migratiors, name) == migratiors.end())
210 return std::nullopt;
211
212 return canBlockClioHelper<MigratorType...>(name);
213 }
214 }
215};
216
217} // namespace migration::impl
The status of a migrator, it provides the helper functions to convert the status to string and vice v...
Definition MigratiorStatus.hpp:13
static MigratorStatus fromString(std::string const &statusStr)
Convert the string to status.
Definition MigratorStatus.cpp:27
void runMigrator(std::string const &name, util::config::ObjectView const &config)
Run the migration according to the given migrator's name.
Definition MigratorsRegister.hpp:116
std::optional< bool > canMigratorBlockClio(std::string_view name) const
Return if the given migrator can block Clio server.
Definition MigratorsRegister.hpp:203
MigratorStatus getMigratorStatus(std::string const &name) const
Get the status of a migrator by its name.
Definition MigratorsRegister.hpp:149
MigratorsRegister(std::shared_ptr< BackendType > backend)
Construct a new Migrators Register object.
Definition MigratorsRegister.hpp:105
constexpr auto getMigratorNames() const
Get all registered migrators' names.
Definition MigratorsRegister.hpp:169
std::string getMigratorDescription(std::string const &name) const
Get the description of a migrator by its name.
Definition MigratorsRegister.hpp:181
std::vector< std::tuple< std::string, MigratorStatus > > getMigratorsStatus() const
Get the status of all the migrators.
Definition MigratorsRegister.hpp:129
Backend BackendType
The backend type which is used by the migrators.
Definition MigratorsRegister.hpp:98
A simple thread-safe logger for the channel specified in the constructor.
Definition Logger.hpp:77
Provides a view into a subset of configuration data defined by a prefix.
Definition ObjectView.hpp:21
used by variadic template to check all migrators are MigratorSpec
Definition Spec.hpp:35
Definition MigratorsRegister.hpp:33
Definition MigratorsRegister.hpp:36
Definition MigratorsRegister.hpp:29
auto synchronous(FnType &&func)
Synchronously executes the given function object inside a coroutine.
Definition BackendInterface.hpp:86
constexpr bool hasNoDuplicateNames()
Checks that the list of given type contains no duplicates.
Definition Concepts.hpp:40