Clio  develop
The XRP Ledger API server.
Loading...
Searching...
No Matches
Registry.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 "etl/Models.hpp"
23#include "etl/RegistryInterface.hpp"
24#include "etl/SystemState.hpp"
25
26#include <xrpl/protocol/TxFormats.h>
27
28#include <concepts>
29#include <cstdint>
30#include <functional>
31#include <string>
32#include <tuple>
33#include <type_traits>
34#include <utility>
35#include <vector>
36
37namespace etl::impl {
38
39template <typename T>
40concept HasLedgerDataHook = requires(T p) {
41 { p.onLedgerData(std::declval<model::LedgerData>()) } -> std::same_as<void>;
42};
43
44template <typename T>
45concept HasInitialDataHook = requires(T p) {
46 { p.onInitialData(std::declval<model::LedgerData>()) } -> std::same_as<void>;
47};
48
49template <typename T>
50concept HasTransactionHook = requires(T p) {
51 { p.onTransaction(uint32_t{}, std::declval<model::Transaction>()) } -> std::same_as<void>;
52};
53
54template <typename T>
55concept HasObjectHook = requires(T p) {
56 { p.onObject(uint32_t{}, std::declval<model::Object>()) } -> std::same_as<void>;
57};
58
59template <typename T>
60concept HasInitialTransactionHook = requires(T p) {
61 {
62 p.onInitialTransaction(uint32_t{}, std::declval<model::Transaction>())
63 } -> std::same_as<void>;
64};
65
66template <typename T>
67concept HasInitialObjectsHook = requires(T p) {
68 {
69 p.onInitialObjects(uint32_t{}, std::declval<std::vector<model::Object>>(), std::string{})
70 } -> std::same_as<void>;
71};
72
73template <typename T>
74concept HasInitialObjectHook = requires(T p) {
75 { p.onInitialObject(uint32_t{}, std::declval<model::Object>()) } -> std::same_as<void>;
76};
77
78template <typename T>
79concept ContainsSpec = std::decay_t<T>::spec::kSPEC_TAG;
80
81template <typename T>
86
87template <typename T>
91
92template <typename T>
94
95template <SomeExtension... Ps>
96class Registry : public RegistryInterface {
97 std::reference_wrapper<SystemState const> state_;
98 std::tuple<Ps...> store_;
99
100 static_assert(
102 "Spec must be specified when 'onTransaction' function exists."
103 );
104
105 static_assert(
107 ...),
108 "Spec must be specified when 'onInitialTransaction' function exists."
109 );
110
111public:
112 explicit constexpr Registry(SystemState const& state, SomeExtension auto&&... exts)
113 requires(std::is_same_v<std::decay_t<decltype(exts)>, std::decay_t<Ps>> and ...)
114 : state_{state}, store_(std::forward<Ps>(exts)...)
115 {
116 }
117
118 ~Registry() override = default;
119 Registry(Registry const&) = delete;
120 Registry(Registry&&) = default;
121 Registry&
122 operator=(Registry const&) = delete;
123 Registry&
124 operator=(Registry&&) = default;
125
126 constexpr void
128 {
129 // send entire batch of data at once
130 {
131 auto const expand = [&](auto& p) {
132 if constexpr (requires { p.onLedgerData(data); })
133 executeIfAllowed(p, [&data](auto& p) { p.onLedgerData(data); });
134 };
135
136 std::apply([&expand](auto&&... xs) { (expand(xs), ...); }, store_);
137 }
138
139 // send filtered transactions
140 {
141 auto const expand = [&]<typename P>(P& p, model::Transaction const& t) {
142 if constexpr (requires { p.onTransaction(data.seq, t); }) {
143 if (std::decay_t<P>::spec::wants(t.type))
144 executeIfAllowed(p, [&data, &t](auto& p) { p.onTransaction(data.seq, t); });
145 }
146 };
147
148 for (auto const& t : data.transactions) {
149 std::apply([&expand, &t](auto&&... xs) { (expand(xs, t), ...); }, store_);
150 }
151 }
152
153 // send per object path
154 {
155 auto const expand = [&]<typename P>(P&& p, model::Object const& o) {
156 if constexpr (requires { p.onObject(data.seq, o); })
157 executeIfAllowed(p, [&data, &o](auto& p) { p.onObject(data.seq, o); });
158 };
159
160 for (auto const& obj : data.objects) {
161 std::apply([&expand, &obj](auto&&... xs) { (expand(xs, obj), ...); }, store_);
162 }
163 }
164 }
165
166 constexpr void
168 uint32_t seq,
169 std::vector<model::Object> const& data,
170 std::string lastKey
171 ) override
172 {
173 // send entire vector path
174 {
175 auto const expand = [&](auto&& p) {
176 if constexpr (requires { p.onInitialObjects(seq, data, lastKey); })
177 executeIfAllowed(p, [seq, &data, &lastKey](auto& p) {
178 p.onInitialObjects(seq, data, lastKey);
179 });
180 };
181
182 std::apply([&expand](auto&&... xs) { (expand(xs), ...); }, store_);
183 }
184
185 // send per object path
186 {
187 auto const expand = [&]<typename P>(P&& p, model::Object const& o) {
188 if constexpr (requires { p.onInitialObject(seq, o); })
189 executeIfAllowed(p, [seq, &o](auto& p) { p.onInitialObject(seq, o); });
190 };
191
192 for (auto const& obj : data) {
193 std::apply([&expand, &obj](auto&&... xs) { (expand(xs, obj), ...); }, store_);
194 }
195 }
196 }
197
198 constexpr void
200 {
201 // send entire batch path
202 {
203 auto const expand = [&](auto&& p) {
204 if constexpr (requires { p.onInitialData(data); })
205 executeIfAllowed(p, [&data](auto& p) { p.onInitialData(data); });
206 };
207
208 std::apply([&expand](auto&&... xs) { (expand(xs), ...); }, store_);
209 }
210
211 // send per tx path
212 {
213 auto const expand = [&]<typename P>(P&& p, model::Transaction const& tx) {
214 if constexpr (requires { p.onInitialTransaction(data.seq, tx); }) {
215 if (std::decay_t<P>::spec::wants(tx.type))
216 executeIfAllowed(p, [&data, &tx](auto& p) {
217 p.onInitialTransaction(data.seq, tx);
218 });
219 }
220 };
221
222 for (auto const& tx : data.transactions) {
223 std::apply([&expand, &tx](auto&&... xs) { (expand(xs, tx), ...); }, store_);
224 }
225 }
226 }
227
228private:
229 void
230 executeIfAllowed(auto& p, auto&& fn)
231 {
232 if constexpr (requires { p.allowInReadonly(); }) {
233 if (state_.get().isWriting or p.allowInReadonly())
234 fn(p);
235 } else {
236 if (state_.get().isWriting)
237 fn(p);
238 }
239 }
240};
241
242static auto
243makeRegistry(SystemState const& state, auto&&... exts)
244{
245 return std::make_unique<Registry<std::decay_t<decltype(exts)>...>>(
246 state, std::forward<decltype(exts)>(exts)...
247 );
248}
249
250} // namespace etl::impl
Definition Registry.hpp:96
constexpr void dispatch(model::LedgerData const &data) override
Dispatch an entire ledger diff.
Definition Registry.hpp:127
constexpr void dispatchInitialObjects(uint32_t seq, std::vector< model::Object > const &data, std::string lastKey) override
Dispatch initial objects.
Definition Registry.hpp:167
constexpr void dispatchInitialData(model::LedgerData const &data) override
Dispatch initial ledger data.
Definition Registry.hpp:199
Definition Registry.hpp:79
Definition Registry.hpp:82
Definition Registry.hpp:45
Definition Registry.hpp:74
Definition Registry.hpp:67
Definition Registry.hpp:60
Definition Registry.hpp:40
Definition Registry.hpp:55
Definition Registry.hpp:50
Definition Registry.hpp:88
Definition Registry.hpp:93
This namespace implements the data access layer and related components.
Definition AmendmentCenter.cpp:75
The interface for a registry that can dispatch transactions and objects to extensions.
Definition RegistryInterface.hpp:73
Represents the state of the ETL subsystem.
Definition SystemState.hpp:38
Represents an entire ledger diff worth of transactions and objects.
Definition Models.hpp:143
Represents a single object on the ledger.
Definition Models.hpp:105
Represents a single transaction on the ledger.
Definition Models.hpp:71