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