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