perf(litebe): change-gate the idle lite refresh worker
The background 2 s refresh worker re-queried and re-copied the whole wallet every cycle (a fresh TLS refresh plus a multi-megabyte JSON build, copies and DOM parse), even when nothing had changed, so CPU and the network never went idle. The worker now skips the full refresh and the re-publish on a cycle that is provably unchanged, while never letting the UI show stale confirmed balance or transactions: - The lite bridge keeps a monotonic mutation epoch, bumped after any command not on a read-only allow-list, so a local change made on any thread (send, shield, import, new address, encrypt/unlock/lock, console) is detected at one choke point. - Each cycle the worker runs one cheap sync probe (one connection, the mandatory block ingest) and a local height read, and refreshes only when the scanned height advanced, the mutation epoch moved, the encryption state changed, a sync is in progress, or a ~10 s heartbeat elapsed; otherwise it skips. Direct/synchronous callers are not gated. - A failed probe backs off instead of running a second sync, so a dead server is not retried back-to-back. Confirmed funds can never be stale beyond one cycle (every confirmed change advances the height or bumps the epoch); only unconfirmed mempool rows can lag up to the heartbeat, and the spend path re-queries the backend directly rather than reading the gated model. Average idle cost drops from three data connections per cycle to about one. Tests: a bridge mutation-epoch test and a worker change-gate test (skip-when-unchanged; refresh on height advance, local mutation and encryption change) against the fake backend. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -43,6 +43,7 @@ inline std::atomic<long> g_liteFakeSyncCalls{0};
|
||||
inline std::atomic<bool> g_liteFakeBadBalance{false}; // when true, "balance" returns invalid JSON
|
||||
inline std::atomic<bool> g_liteFakeSendFails{false}; // when true, "send"/"shield" return {"error":..}
|
||||
inline std::atomic<long> g_liteFakeSaveCount{0}; // counts "save" commands (persistence checks)
|
||||
inline std::atomic<unsigned long long> g_liteFakeHeight{1000}; // settable last-scanned height (C23 gate test)
|
||||
inline std::atomic<bool> g_liteFakeEncrypted{false}; // wallet-encryption state machine (encrypt/...)
|
||||
inline std::atomic<bool> g_liteFakeLocked{false}; // spending-keys-locked state
|
||||
inline std::atomic<bool> g_liteFakeBlockNew{false}; // "new" blocks (models do_save waiting on sync_lock)
|
||||
@@ -87,6 +88,7 @@ inline void resetLiteFakeCounters()
|
||||
{
|
||||
g_liteFakeAlloc = 0;
|
||||
g_liteFakeFreed = 0;
|
||||
g_liteFakeHeight = 1000;
|
||||
g_liteFakeShutdownCalled = false;
|
||||
g_liteFakeDeadServerSubstr.clear();
|
||||
g_liteFakeWarmupServerSubstr.clear();
|
||||
@@ -215,7 +217,8 @@ inline char* liteFakeExecute(const char* command, const char* args)
|
||||
if (std::strcmp(c, "list") == 0)
|
||||
return liteFakeDup("[{\"txid\":\"faketx\",\"datetime\":1700000000,\"block_height\":990,"
|
||||
"\"unconfirmed\":false,\"address\":\"zs1fakeaddr\",\"amount\":150000000,\"memo\":\"\"}]");
|
||||
if (std::strcmp(c, "height") == 0) return liteFakeDup("{\"height\":1000}");
|
||||
if (std::strcmp(c, "height") == 0)
|
||||
return liteFakeDup(("{\"height\":" + std::to_string(g_liteFakeHeight.load()) + "}").c_str());
|
||||
if (std::strcmp(c, "info") == 0)
|
||||
return liteFakeDup("{\"chain_name\":\"main\",\"version\":\"sdxl-fake\",\"latest_block_height\":1000}");
|
||||
// M4 spend/backup commands. send/shield report failure via {"error":..} (NOT an
|
||||
|
||||
Reference in New Issue
Block a user