feat(util): add CoalescingWriter for background file/snapshot writes

One background thread for blocking write jobs, for the settings.json /
wallets.json saves and the tx-history snapshot that later commits move
off the UI thread. Jobs are keyed (a file path, "tx-history"):

- a submit for a key that is still queued replaces that job and keeps
  its place in line (latest wins);
- keys run first in, first out, one job at a time, so two writes of one
  file never overlap and an older snapshot never lands after a newer one;
- submitAndWait() blocks until that job (or a newer one for the key) has
  run and returns its result, for writes the caller needs on disk;
- flush() waits with a bound; stop() runs everything queued, then joins;
- the thread starts on first use and sleeps when idle; with no thread
  (none could be created, or after stop()) a job runs inline.

persistFileAtomically() routes Platform::writeFileAtomically through a
writer, or writes synchronously when there is none. Nothing uses it yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-09 21:09:48 -05:00
co-authored by Claude Opus 5.5
parent cee8b9d7f6
commit 3f1194a84b
4 changed files with 487 additions and 0 deletions
+3
View File
@@ -559,6 +559,7 @@ set(APP_SOURCES
src/data/exchange_info.cpp
src/util/logger.cpp
src/util/async_task_manager.cpp
src/util/coalescing_writer.cpp
src/util/amount_format.cpp
src/util/address_validation.cpp
src/util/seed_phrase.cpp
@@ -705,6 +706,7 @@ set(APP_HEADERS
src/util/logger.h
src/util/async_task_manager.h
src/util/fetch_backoff.h
src/util/coalescing_writer.h
src/util/amount_format.h
src/util/base64.h
src/util/single_instance.h
@@ -1213,6 +1215,7 @@ if(BUILD_TESTING)
src/resources/embedded_resources.cpp
src/util/secure_vault.cpp
src/util/platform.cpp
src/util/coalescing_writer.cpp
src/util/logger.cpp
src/util/lite_server_probe.cpp
src/util/pool_registry_core.cpp