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 "etlng/Models.hpp"
23#include "etlng/RegistryInterface.hpp"
24
25#include <xrpl/protocol/TxFormats.h>
26
27#include <concepts>
28#include <cstdint>
29#include <string>
30#include <tuple>
31#include <type_traits>
32#include <utility>
33#include <vector>
34
35namespace etlng::impl {
36
37template <typename T>
38concept HasLedgerDataHook = requires(T p) {
39 { p.onLedgerData(std::declval<etlng::model::LedgerData>()) } -> std::same_as<void>;
40};
41
42template <typename T>
43concept HasInitialDataHook = requires(T p) {
44 { p.onInitialData(std::declval<etlng::model::LedgerData>()) } -> std::same_as<void>;
45};
46
47template <typename T>
48concept HasTransactionHook = requires(T p) {
49 { p.onTransaction(uint32_t{}, std::declval<etlng::model::Transaction>()) } -> std::same_as<void>;
50};
51
52template <typename T>
53concept HasObjectHook = requires(T p) {
54 { p.onObject(uint32_t{}, std::declval<etlng::model::Object>()) } -> std::same_as<void>;
55};
56
57template <typename T>
58concept HasInitialTransactionHook = requires(T p) {
59 { p.onInitialTransaction(uint32_t{}, std::declval<etlng::model::Transaction>()) } -> std::same_as<void>;
60};
61
62template <typename T>
63concept HasInitialObjectsHook = requires(T p) {
64 {
65 p.onInitialObjects(uint32_t{}, std::declval<std::vector<etlng::model::Object>>(), std::string{})
66 } -> std::same_as<void>;
67};
68
69template <typename T>
70concept HasInitialObjectHook = requires(T p) {
71 { p.onInitialObject(uint32_t{}, std::declval<etlng::model::Object>()) } -> std::same_as<void>;
72};
73
74template <typename T>
75concept ContainsSpec = std::decay_t<T>::spec::kSPEC_TAG;
76
77template <typename T>
81
82template <typename T>
86
87template <typename T>
89
90template <SomeExtension... Ps>
92 std::tuple<Ps...> store_;
93
94 static_assert(
96 "Spec must be specified when 'onTransaction' function exists."
97 );
98
99 static_assert(
101 "Spec must be specified when 'onInitialTransaction' function exists."
102 );
103
104public:
105 explicit constexpr Registry(SomeExtension auto&&... exts)
106 requires(std::is_same_v<std::decay_t<decltype(exts)>, std::decay_t<Ps>> and ...)
107 : store_(std::forward<Ps>(exts)...)
108 {
109 }
110
111 ~Registry() override = default;
112 Registry(Registry const&) = delete;
113 Registry(Registry&&) = default;
114 Registry&
115 operator=(Registry const&) = delete;
116 Registry&
117 operator=(Registry&&) = default;
118
119 constexpr void
121 {
122 // send entire batch of data at once
123 {
124 auto const expand = [&](auto& p) {
125 if constexpr (requires { p.onLedgerData(data); }) {
126 p.onLedgerData(data);
127 }
128 };
129
130 std::apply([&expand](auto&&... xs) { (expand(xs), ...); }, store_);
131 }
132
133 // send filtered transactions
134 {
135 auto const expand = [&]<typename P>(P& p, model::Transaction const& t) {
136 if constexpr (requires { p.onTransaction(data.seq, t); }) {
137 if (std::decay_t<P>::spec::wants(t.type))
138 p.onTransaction(data.seq, t);
139 }
140 };
141
142 for (auto const& t : data.transactions) {
143 std::apply([&expand, &t](auto&&... xs) { (expand(xs, t), ...); }, store_);
144 }
145 }
146
147 // send per object path
148 {
149 auto const expand = [&]<typename P>(P&& p, model::Object const& o) {
150 if constexpr (requires { p.onObject(data.seq, o); }) {
151 p.onObject(data.seq, o);
152 }
153 };
154
155 for (auto const& obj : data.objects) {
156 std::apply([&expand, &obj](auto&&... xs) { (expand(xs, obj), ...); }, store_);
157 }
158 }
159 }
160
161 constexpr void
162 dispatchInitialObjects(uint32_t seq, std::vector<model::Object> const& data, std::string lastKey) override
163 {
164 // send entire vector path
165 {
166 auto const expand = [&](auto&& p) {
167 if constexpr (requires { p.onInitialObjects(seq, data, lastKey); }) {
168 p.onInitialObjects(seq, data, lastKey);
169 }
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 p.onInitialObject(seq, o);
180 }
181 };
182
183 for (auto const& obj : data) {
184 std::apply([&expand, &obj](auto&&... xs) { (expand(xs, obj), ...); }, store_);
185 }
186 }
187 }
188
189 constexpr void
191 {
192 // send entire batch path
193 {
194 auto const expand = [&](auto&& p) {
195 if constexpr (requires { p.onInitialData(data); }) {
196 p.onInitialData(data);
197 }
198 };
199
200 std::apply([&expand](auto&&... xs) { (expand(xs), ...); }, store_);
201 }
202
203 // send per tx path
204 {
205 auto const expand = [&]<typename P>(P&& p, model::Transaction const& tx) {
206 if constexpr (requires { p.onInitialTransaction(data.seq, tx); }) {
207 if (std::decay_t<P>::spec::wants(tx.type))
208 p.onInitialTransaction(data.seq, tx);
209 }
210 };
211
212 for (auto const& tx : data.transactions) {
213 std::apply([&expand, &tx](auto&&... xs) { (expand(xs, tx), ...); }, store_);
214 }
215 }
216 }
217};
218
219} // namespace etlng::impl
Definition Registry.hpp:91
constexpr void dispatchInitialData(model::LedgerData const &data) override
Dispatch initial ledger data.
Definition Registry.hpp:190
constexpr void dispatch(model::LedgerData const &data) override
Dispatch an entire ledger diff.
Definition Registry.hpp:120
constexpr void dispatchInitialObjects(uint32_t seq, std::vector< model::Object > const &data, std::string lastKey) override
Dispatch initial objects.
Definition Registry.hpp:162
Definition Registry.hpp:75
Definition Registry.hpp:78
Definition Registry.hpp:43
Definition Registry.hpp:70
Definition Registry.hpp:63
Definition Registry.hpp:58
Definition Registry.hpp:38
Definition Registry.hpp:53
Definition Registry.hpp:48
Definition Registry.hpp:83
Definition Registry.hpp:88
This namespace implements the data access layer and related components.
Definition AmendmentCenter.cpp:70
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