Clio develop
The XRP Ledger API server.
Loading...
Searching...
No Matches
MigratorsRegister.hpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of clio: https://github.com/XRPLF/clio
4 Copyright (c) 2024, the clio developers.
5
6 Permission to use, copy, modify, and distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#pragma once
21
22#include "data/BackendInterface.hpp"
23#include "migration/MigratiorStatus.hpp"
24#include "migration/impl/Spec.hpp"
25#include "util/Assert.hpp"
26#include "util/Concepts.hpp"
27#include "util/log/Logger.hpp"
28#include "util/newconfig/ObjectView.hpp"
29
30#include <algorithm>
31#include <array>
32#include <iterator>
33#include <memory>
34#include <optional>
35#include <ranges>
36#include <string>
37#include <string_view>
38#include <tuple>
39#include <utility>
40#include <vector>
41
42namespace migration::impl {
43
47template <typename BackendType, typename MigratorType>
48concept MigrationBackend = requires { requires std::same_as<typename MigratorType::Backend, BackendType>; };
49
50template <typename Backend, typename... MigratorType>
52
53template <typename T>
54concept HasCanBlockClio = requires(T t) {
55 { t.kCAN_BLOCK_CLIO };
56};
57
65template <typename Backend, typename... MigratorType>
66 requires AllMigratorSpec<MigratorType...>
68 static_assert(util::hasNoDuplicateNames<MigratorType...>());
69
70 util::Logger log_{"Migration"};
71 std::shared_ptr<Backend> backend_;
72
73 template <typename Migrator>
74 void
75 callMigration(std::string const& name, util::config::ObjectView const& config)
76 {
77 if (name == Migrator::kNAME) {
78 LOG(log_.info()) << "Running migration: " << name;
79 Migrator::runMigration(backend_, config);
80 backend_->writeMigratorStatus(name, MigratorStatus(MigratorStatus::Migrated).toString());
81 LOG(log_.info()) << "Finished migration: " << name;
82 }
83 }
84
85 template <typename T>
86 static constexpr std::string_view
87 getDescriptionIfMatch(std::string_view targetName)
88 {
89 return (T::kNAME == targetName) ? T::kDESCRIPTION : "";
90 }
91
92 template <typename First, typename... Rest>
93 static constexpr bool
94 canBlockClioHelper(std::string_view targetName)
95 {
96 if (targetName == First::kNAME) {
97 if constexpr (HasCanBlockClio<First>) {
98 return First::kCAN_BLOCK_CLIO;
99 }
100 return false;
101 }
102 if constexpr (sizeof...(Rest) > 0) {
103 return canBlockClioHelper<Rest...>(targetName);
104 }
105 ASSERT(false, "The migrator name is not found");
106 std::unreachable();
107 }
108
109public:
113 using BackendType = Backend;
114
120 MigratorsRegister(std::shared_ptr<BackendType> backend) : backend_{std::move(backend)}
121 {
122 }
123
130 void
131 runMigrator(std::string const& name, util::config::ObjectView const& config)
132 requires BackendMatchAllMigrators<BackendType, MigratorType...>
133 {
134 (callMigration<MigratorType>(name, config), ...);
135 }
136
143 std::vector<std::tuple<std::string, MigratorStatus>>
145 {
146 auto const fullList = getMigratorNames();
147
148 std::vector<std::tuple<std::string, MigratorStatus>> status;
149
150 std::ranges::transform(fullList, std::back_inserter(status), [&](auto const& migratorName) {
151 auto const migratorNameStr = std::string(migratorName);
152 return std::make_tuple(migratorNameStr, getMigratorStatus(migratorNameStr));
153 });
154 return status;
155 }
156
164 getMigratorStatus(std::string const& name) const
165 {
166 auto const fullList = getMigratorNames();
167 if (std::ranges::find(fullList, name) == fullList.end()) {
168 return MigratorStatus::NotKnown;
169 }
170 auto const statusStringOpt =
171 data::synchronous([&](auto yield) { return backend_->fetchMigratorStatus(name, yield); });
172
173 return statusStringOpt ? MigratorStatus::fromString(statusStringOpt.value()) : MigratorStatus::NotMigrated;
174 }
175
181 constexpr auto
183 {
184 return std::array<std::string_view, sizeof...(MigratorType)>{MigratorType::kNAME...};
185 }
186
193 std::string
194 getMigratorDescription(std::string const& name) const
195 {
196 if constexpr (sizeof...(MigratorType) == 0) {
197 return "No Description";
198 } else {
199 // Fold expression to search through all types
200 std::string const result = ([](std::string const& name) {
201 return std::string(getDescriptionIfMatch<MigratorType>(name));
202 }(name) + ...);
203
204 return result.empty() ? "No Description" : result;
205 }
206 }
207
215 std::optional<bool>
216 canMigratorBlockClio(std::string_view name) const
217 {
218 if constexpr (sizeof...(MigratorType) == 0) {
219 return std::nullopt;
220 } else {
221 auto const migratiors = getMigratorNames();
222 if (std::ranges::find(migratiors, name) == migratiors.end())
223 return std::nullopt;
224
225 return canBlockClioHelper<MigratorType...>(name);
226 }
227 }
228};
229
230} // 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:31
static MigratorStatus fromString(std::string const &statusStr)
Convert the string to status.
Definition MigratorStatus.cpp:46
The register of migrators. It will dispatch the migration to the corresponding migrator....
Definition MigratorsRegister.hpp:67
void runMigrator(std::string const &name, util::config::ObjectView const &config)
Run the migration according to the given migrator's name.
Definition MigratorsRegister.hpp:131
std::optional< bool > canMigratorBlockClio(std::string_view name) const
Return if the given migrator can block Clio server.
Definition MigratorsRegister.hpp:216
MigratorStatus getMigratorStatus(std::string const &name) const
Get the status of a migrator by its name.
Definition MigratorsRegister.hpp:164
MigratorsRegister(std::shared_ptr< BackendType > backend)
Construct a new Migrators Register object.
Definition MigratorsRegister.hpp:120
constexpr auto getMigratorNames() const
Get all registered migrators' names.
Definition MigratorsRegister.hpp:182
std::string getMigratorDescription(std::string const &name) const
Get the description of a migrator by its name.
Definition MigratorsRegister.hpp:194
std::vector< std::tuple< std::string, MigratorStatus > > getMigratorsStatus() const
Get the status of all the migrators.
Definition MigratorsRegister.hpp:144
Backend BackendType
The backend type which is used by the migrators.
Definition MigratorsRegister.hpp:113
A simple thread-safe logger for the channel specified in the constructor.
Definition Logger.hpp:111
Pump info(SourceLocationType const &loc=CURRENT_SRC_LOCATION) const
Interface for logging at Severity::NFO severity.
Definition Logger.cpp:219
Provides a view into a subset of configuration data defined by a prefix.
Definition ObjectView.hpp:40
used by variadic template to check all migrators are MigratorSpec
Definition Spec.hpp:54
Definition MigratorsRegister.hpp:51
Definition MigratorsRegister.hpp:54
Definition MigratorsRegister.hpp:48
auto synchronous(FnType &&func)
Synchronously executes the given function object inside a coroutine.
Definition BackendInterface.hpp:104
constexpr bool hasNoDuplicateNames()
Checks that the list of given type contains no duplicates.
Definition Concepts.hpp:59