mirror of
https://github.com/XRPLF/clio.git
synced 2026-06-04 17:26:49 +00:00
Make database reads async
* yield on db read using asio * PostgresBackend fetches multiple transactions or objects in parallel
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <etl/ETLSource.h>
|
||||
#include <rpc/Handlers.h>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace RPC {
|
||||
|
||||
std::optional<Context>
|
||||
make_WsContext(
|
||||
boost::asio::yield_context& yc,
|
||||
boost::json::object const& request,
|
||||
std::shared_ptr<BackendInterface const> const& backend,
|
||||
std::shared_ptr<SubscriptionManager> const& subscriptions,
|
||||
@@ -20,6 +23,7 @@ make_WsContext(
|
||||
std::string command = request.at("command").as_string().c_str();
|
||||
|
||||
return Context{
|
||||
yc,
|
||||
command,
|
||||
1,
|
||||
request,
|
||||
@@ -34,6 +38,7 @@ make_WsContext(
|
||||
|
||||
std::optional<Context>
|
||||
make_HttpContext(
|
||||
boost::asio::yield_context& yc,
|
||||
boost::json::object const& request,
|
||||
std::shared_ptr<BackendInterface const> const& backend,
|
||||
std::shared_ptr<SubscriptionManager> const& subscriptions,
|
||||
@@ -62,6 +67,7 @@ make_HttpContext(
|
||||
return {};
|
||||
|
||||
return Context{
|
||||
yc,
|
||||
command,
|
||||
1,
|
||||
array.at(0).as_object(),
|
||||
@@ -169,7 +175,8 @@ buildResponse(Context const& ctx)
|
||||
boost::json::object toForward = ctx.params;
|
||||
toForward["command"] = ctx.method;
|
||||
|
||||
auto res = ctx.balancer->forwardToRippled(toForward, ctx.clientIp);
|
||||
auto res =
|
||||
ctx.balancer->forwardToRippled(toForward, ctx.clientIp, ctx.yield);
|
||||
|
||||
ctx.counters.rpcForwarded(ctx.method);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define REPORTING_RPC_H_INCLUDED
|
||||
|
||||
#include <ripple/protocol/ErrorCodes.h>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/json.hpp>
|
||||
#include <backend/BackendInterface.h>
|
||||
#include <optional>
|
||||
@@ -27,6 +28,7 @@ namespace RPC {
|
||||
|
||||
struct Context
|
||||
{
|
||||
boost::asio::yield_context& yield;
|
||||
std::string method;
|
||||
std::uint32_t version;
|
||||
boost::json::object const& params;
|
||||
@@ -42,6 +44,7 @@ struct Context
|
||||
std::string clientIp;
|
||||
|
||||
Context(
|
||||
boost::asio::yield_context& yield_,
|
||||
std::string const& command_,
|
||||
std::uint32_t version_,
|
||||
boost::json::object const& params_,
|
||||
@@ -52,7 +55,8 @@ struct Context
|
||||
Backend::LedgerRange const& range_,
|
||||
Counters& counters_,
|
||||
std::string const& clientIp_)
|
||||
: method(command_)
|
||||
: yield(yield_)
|
||||
, method(command_)
|
||||
, version(version_)
|
||||
, params(params_)
|
||||
, backend(backend_)
|
||||
@@ -135,6 +139,7 @@ make_error(Error err);
|
||||
|
||||
std::optional<Context>
|
||||
make_WsContext(
|
||||
boost::asio::yield_context& yc,
|
||||
boost::json::object const& request,
|
||||
std::shared_ptr<BackendInterface const> const& backend,
|
||||
std::shared_ptr<SubscriptionManager> const& subscriptions,
|
||||
@@ -146,6 +151,7 @@ make_WsContext(
|
||||
|
||||
std::optional<Context>
|
||||
make_HttpContext(
|
||||
boost::asio::yield_context& yc,
|
||||
boost::json::object const& request,
|
||||
std::shared_ptr<BackendInterface const> const& backend,
|
||||
std::shared_ptr<SubscriptionManager> const& subscriptions,
|
||||
|
||||
@@ -32,7 +32,8 @@ getRequiredBool(boost::json::object const& request, std::string const& field)
|
||||
else
|
||||
throw InvalidParamsError("Missing field " + field);
|
||||
}
|
||||
std::optional<uint32_t>
|
||||
|
||||
std::optional<std::uint32_t>
|
||||
getUInt(boost::json::object const& request, std::string const& field)
|
||||
{
|
||||
if (!request.contains(field))
|
||||
@@ -44,18 +45,20 @@ getUInt(boost::json::object const& request, std::string const& field)
|
||||
else
|
||||
throw InvalidParamsError("Invalid field " + field + ", not uint.");
|
||||
}
|
||||
uint32_t
|
||||
|
||||
std::uint32_t
|
||||
getUInt(
|
||||
boost::json::object const& request,
|
||||
std::string const& field,
|
||||
uint32_t dfault)
|
||||
std::uint32_t const dfault)
|
||||
{
|
||||
if (auto res = getUInt(request, field))
|
||||
return *res;
|
||||
else
|
||||
return dfault;
|
||||
}
|
||||
uint32_t
|
||||
|
||||
std::uint32_t
|
||||
getRequiredUInt(boost::json::object const& request, std::string const& field)
|
||||
{
|
||||
if (auto res = getUInt(request, field))
|
||||
@@ -63,6 +66,7 @@ getRequiredUInt(boost::json::object const& request, std::string const& field)
|
||||
else
|
||||
throw InvalidParamsError("Missing field " + field);
|
||||
}
|
||||
|
||||
std::optional<std::string>
|
||||
getString(boost::json::object const& request, std::string const& field)
|
||||
{
|
||||
@@ -97,7 +101,7 @@ std::optional<ripple::STAmount>
|
||||
getDeliveredAmount(
|
||||
std::shared_ptr<ripple::STTx const> const& txn,
|
||||
std::shared_ptr<ripple::TxMeta const> const& meta,
|
||||
uint32_t ledgerSequence)
|
||||
std::uint32_t const ledgerSequence)
|
||||
{
|
||||
if (meta->hasDeliveredAmount())
|
||||
return meta->getDeliveredAmount();
|
||||
@@ -358,7 +362,7 @@ ledgerInfoFromRequest(Context const& ctx)
|
||||
if (!ledgerHash.parseHex(hashValue.as_string().c_str()))
|
||||
return Status{Error::rpcINVALID_PARAMS, "ledgerHashMalformed"};
|
||||
|
||||
lgrInfo = ctx.backend->fetchLedgerByHash(ledgerHash);
|
||||
lgrInfo = ctx.backend->fetchLedgerByHash(ledgerHash, ctx.yield);
|
||||
}
|
||||
else if (!indexValue.is_null())
|
||||
{
|
||||
@@ -370,11 +374,12 @@ ledgerInfoFromRequest(Context const& ctx)
|
||||
else
|
||||
return Status{Error::rpcINVALID_PARAMS, "ledgerIndexMalformed"};
|
||||
|
||||
lgrInfo = ctx.backend->fetchLedgerBySequence(ledgerSequence);
|
||||
lgrInfo = ctx.backend->fetchLedgerBySequence(ledgerSequence, ctx.yield);
|
||||
}
|
||||
else
|
||||
{
|
||||
lgrInfo = ctx.backend->fetchLedgerBySequence(ctx.range.maxSequence);
|
||||
lgrInfo = ctx.backend->fetchLedgerBySequence(
|
||||
ctx.range.maxSequence, ctx.yield);
|
||||
}
|
||||
|
||||
if (!lgrInfo)
|
||||
@@ -407,10 +412,11 @@ traverseOwnedNodes(
|
||||
ripple::AccountID const& accountID,
|
||||
std::uint32_t sequence,
|
||||
ripple::uint256 const& cursor,
|
||||
boost::asio::yield_context& yield,
|
||||
std::function<bool(ripple::SLE)> atOwnedNode)
|
||||
{
|
||||
if (!backend.fetchLedgerObject(
|
||||
ripple::keylet::account(accountID).key, sequence))
|
||||
ripple::keylet::account(accountID).key, sequence, yield))
|
||||
throw AccountNotFoundError(ripple::toBase58(accountID));
|
||||
auto const rootIndex = ripple::keylet::ownerDir(accountID);
|
||||
auto currentIndex = rootIndex;
|
||||
@@ -421,7 +427,8 @@ traverseOwnedNodes(
|
||||
auto start = std::chrono::system_clock::now();
|
||||
for (;;)
|
||||
{
|
||||
auto ownedNode = backend.fetchLedgerObject(currentIndex.key, sequence);
|
||||
auto ownedNode =
|
||||
backend.fetchLedgerObject(currentIndex.key, sequence, yield);
|
||||
|
||||
if (!ownedNode)
|
||||
{
|
||||
@@ -449,7 +456,7 @@ traverseOwnedNodes(
|
||||
<< ((end - start).count() / 1000000000.0);
|
||||
|
||||
start = std::chrono::system_clock::now();
|
||||
auto objects = backend.fetchLedgerObjects(keys, sequence);
|
||||
auto objects = backend.fetchLedgerObjects(keys, sequence, yield);
|
||||
end = std::chrono::system_clock::now();
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "Time loading owned entries: "
|
||||
@@ -639,13 +646,14 @@ bool
|
||||
isGlobalFrozen(
|
||||
BackendInterface const& backend,
|
||||
std::uint32_t sequence,
|
||||
ripple::AccountID const& issuer)
|
||||
ripple::AccountID const& issuer,
|
||||
boost::asio::yield_context& yield)
|
||||
{
|
||||
if (ripple::isXRP(issuer))
|
||||
return false;
|
||||
|
||||
auto key = ripple::keylet::account(issuer).key;
|
||||
auto blob = backend.fetchLedgerObject(key, sequence);
|
||||
auto blob = backend.fetchLedgerObject(key, sequence, yield);
|
||||
|
||||
if (!blob)
|
||||
return false;
|
||||
@@ -662,13 +670,14 @@ isFrozen(
|
||||
std::uint32_t sequence,
|
||||
ripple::AccountID const& account,
|
||||
ripple::Currency const& currency,
|
||||
ripple::AccountID const& issuer)
|
||||
ripple::AccountID const& issuer,
|
||||
boost::asio::yield_context& yield)
|
||||
{
|
||||
if (ripple::isXRP(currency))
|
||||
return false;
|
||||
|
||||
auto key = ripple::keylet::account(issuer).key;
|
||||
auto blob = backend.fetchLedgerObject(key, sequence);
|
||||
auto blob = backend.fetchLedgerObject(key, sequence, yield);
|
||||
|
||||
if (!blob)
|
||||
return false;
|
||||
@@ -682,7 +691,7 @@ isFrozen(
|
||||
if (issuer != account)
|
||||
{
|
||||
key = ripple::keylet::line(account, issuer, currency).key;
|
||||
blob = backend.fetchLedgerObject(key, sequence);
|
||||
blob = backend.fetchLedgerObject(key, sequence, yield);
|
||||
|
||||
if (!blob)
|
||||
return false;
|
||||
@@ -704,10 +713,11 @@ ripple::XRPAmount
|
||||
xrpLiquid(
|
||||
BackendInterface const& backend,
|
||||
std::uint32_t sequence,
|
||||
ripple::AccountID const& id)
|
||||
ripple::AccountID const& id,
|
||||
boost::asio::yield_context& yield)
|
||||
{
|
||||
auto key = ripple::keylet::account(id).key;
|
||||
auto blob = backend.fetchLedgerObject(key, sequence);
|
||||
auto blob = backend.fetchLedgerObject(key, sequence, yield);
|
||||
|
||||
if (!blob)
|
||||
return beast::zero;
|
||||
@@ -718,7 +728,7 @@ xrpLiquid(
|
||||
std::uint32_t const ownerCount = sle.getFieldU32(ripple::sfOwnerCount);
|
||||
|
||||
auto const reserve =
|
||||
backend.fetchFees(sequence)->accountReserve(ownerCount);
|
||||
backend.fetchFees(sequence, yield)->accountReserve(ownerCount);
|
||||
|
||||
auto const balance = sle.getFieldAmount(ripple::sfBalance);
|
||||
|
||||
@@ -732,9 +742,10 @@ xrpLiquid(
|
||||
ripple::STAmount
|
||||
accountFunds(
|
||||
BackendInterface const& backend,
|
||||
uint32_t sequence,
|
||||
std::uint32_t const sequence,
|
||||
ripple::STAmount const& amount,
|
||||
ripple::AccountID const& id)
|
||||
ripple::AccountID const& id,
|
||||
boost::asio::yield_context& yield)
|
||||
{
|
||||
if (!amount.native() && amount.getIssuer() == id)
|
||||
{
|
||||
@@ -743,7 +754,13 @@ accountFunds(
|
||||
else
|
||||
{
|
||||
return accountHolds(
|
||||
backend, sequence, id, amount.getCurrency(), amount.getIssuer());
|
||||
backend,
|
||||
sequence,
|
||||
id,
|
||||
amount.getCurrency(),
|
||||
amount.getIssuer(),
|
||||
true,
|
||||
yield);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -754,16 +771,17 @@ accountHolds(
|
||||
ripple::AccountID const& account,
|
||||
ripple::Currency const& currency,
|
||||
ripple::AccountID const& issuer,
|
||||
bool zeroIfFrozen)
|
||||
bool const zeroIfFrozen,
|
||||
boost::asio::yield_context& yield)
|
||||
{
|
||||
ripple::STAmount amount;
|
||||
if (ripple::isXRP(currency))
|
||||
{
|
||||
return {xrpLiquid(backend, sequence, account)};
|
||||
return {xrpLiquid(backend, sequence, account, yield)};
|
||||
}
|
||||
auto key = ripple::keylet::line(account, issuer, currency).key;
|
||||
|
||||
auto const blob = backend.fetchLedgerObject(key, sequence);
|
||||
auto const blob = backend.fetchLedgerObject(key, sequence, yield);
|
||||
|
||||
if (!blob)
|
||||
{
|
||||
@@ -774,7 +792,8 @@ accountHolds(
|
||||
ripple::SerialIter it{blob->data(), blob->size()};
|
||||
ripple::SLE sle{it, key};
|
||||
|
||||
if (zeroIfFrozen && isFrozen(backend, sequence, account, currency, issuer))
|
||||
if (zeroIfFrozen &&
|
||||
isFrozen(backend, sequence, account, currency, issuer, yield))
|
||||
{
|
||||
amount.clear(ripple::Issue(currency, issuer));
|
||||
}
|
||||
@@ -796,10 +815,11 @@ ripple::Rate
|
||||
transferRate(
|
||||
BackendInterface const& backend,
|
||||
std::uint32_t sequence,
|
||||
ripple::AccountID const& issuer)
|
||||
ripple::AccountID const& issuer,
|
||||
boost::asio::yield_context& yield)
|
||||
{
|
||||
auto key = ripple::keylet::account(issuer).key;
|
||||
auto blob = backend.fetchLedgerObject(key, sequence);
|
||||
auto blob = backend.fetchLedgerObject(key, sequence, yield);
|
||||
|
||||
if (blob)
|
||||
{
|
||||
@@ -819,17 +839,18 @@ postProcessOrderBook(
|
||||
ripple::Book const& book,
|
||||
ripple::AccountID const& takerID,
|
||||
Backend::BackendInterface const& backend,
|
||||
uint32_t ledgerSequence)
|
||||
std::uint32_t const ledgerSequence,
|
||||
boost::asio::yield_context& yield)
|
||||
{
|
||||
boost::json::array jsonOffers;
|
||||
|
||||
std::map<ripple::AccountID, ripple::STAmount> umBalance;
|
||||
|
||||
bool globalFreeze =
|
||||
isGlobalFrozen(backend, ledgerSequence, book.out.account) ||
|
||||
isGlobalFrozen(backend, ledgerSequence, book.out.account);
|
||||
isGlobalFrozen(backend, ledgerSequence, book.out.account, yield) ||
|
||||
isGlobalFrozen(backend, ledgerSequence, book.out.account, yield);
|
||||
|
||||
auto rate = transferRate(backend, ledgerSequence, book.out.account);
|
||||
auto rate = transferRate(backend, ledgerSequence, book.out.account, yield);
|
||||
|
||||
for (auto const& obj : offers)
|
||||
{
|
||||
@@ -877,7 +898,8 @@ postProcessOrderBook(
|
||||
uOfferOwnerID,
|
||||
book.out.currency,
|
||||
book.out.account,
|
||||
zeroIfFrozen);
|
||||
zeroIfFrozen,
|
||||
yield);
|
||||
|
||||
if (saOwnerFunds < beast::zero)
|
||||
saOwnerFunds.clear();
|
||||
|
||||
@@ -64,7 +64,7 @@ generatePubLedgerMessage(
|
||||
ripple::LedgerInfo const& lgrInfo,
|
||||
ripple::Fees const& fees,
|
||||
std::string const& ledgerRange,
|
||||
uint32_t txnCount);
|
||||
std::uint32_t txnCount);
|
||||
|
||||
std::variant<Status, ripple::LedgerInfo>
|
||||
ledgerInfoFromRequest(Context const& ctx);
|
||||
@@ -75,6 +75,7 @@ traverseOwnedNodes(
|
||||
ripple::AccountID const& accountID,
|
||||
std::uint32_t sequence,
|
||||
ripple::uint256 const& cursor,
|
||||
boost::asio::yield_context& yield,
|
||||
std::function<bool(ripple::SLE)> atOwnedNode);
|
||||
|
||||
std::variant<Status, std::pair<ripple::PublicKey, ripple::SecretKey>>
|
||||
@@ -90,7 +91,8 @@ bool
|
||||
isGlobalFrozen(
|
||||
BackendInterface const& backend,
|
||||
std::uint32_t seq,
|
||||
ripple::AccountID const& issuer);
|
||||
ripple::AccountID const& issuer,
|
||||
boost::asio::yield_context& yield);
|
||||
|
||||
bool
|
||||
isFrozen(
|
||||
@@ -98,14 +100,16 @@ isFrozen(
|
||||
std::uint32_t sequence,
|
||||
ripple::AccountID const& account,
|
||||
ripple::Currency const& currency,
|
||||
ripple::AccountID const& issuer);
|
||||
ripple::AccountID const& issuer,
|
||||
boost::asio::yield_context& yield);
|
||||
|
||||
ripple::STAmount
|
||||
accountFunds(
|
||||
BackendInterface const& backend,
|
||||
uint32_t sequence,
|
||||
std::uint32_t sequence,
|
||||
ripple::STAmount const& amount,
|
||||
ripple::AccountID const& id);
|
||||
ripple::AccountID const& id,
|
||||
boost::asio::yield_context& yield);
|
||||
|
||||
ripple::STAmount
|
||||
accountHolds(
|
||||
@@ -114,26 +118,31 @@ accountHolds(
|
||||
ripple::AccountID const& account,
|
||||
ripple::Currency const& currency,
|
||||
ripple::AccountID const& issuer,
|
||||
bool zeroIfFrozen = false);
|
||||
bool zeroIfFrozen,
|
||||
boost::asio::yield_context& yield);
|
||||
|
||||
ripple::Rate
|
||||
transferRate(
|
||||
BackendInterface const& backend,
|
||||
std::uint32_t sequence,
|
||||
ripple::AccountID const& issuer);
|
||||
ripple::AccountID const& issuer,
|
||||
boost::asio::yield_context& yield);
|
||||
|
||||
ripple::XRPAmount
|
||||
xrpLiquid(
|
||||
BackendInterface const& backend,
|
||||
std::uint32_t sequence,
|
||||
ripple::AccountID const& id);
|
||||
ripple::AccountID const& id,
|
||||
boost::asio::yield_context& yield);
|
||||
|
||||
boost::json::array
|
||||
postProcessOrderBook(
|
||||
std::vector<Backend::LedgerObject> const& offers,
|
||||
ripple::Book const& book,
|
||||
ripple::AccountID const& takerID,
|
||||
Backend::BackendInterface const& backend,
|
||||
uint32_t ledgerSequence);
|
||||
std::uint32_t ledgerSequence,
|
||||
boost::asio::yield_context& yield);
|
||||
|
||||
std::variant<Status, ripple::Book>
|
||||
parseBook(boost::json::object const& request);
|
||||
@@ -141,16 +150,16 @@ parseBook(boost::json::object const& request);
|
||||
std::variant<Status, ripple::AccountID>
|
||||
parseTaker(boost::json::value const& request);
|
||||
|
||||
std::optional<uint32_t>
|
||||
std::optional<std::uint32_t>
|
||||
getUInt(boost::json::object const& request, std::string const& field);
|
||||
|
||||
uint32_t
|
||||
std::uint32_t
|
||||
getUInt(
|
||||
boost::json::object const& request,
|
||||
std::string const& field,
|
||||
uint32_t dfault);
|
||||
std::uint32_t dfault);
|
||||
|
||||
uint32_t
|
||||
std::uint32_t
|
||||
getRequiredUInt(boost::json::object const& request, std::string const& field);
|
||||
|
||||
std::optional<bool>
|
||||
|
||||
@@ -122,7 +122,12 @@ doAccountChannels(Context const& context)
|
||||
};
|
||||
|
||||
auto nextCursor = traverseOwnedNodes(
|
||||
*context.backend, *accountID, lgrInfo.seq, marker, addToResponse);
|
||||
*context.backend,
|
||||
*accountID,
|
||||
lgrInfo.seq,
|
||||
marker,
|
||||
context.yield,
|
||||
addToResponse);
|
||||
|
||||
response["ledger_hash"] = ripple::strHex(lgrInfo.hash);
|
||||
response["ledger_index"] = lgrInfo.seq;
|
||||
|
||||
@@ -60,7 +60,12 @@ doAccountCurrencies(Context const& context)
|
||||
};
|
||||
|
||||
traverseOwnedNodes(
|
||||
*context.backend, *accountID, lgrInfo.seq, beast::zero, addToResponse);
|
||||
*context.backend,
|
||||
*accountID,
|
||||
lgrInfo.seq,
|
||||
beast::zero,
|
||||
context.yield,
|
||||
addToResponse);
|
||||
|
||||
response["ledger_hash"] = ripple::strHex(lgrInfo.hash);
|
||||
response["ledger_index"] = lgrInfo.seq;
|
||||
|
||||
@@ -64,7 +64,7 @@ doAccountInfo(Context const& context)
|
||||
|
||||
auto start = std::chrono::system_clock::now();
|
||||
std::optional<std::vector<unsigned char>> dbResponse =
|
||||
context.backend->fetchLedgerObject(key.key, lgrInfo.seq);
|
||||
context.backend->fetchLedgerObject(key.key, lgrInfo.seq, context.yield);
|
||||
auto end = std::chrono::system_clock::now();
|
||||
|
||||
auto time =
|
||||
@@ -103,8 +103,8 @@ doAccountInfo(Context const& context)
|
||||
|
||||
// This code will need to be revisited if in the future we
|
||||
// support multiple SignerLists on one account.
|
||||
auto const signers =
|
||||
context.backend->fetchLedgerObject(signersKey.key, lgrInfo.seq);
|
||||
auto const signers = context.backend->fetchLedgerObject(
|
||||
signersKey.key, lgrInfo.seq, context.yield);
|
||||
if (signers)
|
||||
{
|
||||
ripple::STLedgerEntry sleSigners{
|
||||
|
||||
@@ -166,7 +166,12 @@ doAccountLines(Context const& context)
|
||||
};
|
||||
|
||||
auto nextCursor = traverseOwnedNodes(
|
||||
*context.backend, *accountID, lgrInfo.seq, cursor, addToResponse);
|
||||
*context.backend,
|
||||
*accountID,
|
||||
lgrInfo.seq,
|
||||
cursor,
|
||||
context.yield,
|
||||
addToResponse);
|
||||
|
||||
if (nextCursor)
|
||||
response["marker"] = ripple::strHex(*nextCursor);
|
||||
|
||||
@@ -102,7 +102,12 @@ doAccountObjects(Context const& context)
|
||||
};
|
||||
|
||||
auto nextCursor = traverseOwnedNodes(
|
||||
*context.backend, *accountID, lgrInfo.seq, cursor, addToResponse);
|
||||
*context.backend,
|
||||
*accountID,
|
||||
lgrInfo.seq,
|
||||
cursor,
|
||||
context.yield,
|
||||
addToResponse);
|
||||
|
||||
response["ledger_hash"] = ripple::strHex(lgrInfo.hash);
|
||||
response["ledger_index"] = lgrInfo.seq;
|
||||
|
||||
@@ -128,7 +128,12 @@ doAccountOffers(Context const& context)
|
||||
};
|
||||
|
||||
auto nextCursor = traverseOwnedNodes(
|
||||
*context.backend, *accountID, lgrInfo.seq, cursor, addToResponse);
|
||||
*context.backend,
|
||||
*accountID,
|
||||
lgrInfo.seq,
|
||||
cursor,
|
||||
context.yield,
|
||||
addToResponse);
|
||||
|
||||
if (nextCursor)
|
||||
response["marker"] = ripple::strHex(*nextCursor);
|
||||
|
||||
@@ -54,7 +54,8 @@ doAccountTx(Context const& context)
|
||||
return Status{
|
||||
Error::rpcINVALID_PARAMS, "transactionIndexNotInt"};
|
||||
|
||||
transactionIndex = value_to<std::uint32_t>(obj.at("seq"));
|
||||
transactionIndex =
|
||||
boost::json::value_to<std::uint32_t>(obj.at("seq"));
|
||||
}
|
||||
|
||||
std::optional<std::uint32_t> ledgerIndex = {};
|
||||
@@ -63,7 +64,8 @@ doAccountTx(Context const& context)
|
||||
if (!obj.at("ledger").is_int64())
|
||||
return Status{Error::rpcINVALID_PARAMS, "ledgerIndexNotInt"};
|
||||
|
||||
ledgerIndex = value_to<std::uint32_t>(obj.at("ledger"));
|
||||
ledgerIndex =
|
||||
boost::json::value_to<std::uint32_t>(obj.at("ledger"));
|
||||
}
|
||||
|
||||
if (!transactionIndex || !ledgerIndex)
|
||||
@@ -124,7 +126,8 @@ doAccountTx(Context const& context)
|
||||
if (!request.at("ledger_index").is_int64())
|
||||
return Status{Error::rpcINVALID_PARAMS, "ledgerIndexNotNumber"};
|
||||
|
||||
auto ledgerIndex = value_to<uint32_t>(request.at("ledger_index"));
|
||||
auto ledgerIndex =
|
||||
boost::json::value_to<std::uint32_t>(request.at("ledger_index"));
|
||||
maxIndex = minIndex = ledgerIndex;
|
||||
}
|
||||
|
||||
@@ -139,7 +142,8 @@ doAccountTx(Context const& context)
|
||||
return RPC::Status{
|
||||
RPC::Error::rpcINVALID_PARAMS, "ledgerHashMalformed"};
|
||||
|
||||
auto lgrInfo = context.backend->fetchLedgerByHash(ledgerHash);
|
||||
auto lgrInfo =
|
||||
context.backend->fetchLedgerByHash(ledgerHash, context.yield);
|
||||
maxIndex = minIndex = lgrInfo->seq;
|
||||
}
|
||||
|
||||
@@ -167,7 +171,7 @@ doAccountTx(Context const& context)
|
||||
boost::json::array txns;
|
||||
auto start = std::chrono::system_clock::now();
|
||||
auto [blobs, retCursor] = context.backend->fetchAccountTransactions(
|
||||
*accountID, limit, forward, cursor);
|
||||
*accountID, limit, forward, cursor, context.yield);
|
||||
|
||||
auto end = std::chrono::system_clock::now();
|
||||
BOOST_LOG_TRIVIAL(info) << __func__ << " db fetch took "
|
||||
|
||||
@@ -82,8 +82,8 @@ doBookOffers(Context const& context)
|
||||
}
|
||||
|
||||
auto start = std::chrono::system_clock::now();
|
||||
auto [offers, retCursor, warning] =
|
||||
context.backend->fetchBookOffers(bookBase, lgrInfo.seq, limit, cursor);
|
||||
auto [offers, retCursor, warning] = context.backend->fetchBookOffers(
|
||||
bookBase, lgrInfo.seq, limit, cursor, context.yield);
|
||||
auto end = std::chrono::system_clock::now();
|
||||
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
@@ -93,7 +93,7 @@ doBookOffers(Context const& context)
|
||||
response["ledger_index"] = lgrInfo.seq;
|
||||
|
||||
response["offers"] = postProcessOrderBook(
|
||||
offers, book, takerID, *context.backend, lgrInfo.seq);
|
||||
offers, book, takerID, *context.backend, lgrInfo.seq, context.yield);
|
||||
|
||||
end = std::chrono::system_clock::now();
|
||||
|
||||
|
||||
@@ -145,8 +145,14 @@ doGatewayBalances(Context const& context)
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
traverseOwnedNodes(
|
||||
*context.backend, *accountID, lgrInfo.seq, beast::zero, addToResponse);
|
||||
*context.backend,
|
||||
*accountID,
|
||||
lgrInfo.seq,
|
||||
beast::zero,
|
||||
context.yield,
|
||||
addToResponse);
|
||||
|
||||
if (!sums.empty())
|
||||
{
|
||||
|
||||
@@ -85,8 +85,8 @@ doLedger(Context const& context)
|
||||
boost::json::array& jsonTxs = header.at("transactions").as_array();
|
||||
if (expand)
|
||||
{
|
||||
auto txns =
|
||||
context.backend->fetchAllTransactionsInLedger(lgrInfo.seq);
|
||||
auto txns = context.backend->fetchAllTransactionsInLedger(
|
||||
lgrInfo.seq, context.yield);
|
||||
|
||||
std::transform(
|
||||
std::move_iterator(txns.begin()),
|
||||
@@ -111,8 +111,8 @@ doLedger(Context const& context)
|
||||
}
|
||||
else
|
||||
{
|
||||
auto hashes =
|
||||
context.backend->fetchAllTransactionHashesInLedger(lgrInfo.seq);
|
||||
auto hashes = context.backend->fetchAllTransactionHashesInLedger(
|
||||
lgrInfo.seq, context.yield);
|
||||
std::transform(
|
||||
std::move_iterator(hashes.begin()),
|
||||
std::move_iterator(hashes.end()),
|
||||
@@ -128,7 +128,8 @@ doLedger(Context const& context)
|
||||
{
|
||||
header["diff"] = boost::json::value(boost::json::array_kind);
|
||||
boost::json::array& jsonDiff = header.at("diff").as_array();
|
||||
auto diff = context.backend->fetchLedgerDiff(lgrInfo.seq);
|
||||
auto diff =
|
||||
context.backend->fetchLedgerDiff(lgrInfo.seq, context.yield);
|
||||
for (auto const& obj : diff)
|
||||
{
|
||||
boost::json::object entry;
|
||||
|
||||
@@ -43,7 +43,7 @@ doLedgerData(Context const& context)
|
||||
if (!request.at("limit").is_int64())
|
||||
return Status{Error::rpcINVALID_PARAMS, "limitNotInteger"};
|
||||
|
||||
limit = value_to<int>(request.at("limit"));
|
||||
limit = boost::json::value_to<int>(request.at("limit"));
|
||||
}
|
||||
|
||||
std::optional<ripple::uint256> cursor;
|
||||
@@ -67,7 +67,8 @@ doLedgerData(Context const& context)
|
||||
|
||||
Backend::LedgerPage page;
|
||||
auto start = std::chrono::system_clock::now();
|
||||
page = context.backend->fetchLedgerPage(cursor, lgrInfo.seq, limit);
|
||||
page = context.backend->fetchLedgerPage(
|
||||
cursor, lgrInfo.seq, limit, 0, context.yield);
|
||||
|
||||
auto end = std::chrono::system_clock::now();
|
||||
|
||||
|
||||
@@ -128,7 +128,8 @@ doLedgerEntry(Context const& context)
|
||||
{
|
||||
auto directory = request.at("directory").as_object();
|
||||
std::uint64_t subIndex = directory.contains("sub_index")
|
||||
? value_to<std::uint64_t>(directory.at("sub_index"))
|
||||
? boost::json::value_to<std::uint64_t>(
|
||||
directory.at("sub_index"))
|
||||
: 0;
|
||||
|
||||
if (directory.contains("dir_root"))
|
||||
@@ -242,7 +243,8 @@ doLedgerEntry(Context const& context)
|
||||
return Status{Error::rpcINVALID_PARAMS, "malformedAccount"};
|
||||
else
|
||||
{
|
||||
std::uint32_t seq = value_to<std::uint32_t>(offer.at("seq"));
|
||||
std::uint32_t seq =
|
||||
boost::json::value_to<std::uint32_t>(offer.at("seq"));
|
||||
key = ripple::keylet::offer(*id, seq).key;
|
||||
}
|
||||
}
|
||||
@@ -342,7 +344,8 @@ doLedgerEntry(Context const& context)
|
||||
}
|
||||
|
||||
auto start = std::chrono::system_clock::now();
|
||||
auto dbResponse = context.backend->fetchLedgerObject(key, lgrInfo.seq);
|
||||
auto dbResponse =
|
||||
context.backend->fetchLedgerObject(key, lgrInfo.seq, context.yield);
|
||||
auto end = std::chrono::system_clock::now();
|
||||
auto time =
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(end - start)
|
||||
|
||||
@@ -45,14 +45,15 @@ doNoRippleCheck(Context const& context)
|
||||
return *status;
|
||||
|
||||
auto lgrInfo = std::get<ripple::LedgerInfo>(v);
|
||||
std::optional<ripple::Fees> fees =
|
||||
includeTxs ? context.backend->fetchFees(lgrInfo.seq) : std::nullopt;
|
||||
std::optional<ripple::Fees> fees = includeTxs
|
||||
? context.backend->fetchFees(lgrInfo.seq, context.yield)
|
||||
: std::nullopt;
|
||||
|
||||
boost::json::array transactions;
|
||||
|
||||
auto keylet = ripple::keylet::account(*accountID);
|
||||
auto accountObj =
|
||||
context.backend->fetchLedgerObject(keylet.key, lgrInfo.seq);
|
||||
auto accountObj = context.backend->fetchLedgerObject(
|
||||
keylet.key, lgrInfo.seq, context.yield);
|
||||
if (!accountObj)
|
||||
throw AccountNotFoundError(ripple::toBase58(*accountID));
|
||||
|
||||
@@ -90,6 +91,7 @@ doNoRippleCheck(Context const& context)
|
||||
*accountID,
|
||||
lgrInfo.seq,
|
||||
{},
|
||||
context.yield,
|
||||
[roleGateway,
|
||||
includeTxs,
|
||||
&fees,
|
||||
|
||||
@@ -30,12 +30,15 @@ doServerInfo(Context const& context)
|
||||
info["counters"].as_object()["rpc"] = context.counters.report();
|
||||
}
|
||||
|
||||
auto serverInfoRippled =
|
||||
context.balancer->forwardToRippled(context.params, context.clientIp);
|
||||
auto serverInfoRippled = context.balancer->forwardToRippled(
|
||||
context.params, context.clientIp, context.yield);
|
||||
|
||||
if (serverInfoRippled && !serverInfoRippled->contains("error"))
|
||||
response["info"].as_object()["load_factor"] = 1;
|
||||
|
||||
auto lgrInfo = context.backend->fetchLedgerBySequence(range->maxSequence);
|
||||
auto lgrInfo = context.backend->fetchLedgerBySequence(
|
||||
range->maxSequence, context.yield);
|
||||
|
||||
assert(lgrInfo.has_value());
|
||||
auto age = std::chrono::duration_cast<std::chrono::seconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
@@ -46,7 +49,7 @@ doServerInfo(Context const& context)
|
||||
validatedLgr["age"] = age;
|
||||
validatedLgr["hash"] = ripple::strHex(lgrInfo->hash);
|
||||
validatedLgr["seq"] = lgrInfo->seq;
|
||||
auto fees = context.backend->fetchFees(lgrInfo->seq);
|
||||
auto fees = context.backend->fetchFees(lgrInfo->seq, context.yield);
|
||||
assert(fees.has_value());
|
||||
validatedLgr["base_fee_xrp"] = fees->base.decimalXRP();
|
||||
validatedLgr["reserve_base_xrp"] = fees->reserve.decimalXRP();
|
||||
|
||||
@@ -35,6 +35,7 @@ validateStreams(boost::json::object const& request)
|
||||
|
||||
boost::json::object
|
||||
subscribeToStreams(
|
||||
boost::asio::yield_context& yield,
|
||||
boost::json::object const& request,
|
||||
std::shared_ptr<WsBase> session,
|
||||
SubscriptionManager& manager)
|
||||
@@ -47,7 +48,7 @@ subscribeToStreams(
|
||||
std::string s = stream.as_string().c_str();
|
||||
|
||||
if (s == "ledger")
|
||||
response = manager.subLedger(session);
|
||||
response = manager.subLedger(yield, session);
|
||||
else if (s == "transactions")
|
||||
manager.subTransactions(session);
|
||||
else if (s == "transactions_proposed")
|
||||
@@ -207,6 +208,7 @@ unsubscribeToAccountsProposed(
|
||||
|
||||
std::variant<Status, std::pair<std::vector<ripple::Book>, boost::json::array>>
|
||||
validateAndGetBooks(
|
||||
boost::asio::yield_context& yield,
|
||||
boost::json::object const& request,
|
||||
std::shared_ptr<Backend::BackendInterface const> const& backend)
|
||||
{
|
||||
@@ -245,23 +247,29 @@ validateAndGetBooks(
|
||||
takerID = std::get<ripple::AccountID>(parsed);
|
||||
}
|
||||
}
|
||||
auto getOrderBook =
|
||||
[&snapshot, &backend, &rng, &takerID](auto book) {
|
||||
auto bookBase = getBookBase(book);
|
||||
auto [offers, retCursor, warning] =
|
||||
backend->fetchBookOffers(
|
||||
bookBase, rng->maxSequence, 200, {});
|
||||
auto getOrderBook = [&snapshot, &backend, &rng, &takerID](
|
||||
auto book,
|
||||
boost::asio::yield_context& yield) {
|
||||
auto bookBase = getBookBase(book);
|
||||
auto [offers, retCursor, warning] =
|
||||
backend->fetchBookOffers(
|
||||
bookBase, rng->maxSequence, 200, {}, yield);
|
||||
|
||||
auto orderBook = postProcessOrderBook(
|
||||
offers, book, takerID, *backend, rng->maxSequence);
|
||||
std::copy(
|
||||
orderBook.begin(),
|
||||
orderBook.end(),
|
||||
std::back_inserter(snapshot));
|
||||
};
|
||||
getOrderBook(b);
|
||||
auto orderBook = postProcessOrderBook(
|
||||
offers,
|
||||
book,
|
||||
takerID,
|
||||
*backend,
|
||||
rng->maxSequence,
|
||||
yield);
|
||||
std::copy(
|
||||
orderBook.begin(),
|
||||
orderBook.end(),
|
||||
std::back_inserter(snapshot));
|
||||
};
|
||||
getOrderBook(b, yield);
|
||||
if (both)
|
||||
getOrderBook(ripple::reversed(b));
|
||||
getOrderBook(ripple::reversed(b), yield);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -322,7 +330,8 @@ doSubscribe(Context const& context)
|
||||
boost::json::array snapshot;
|
||||
if (request.contains("books"))
|
||||
{
|
||||
auto parsed = validateAndGetBooks(request, context.backend);
|
||||
auto parsed =
|
||||
validateAndGetBooks(context.yield, request, context.backend);
|
||||
if (auto status = std::get_if<Status>(&parsed))
|
||||
return *status;
|
||||
auto [bks, snap] =
|
||||
@@ -335,7 +344,7 @@ doSubscribe(Context const& context)
|
||||
boost::json::object response;
|
||||
if (request.contains("streams"))
|
||||
response = subscribeToStreams(
|
||||
request, context.session, *context.subscriptions);
|
||||
context.yield, request, context.session, *context.subscriptions);
|
||||
|
||||
if (request.contains("accounts"))
|
||||
subscribeToAccounts(request, context.session, *context.subscriptions);
|
||||
|
||||
@@ -16,7 +16,7 @@ doTransactionEntry(Context const& context)
|
||||
if (!hash.parseHex(getRequiredString(context.params, "tx_hash")))
|
||||
return Status{Error::rpcINVALID_PARAMS, "malformedTransaction"};
|
||||
|
||||
auto dbResponse = context.backend->fetchTransaction(hash);
|
||||
auto dbResponse = context.backend->fetchTransaction(hash, context.yield);
|
||||
// Note: transaction_entry is meant to only search a specified ledger for
|
||||
// the specified transaction. tx searches the entire range of history. For
|
||||
// rippled, having two separate commands made sense, as tx would use SQLite
|
||||
|
||||
@@ -37,7 +37,7 @@ doTx(Context const& context)
|
||||
if (!range)
|
||||
return Status{Error::rpcNOT_READY};
|
||||
|
||||
auto dbResponse = context.backend->fetchTransaction(hash);
|
||||
auto dbResponse = context.backend->fetchTransaction(hash, context.yield);
|
||||
if (!dbResponse)
|
||||
return Status{Error::rpcTXN_NOT_FOUND};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user