23#include "data/LedgerCache.hpp"
24#include "data/Types.hpp"
25#include "etl/CorruptionDetector.hpp"
26#include "util/log/Logger.hpp"
28#include <boost/asio/executor_work_guard.hpp>
29#include <boost/asio/io_context.hpp>
30#include <boost/asio/spawn.hpp>
31#include <boost/json.hpp>
32#include <boost/json/object.hpp>
33#include <boost/utility/result_of.hpp>
34#include <xrpl/basics/base_uint.h>
35#include <xrpl/protocol/AccountID.h>
36#include <xrpl/protocol/Fees.h>
37#include <xrpl/protocol/LedgerHeader.h>
44#include <shared_mutex>
62 what()
const throw()
override
64 return "Database read timed out. Please retry the request";
68static constexpr std::size_t kDEFAULT_WAIT_BETWEEN_RETRY = 500;
77template <
typename FnType>
87 LOG(log.error()) <<
"Database request timed out. Sleeping and retrying ... ";
88 std::this_thread::sleep_for(std::chrono::milliseconds(waitMs));
100template <
typename FnType>
104 boost::asio::io_context ctx;
106 using R =
typename boost::result_of<FnType(boost::asio::yield_context)>::type;
107 if constexpr (!std::is_same_v<R, void>) {
109 boost::asio::spawn(ctx, [_ = boost::asio::make_work_guard(ctx), &func, &res](
auto yield) {
116 boost::asio::spawn(ctx, [_ = boost::asio::make_work_guard(ctx), &func](
auto yield) { func(yield); });
128template <
typename FnType>
140 mutable std::shared_mutex rngMtx_;
141 std::optional<LedgerRange> range_;
143 std::optional<etl::CorruptionDetector<LedgerCache>> corruptionDetector_;
176 corruptionDetector_ = std::move(detector);
186 virtual std::optional<ripple::LedgerHeader>
196 virtual std::optional<ripple::LedgerHeader>
205 virtual std::optional<std::uint32_t>
213 std::optional<LedgerRange>
225 virtual std::vector<ripple::uint256>
226 fetchAccountRoots(std::uint32_t number, std::uint32_t pageSize, std::uint32_t seq, boost::asio::yield_context yield)
245 setRange(uint32_t min, uint32_t max,
bool force =
false);
254 std::optional<ripple::Fees>
255 fetchFees(std::uint32_t seq, boost::asio::yield_context yield)
const;
264 virtual std::optional<TransactionAndMetadata>
274 virtual std::vector<TransactionAndMetadata>
275 fetchTransactions(std::vector<ripple::uint256>
const& hashes, boost::asio::yield_context yield)
const = 0;
289 ripple::AccountID
const& account,
292 std::optional<TransactionsCursor>
const& cursor,
293 boost::asio::yield_context yield
303 virtual std::vector<TransactionAndMetadata>
313 virtual std::vector<ripple::uint256>
324 virtual std::optional<NFT>
325 fetchNFT(ripple::uint256
const& tokenID, std::uint32_t ledgerSequence, boost::asio::yield_context yield)
const = 0;
339 ripple::uint256
const& tokenID,
342 std::optional<TransactionsCursor>
const& cursorIn,
343 boost::asio::yield_context yield
359 ripple::AccountID
const& issuer,
360 std::optional<std::uint32_t>
const& taxon,
361 std::uint32_t ledgerSequence,
363 std::optional<ripple::uint256>
const& cursorIn,
364 boost::asio::yield_context yield
379 ripple::uint192
const& mptID,
380 std::uint32_t
const limit,
381 std::optional<ripple::AccountID>
const& cursorIn,
382 std::uint32_t
const ledgerSequence,
383 boost::asio::yield_context yield
398 fetchLedgerObject(ripple::uint256
const& key, std::uint32_t sequence, boost::asio::yield_context yield)
const;
410 std::optional<std::uint32_t>
411 fetchLedgerObjectSeq(ripple::uint256
const& key, std::uint32_t sequence, boost::asio::yield_context yield)
const;
426 std::vector<ripple::uint256>
const& keys,
427 std::uint32_t sequence,
428 boost::asio::yield_context yield
439 virtual std::optional<Blob>
440 doFetchLedgerObject(ripple::uint256
const& key, std::uint32_t sequence, boost::asio::yield_context yield)
const = 0;
450 virtual std::optional<std::uint32_t>
462 virtual std::vector<Blob>
464 std::vector<ripple::uint256>
const& keys,
465 std::uint32_t sequence,
466 boost::asio::yield_context yield
476 virtual std::vector<LedgerObject>
477 fetchLedgerDiff(std::uint32_t ledgerSequence, boost::asio::yield_context yield)
const = 0;
491 std::optional<ripple::uint256>
const& cursor,
492 std::uint32_t ledgerSequence,
495 boost::asio::yield_context yield
506 std::optional<LedgerObject>
507 fetchSuccessorObject(ripple::uint256 key, std::uint32_t ledgerSequence, boost::asio::yield_context yield)
const;
520 std::optional<ripple::uint256>
521 fetchSuccessorKey(ripple::uint256 key, std::uint32_t ledgerSequence, boost::asio::yield_context yield)
const;
531 virtual std::optional<ripple::uint256>
532 doFetchSuccessorKey(ripple::uint256 key, std::uint32_t ledgerSequence, boost::asio::yield_context yield)
const = 0;
545 ripple::uint256
const& book,
546 std::uint32_t ledgerSequence,
548 boost::asio::yield_context yield
558 virtual std::optional<std::string>
568 std::optional<LedgerRange>
577 virtual std::optional<LedgerRange>
585 std::optional<LedgerRange>
595 writeLedger(ripple::LedgerHeader
const& ledgerHeader, std::string&& blob) = 0;
621 std::string&& transaction,
622 std::string&& metadata
665 writeSuccessor(std::string&& key, std::uint32_t seq, std::string&& successor) = 0;
710 virtual boost::json::object
722 doWriteLedgerObject(std::string&& key, std::uint32_t seq, std::string&& blob) = 0;
730 doFinishWrites() = 0;
The interface to the database used by Clio.
Definition BackendInterface.hpp:138
void setCorruptionDetector(etl::CorruptionDetector< LedgerCache > detector)
Sets the corruption detector.
Definition BackendInterface.hpp:174
virtual std::vector< TransactionAndMetadata > fetchAllTransactionsInLedger(std::uint32_t ledgerSequence, boost::asio::yield_context yield) const =0
Fetches all transactions from a specific ledger.
std::optional< ripple::Fees > fetchFees(std::uint32_t seq, boost::asio::yield_context yield) const
Fetch the fees from a specific ledger sequence.
Definition BackendInterface.cpp:360
virtual std::vector< ripple::uint256 > fetchAccountRoots(std::uint32_t number, std::uint32_t pageSize, std::uint32_t seq, boost::asio::yield_context yield) const =0
Fetch the specified number of account root object indexes by page, the accounts need to exist for seq...
virtual bool isTooBusy() const =0
virtual void writeNFTs(std::vector< NFTsData > const &data)=0
Writes NFTs to the database.
std::vector< Blob > fetchLedgerObjects(std::vector< ripple::uint256 > const &keys, std::uint32_t sequence, boost::asio::yield_context yield) const
Fetches all ledger objects by their keys.
Definition BackendInterface.cpp:119
virtual std::optional< TransactionAndMetadata > fetchTransaction(ripple::uint256 const &hash, boost::asio::yield_context yield) const =0
Fetches a specific transaction.
void setRange(uint32_t min, uint32_t max, bool force=false)
Sets the range of sequences that are stored in the DB.
Definition BackendInterface.cpp:293
std::optional< LedgerObject > fetchSuccessorObject(ripple::uint256 key, std::uint32_t ledgerSequence, boost::asio::yield_context yield) const
Fetches the successor object.
Definition BackendInterface.cpp:169
virtual std::vector< Blob > doFetchLedgerObjects(std::vector< ripple::uint256 > const &keys, std::uint32_t sequence, boost::asio::yield_context yield) const =0
The database-specific implementation for fetching ledger objects.
virtual void startWrites() const =0
Starts a write transaction with the DB. No-op for cassandra.
virtual std::vector< ripple::uint256 > fetchAllTransactionHashesInLedger(std::uint32_t ledgerSequence, boost::asio::yield_context yield) const =0
Fetches all transaction hashes from a specific ledger.
std::optional< std::uint32_t > fetchLedgerObjectSeq(ripple::uint256 const &key, std::uint32_t sequence, boost::asio::yield_context yield) const
Fetches a specific ledger object sequence.
Definition BackendInterface.cpp:106
BookOffersPage fetchBookOffers(ripple::uint256 const &book, std::uint32_t ledgerSequence, std::uint32_t limit, boost::asio::yield_context yield) const
Fetches book offers.
Definition BackendInterface.cpp:187
virtual std::optional< LedgerRange > hardFetchLedgerRange(boost::asio::yield_context yield) const =0
Fetches the ledger range from DB.
virtual void writeLedgerObject(std::string &&key, std::uint32_t seq, std::string &&blob)
Writes a new ledger object.
Definition BackendInterface.cpp:70
virtual void writeSuccessor(std::string &&key, std::uint32_t seq, std::string &&successor)=0
Write a new successor.
virtual std::optional< std::string > fetchMigratorStatus(std::string const &migratorName, boost::asio::yield_context yield) const =0
Fetches the status of migrator by name.
virtual void waitForWritesToFinish()=0
Wait for all pending writes to finish.
std::optional< LedgerRange > hardFetchLedgerRange() const
Synchronously fetches the ledger range from DB.
Definition BackendInterface.cpp:261
virtual std::vector< TransactionAndMetadata > fetchTransactions(std::vector< ripple::uint256 > const &hashes, boost::asio::yield_context yield) const =0
Fetches multiple transactions.
LedgerCache & cache()
Definition BackendInterface.hpp:163
virtual NFTsAndCursor fetchNFTsByIssuer(ripple::AccountID const &issuer, std::optional< std::uint32_t > const &taxon, std::uint32_t ledgerSequence, std::uint32_t limit, std::optional< ripple::uint256 > const &cursorIn, boost::asio::yield_context yield) const =0
Fetches all NFTs issued by a given address.
virtual std::optional< ripple::LedgerHeader > fetchLedgerBySequence(std::uint32_t sequence, boost::asio::yield_context yield) const =0
Fetches a specific ledger by sequence number.
virtual std::optional< Blob > doFetchLedgerObject(ripple::uint256 const &key, std::uint32_t sequence, boost::asio::yield_context yield) const =0
The database-specific implementation for fetching a ledger object.
std::optional< ripple::uint256 > fetchSuccessorKey(ripple::uint256 key, std::uint32_t ledgerSequence, boost::asio::yield_context yield) const
Fetches the successor key.
Definition BackendInterface.cpp:153
std::optional< LedgerRange > hardFetchLedgerRangeNoThrow() const
Fetches the ledger range from DB retrying until no DatabaseTimeout is thrown.
Definition BackendInterface.cpp:77
virtual void writeNFTTransactions(std::vector< NFTTransactionsData > const &data)=0
Write NFTs transactions.
std::optional< LedgerRange > fetchLedgerRange() const
Fetch the current ledger range.
Definition BackendInterface.cpp:267
virtual void writeTransaction(std::string &&hash, std::uint32_t seq, std::uint32_t date, std::string &&transaction, std::string &&metadata)=0
Writes a new transaction.
bool finishWrites(std::uint32_t ledgerSequence)
Tells database we finished writing all data for a specific ledger.
Definition BackendInterface.cpp:59
virtual boost::json::object stats() const =0
virtual TransactionsAndCursor fetchNFTTransactions(ripple::uint256 const &tokenID, std::uint32_t limit, bool forward, std::optional< TransactionsCursor > const &cursorIn, boost::asio::yield_context yield) const =0
Fetches all transactions for a specific NFT.
virtual std::optional< std::uint32_t > fetchLatestLedgerSequence(boost::asio::yield_context yield) const =0
Fetches the latest ledger sequence.
virtual std::optional< NFT > fetchNFT(ripple::uint256 const &tokenID, std::uint32_t ledgerSequence, boost::asio::yield_context yield) const =0
Fetches a specific NFT.
virtual void writeAccountTransactions(std::vector< AccountTransactionsData > data)=0
Write a new set of account transactions.
virtual void writeMigratorStatus(std::string const &migratorName, std::string const &status)=0
Mark the migration status of a migrator as Migrated in the database.
virtual void writeMPTHolders(std::vector< MPTHolderData > const &data)=0
Write accounts that started holding onto a MPT.
LedgerCache const & cache() const
Definition BackendInterface.hpp:154
virtual std::vector< LedgerObject > fetchLedgerDiff(std::uint32_t ledgerSequence, boost::asio::yield_context yield) const =0
Returns the difference between ledgers.
std::optional< Blob > fetchLedgerObject(ripple::uint256 const &key, std::uint32_t sequence, boost::asio::yield_context yield) const
Fetches a specific ledger object.
Definition BackendInterface.cpp:84
LedgerPage fetchLedgerPage(std::optional< ripple::uint256 > const &cursor, std::uint32_t ledgerSequence, std::uint32_t limit, bool outOfOrder, boost::asio::yield_context yield)
Fetches a page of ledger objects, ordered by key/index.
Definition BackendInterface.cpp:306
virtual TransactionsAndCursor fetchAccountTransactions(ripple::AccountID const &account, std::uint32_t limit, bool forward, std::optional< TransactionsCursor > const &cursor, boost::asio::yield_context yield) const =0
Fetches all transactions for a specific account.
virtual std::optional< ripple::uint256 > doFetchSuccessorKey(ripple::uint256 key, std::uint32_t ledgerSequence, boost::asio::yield_context yield) const =0
Database-specific implementation of fetching the successor key.
virtual std::optional< std::uint32_t > doFetchLedgerObjectSeq(ripple::uint256 const &key, std::uint32_t sequence, boost::asio::yield_context yield) const =0
The database-specific implementation for fetching a ledger object sequence.
void updateRange(uint32_t newMax)
Updates the range of sequences that are stored in the DB.
Definition BackendInterface.cpp:274
virtual void writeLedger(ripple::LedgerHeader const &ledgerHeader, std::string &&blob)=0
Writes to a specific ledger.
virtual MPTHoldersAndCursor fetchMPTHolders(ripple::uint192 const &mptID, std::uint32_t const limit, std::optional< ripple::AccountID > const &cursorIn, std::uint32_t const ledgerSequence, boost::asio::yield_context yield) const =0
Fetches all holders' balances for a MPTIssuanceID.
virtual std::optional< ripple::LedgerHeader > fetchLedgerByHash(ripple::uint256 const &hash, boost::asio::yield_context yield) const =0
Fetches a specific ledger by hash.
Represents a database timeout error.
Definition BackendInterface.hpp:56
char const * what() const override
Definition BackendInterface.hpp:62
Cache for an entire ledger.
Definition LedgerCache.hpp:46
A helper to notify Clio operator about a corruption in the DB.
Definition CorruptionDetector.hpp:35
A simple thread-safe logger for the channel specified in the constructor.
Definition Logger.hpp:110
This namespace implements the data access layer and related components.
Definition AmendmentCenter.cpp:70
auto synchronous(FnType &&func)
Synchronously executes the given function object inside a coroutine.
Definition BackendInterface.hpp:102
auto synchronousAndRetryOnTimeout(FnType &&func)
Synchronously execute the given function object and retry until no DatabaseTimeout is thrown.
Definition BackendInterface.hpp:130
auto retryOnTimeout(FnType func, size_t waitMs=kDEFAULT_WAIT_BETWEEN_RETRY)
A helper function that catches DatabaseTimout exceptions and retries indefinitely.
Definition BackendInterface.hpp:79
Represents a page of book offer objects.
Definition Types.hpp:60
Represents a page of LedgerObjects.
Definition Types.hpp:52
Represents an array of MPTokens.
Definition Types.hpp:239
Represents a bundle of NFTs with a cursor to the next page.
Definition Types.hpp:231
Represests a bundle of transactions with metadata and a cursor to the next page.
Definition Types.hpp:164