upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbitflash-maintainer <noreply@bitflash.invalid>2026-08-23 11:56:31 +0000
committerbitflash-maintainer <noreply@bitflash.invalid>2026-08-23 11:56:31 +0000
commit991853fa55a749d28d6f9e507ce72b289df92785 (patch)
tree97fa0b3fe2d4140392653a05398ae620eac1b881 /src
parent111fb886c2a38c8ab76fd064c9dbb1f403fde7c1 (diff)
payout: qualify the single-writer claim for pool_status.json
The comment justifying the absence of a version guard said RefreshStats "runs only on the event loop". That was true when it was written and is no longer: the payout-ledger self-test drives RefreshStats directly, to check that no payout mutex is held across the write. The conclusion still holds -- the test calls it from one thread at a time with the pool not running, so pool_status.json still has a single writer -- but the reason a reader would check is now stated, along with what would invalidate it. A claim in a comment that has quietly stopped being true is how 33f2e8a came to assert that no thread waits on I/O holding gPayoutLedgerMutex on the commit that made it do so. Property: comment only.
Diffstat (limited to 'src')
-rw-r--r--src/rpc.cpp17
1 files changed, 12 insertions, 5 deletions
diff --git a/src/rpc.cpp b/src/rpc.cpp
index 79947df..7a6b6a4 100644
--- a/src/rpc.cpp
+++ b/src/rpc.cpp
@@ -2429,11 +2429,18 @@ static std::string SerializePoolStatusLocked()
2429// Publish the operator status file. Call with every payout mutex released. 2429// Publish the operator status file. Call with every payout mutex released.
2430// 2430//
2431// Still no version guard and no write mutex, deliberately, and the split does 2431// Still no version guard and no write mutex, deliberately, and the split does
2432// not change the argument: RefreshStats remains the only caller, it still runs 2432// not change the argument: RefreshStats remains the only caller of either
2433// only on the event loop, and it now calls this after leaving the scope that 2433// half, in production it runs only on the event loop, and it now calls this
2434// serialised -- so the serialise and the write stay strictly ordered on one 2434// after leaving the scope that serialised -- so the serialise and the write
2435// thread and pool_status.json still has a single writer by construction. It 2435// stay strictly ordered on one thread and pool_status.json still has a single
2436// shares WriteFileAtomic so the durability rules stay in one place. 2436// writer by construction. It shares WriteFileAtomic so the durability rules
2437// stay in one place.
2438//
2439// "In production" is doing real work in that sentence. The payout-ledger
2440// self-test also calls RefreshStats, from one thread at a time and with the
2441// pool not running, which is why it is still a single writer there too. A
2442// second concurrent caller anywhere would invalidate this paragraph and want
2443// the same versioned publish the ledgers use.
2437static void PublishPoolStatus(const std::string& blob) 2444static void PublishPoolStatus(const std::string& blob)
2438{ 2445{
2439 WriteFileAtomic(PoolStatusFilePath(), blob, "pool status"); 2446 WriteFileAtomic(PoolStatusFilePath(), blob, "pool status");