node, cli, database, metrics: thread process Io through instead of global_single_threaded - #977
Open
GrapeBaBa wants to merge 3 commits into
Open
node, cli, database, metrics: thread process Io through instead of global_single_threaded#977GrapeBaBa wants to merge 3 commits into
GrapeBaBa wants to merge 3 commits into
Conversation
…le_threaded
std.Io.Threaded.global_single_threaded is documented for debugging ("most code
should avoid referencing this declaration") and does not support concurrency or
cancelation. Thread the process Io (main's init.io, already used for the
ThreadPool) through to the entrypoint components instead of hardcoding the
debugging global:
- ApiServer / MetricsServer: take + store an io: std.Io, use it in run() /
handleSSEEvents().
- database.Db.open / openBackend + warnIfOtherBackendPopulated: take io.
- BeamNode / Node.init: take + store io; use it in wipeAndReopenDb; the lean
node's ThreadPool.init now uses the threaded io too (consistent with the
beam-branch pool).
All call sites updated. Behavior is identical: every converted use is plain
blocking I/O and the API/metrics servers remain serial accept-loops on their
own threads. Test/debug code keeps the explicit global, which is its intended use.
NOT yet threaded (tracked follow-up, see commit body): the checkpoint-sync HTTP
client (downloadCheckpointState / checkpoint fetch — real outbound network where
timeouts/cancellation matter, needs new signatures on those free fns), the
DB-backend-internal open (rocksdb/lmdb), and the deeper library packages
(utils/fs, state-transition, network, metrics, key-manager, api/event_broadcaster)
which also reference the global.
Validated: zig build green.
…init Continue replacing the debugging std.Io.Threaded.global_single_threaded with the threaded process Io for the remaining HIGH-VALUE production sites: - node.zig downloadCheckpointState / downloadAndStoreCheckpointBlock: take io: std.Io; the std.http.Client now uses the threaded Io (real outbound network — timeouts/cancellation belong on a proper Io). Threaded from the lean Node's io. - metrics.init + api.init: take io: std.Io, threaded from main's init.io / the node's io. Test-only callers pass the global explicitly (retained). Deliberately LEFT on a default Io (NOT threaded — pervasive blocking primitives; threading to every call site is a whole-codebase cascade for ~zero benefit, as these need neither concurrency nor cancellation): - utils/sync SyncMutex, utils/log logger, utils/time sleepNs (16 callers), key-manager, api/event_broadcaster defaultIo() accessors. Also left (low value / deep cascade): network/ethlibp2p deserialization-dump dir (debug-only, would route through the gossip-handler layers) and utils/fs readFileToEndAlloc -> loadFromYAMLFile (~8 sites + 3 CLI helpers). Net: every production site where Io behavior actually matters (servers, DB, node pool, checkpoint HTTP, metrics) now uses the threaded process Io; the debugging global remains only behind deliberate blocking-primitive defaults and test code. Validated: zig build green.
…stalled process Io `std.Io.Threaded.global_single_threaded` is documented debug-only — "most code should avoid referencing this declaration entirely." The first two commits threaded the process Io through the entrypoint components (servers, DB, node, checkpoint HTTP, metrics). This removes the global from the remaining LEAF sites that cannot practically take an `io` parameter. Mechanism: a single deliberate process `Io` (`pkgs/utils/src/process_io.zig`), installed once from `main`'s `init.io` as the first statement of `mainInner` (before any worker threads spawn). The leaf primitives' `defaultIo()` helpers and inline sites now call `process_io.get()`. The installed value is the real process Io (a worker-capable `Threaded`), NOT a single-threaded instance; a zeam-owned local fallback covers tests / pre-install bootstrap. Sites repointed (all blocking primitives / leaf code): - utils: `SyncMutex`/`RwLock` (`sync.zig` defaultIo), logger (`log.zig`), `sleepNs` (`time.zig`), fs helpers (`fs.zig` production paths). - key-manager `defaultIo`, api/event_broadcaster `defaultIo`. - network/ethlibp2p deserialization-dump dir. - database rocksdb/lmdb backend `open`. - node/locking connected-peers RNG (`std.Random.IoSource`). After this, NO production code references `global_single_threaded` — only `test` blocks, `setupTestPrimitives`, and `tools`/`spectest`/`stress` retain it (their intended debug/test use). Validated: zig build green.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Remove every production reference to
std.Io.Threaded.global_single_threadedand route all of it through the processIo.global_single_threadedis documented debug-only — "In general… library code should accept anIoparameter rather than accessing this declaration. Most code should avoid referencing this declaration entirely… This instance does not support concurrency or cancelation." It should not appear in production code regardless of whether the behavior happens to be equivalent.Approach (two layers)
1. App/entrypoint components take an explicit
io: std.Io(threaded frommain'sinit.io, which already backs theThreadPool):ApiServer/MetricsServer(io field, used inrun()/handleSSEEvents()).database.Db.open/openBackend(+warnIfOtherBackendPopulated).BeamNode/Node.init(io field;wipeAndReopenDb; the lean node's ownThreadPool.init).downloadCheckpointState/downloadAndStoreCheckpointBlock) — real outbound network.metrics.init/api.init.2. Leaf blocking primitives that can't practically take an
ioparam use a single deliberate processIo—pkgs/utils/src/process_io.zig, installed once frominit.ioas the first statement ofmainInner(before any worker thread spawns; written-once-before-reads):utilsSyncMutex/RwLock, logger,sleepNs, fs helpers.key-manager,api/event_broadcaster,network/ethlibp2p(debug dump),databaserocksdb/lmdb backendopen,node/lockingconnected-peers RNG.The installed value is the real process
Io(a worker-capableThreaded), not a single-threaded instance. A zeam-owned local fallback covers tests / pre-install bootstrap.Result
grep -rn global_single_threaded pkgs/shows no production references — onlytestblocks,setupTestPrimitives, andtools/spectest/stressretain it (their intended debug/test use).Behavior
Identical. Every converted site does plain blocking I/O; the API/metrics servers remain serial accept-loops; the installed process
Ioperforms the same kernel operations (theThreadedfutex/blocking path is instance-independent). No concurrency/cancellation semantics were added.Test plan
zig buildgreen onmain.