Clio  develop
The XRP Ledger API server.
Loading...
Searching...
No Matches
CursorFromFixDiffNumProvider.hpp
1#pragma once
2
3#include "data/BackendInterface.hpp"
4#include "data/Types.hpp"
5#include "etl/impl/BaseCursorProvider.hpp"
6
7#include <boost/algorithm/string/predicate.hpp>
8#include <boost/asio/io_context.hpp>
9#include <xrpl/basics/base_uint.h>
10#include <xrpl/basics/strHex.h>
11
12#include <algorithm>
13#include <cstddef>
14#include <cstdint>
15#include <iterator>
16#include <memory>
17#include <ranges>
18#include <string>
19#include <vector>
20
21namespace etl::impl {
22
23class CursorFromFixDiffNumProvider : public BaseCursorProvider {
24 std::shared_ptr<BackendInterface> backend_;
25
26 size_t numDiffs_;
27
28public:
29 CursorFromFixDiffNumProvider(std::shared_ptr<BackendInterface> backend, size_t numDiffs)
30 : backend_{std::move(backend)}, numDiffs_{numDiffs}
31 {
32 }
33
34 [[nodiscard]] std::vector<CursorPair>
35 getCursors(uint32_t const seq) const override
36 {
37 namespace rg = std::ranges;
38 namespace vs = std::views;
39
40 auto diffs = std::vector<data::LedgerObject>{};
41
42 auto const append = [](auto&& a, auto&& b) {
43 a.insert(std::end(a), std::begin(b), std::end(b));
44 };
45 auto const fetchDiff = [this, seq](uint32_t offset) {
46 return data::synchronousAndRetryOnTimeout([this, seq, offset](auto yield) {
47 return backend_->fetchLedgerDiff(seq - offset, yield);
48 });
49 };
50
51 rg::for_each(vs::iota(0u, numDiffs_), [&](auto i) { append(diffs, fetchDiff(i)); });
52 rg::sort(diffs, [](auto const& a, auto const& b) {
53 return a.key < b.key or (a.key == b.key and std::size(a.blob) < std::size(b.blob));
54 });
55
56 auto const [removalCursor, last] =
57 rg::unique(diffs, [](auto const& a, auto const& b) { return a.key == b.key; });
58 diffs.erase(removalCursor, last);
59
60 std::vector<ripple::uint256> cursors{data::kFIRST_KEY};
61 rg::copy(
62 diffs //
63 | vs::filter([](auto const& obj) { return not obj.blob.empty(); }) //
64 | vs::transform([](auto const& obj) { return obj.key; }),
65 std::back_inserter(cursors)
66 );
67 cursors.push_back(data::kLAST_KEY); // last pair should cover the remaining range
68
69 std::vector<CursorPair> pairs;
70 pairs.reserve(cursors.size());
71
72 // FIXME: this should be `cursors | vs::pairwise` (C++23)
73 std::transform(
74 std::begin(cursors),
75 std::prev(std::end(cursors)),
76 std::next(std::begin(cursors)),
77 std::back_inserter(pairs),
78 [](auto&& a, auto&& b) -> CursorPair { return {a, b}; }
79 );
80
81 return pairs;
82 }
83};
84
85} // namespace etl::impl
auto synchronousAndRetryOnTimeout(FnType &&func)
Synchronously execute the given function object and retry until no DatabaseTimeout is thrown.
Definition BackendInterface.hpp:117
Definition BaseCursorProvider.hpp:14
Definition BaseCursorProvider.hpp:9