mirror of
https://github.com/XRPLF/rippled.git
synced 2026-07-30 02:20:39 +00:00
FetchReport::elapsed was milliseconds, so every nodestore read rounded to zero: a warm store answers in single-digit microseconds and a cold one in low hundreds, and both became 0 ms. That difference is the whole signal separating a cold-read stall from a healthy node, and it was being discarded at the type. Database::fetchNodeObject now measures once and uses that one value for both the cumulative counter and the report, so the two can never disagree. The job-queue call still takes milliseconds and now casts explicitly. BatchWriteReport::elapsed stays milliseconds and is documented as such: a batch write covers many objects and reaches the disk, so it belongs in that range. Also adds a sub-millisecond histogram ladder, because the existing bucket edges start at 100 microseconds and put the entire warm range in bucket 0. It is not wired to a view yet: no sub-millisecond instrument exists to name, so the edges wait for the instrument that records read latency. The new test captures what the nodestore reports and asserts the reported total equals the internal microsecond accumulator exactly, plus that at least one report is not a whole number of milliseconds -- which a millisecond-typed field can never satisfy on any hardware.
56 lines
1.5 KiB
C++
56 lines
1.5 KiB
C++
#include <xrpld/app/main/NodeStoreScheduler.h>
|
|
|
|
#include <xrpl/core/Job.h>
|
|
#include <xrpl/core/JobQueue.h>
|
|
#include <xrpl/nodestore/Scheduler.h>
|
|
#include <xrpl/nodestore/Task.h>
|
|
|
|
#include <chrono>
|
|
|
|
namespace xrpl {
|
|
|
|
NodeStoreScheduler::NodeStoreScheduler(JobQueue& jobQueue) : jobQueue_(jobQueue)
|
|
{
|
|
}
|
|
|
|
void
|
|
NodeStoreScheduler::scheduleTask(node_store::Task& task)
|
|
{
|
|
if (jobQueue_.isStopped())
|
|
return;
|
|
|
|
if (!jobQueue_.addJob(JtWrite, "NObjStore", [&task]() { task.performScheduledTask(); }))
|
|
{
|
|
// Job not added, presumably because we're shutting down.
|
|
// Recover by executing the task synchronously.
|
|
task.performScheduledTask();
|
|
}
|
|
}
|
|
|
|
void
|
|
NodeStoreScheduler::onFetch(node_store::FetchReport const& report)
|
|
{
|
|
if (jobQueue_.isStopped())
|
|
return;
|
|
|
|
// The report is in microseconds but addLoadEvents takes milliseconds, so
|
|
// cast explicitly. The load monitor only tracks whole-millisecond load,
|
|
// so the sub-millisecond detail is deliberately dropped here; telemetry
|
|
// reads the microsecond value from the nodestore instead.
|
|
jobQueue_.addLoadEvents(
|
|
report.fetchType == node_store::FetchType::Async ? JtNsAsyncRead : JtNsSyncRead,
|
|
1,
|
|
std::chrono::duration_cast<std::chrono::milliseconds>(report.elapsed));
|
|
}
|
|
|
|
void
|
|
NodeStoreScheduler::onBatchWrite(node_store::BatchWriteReport const& report)
|
|
{
|
|
if (jobQueue_.isStopped())
|
|
return;
|
|
|
|
jobQueue_.addLoadEvents(JtNsWrite, report.writeCount, report.elapsed);
|
|
}
|
|
|
|
} // namespace xrpl
|