Problem
In crates/worker/src/runtime.rs:36-60, actors are spawned sequentially without synchronization:
let state_addr = system.spawn(StateActor { role }); // Line 39
system.spawn(NetworkActor::new(state_addr, ...)); // Line 41
NetworkActor::started() spawns a background task that immediately begins draining TopicEvents and forwarding EventMsg to the StateActor. If the gossip topic has buffered messages, they arrive at the StateActor before its started() hook completes.
There is no startup barrier — no mechanism to ensure all actors are initialized before processing begins.
Impact
- Events arriving during startup may hit an uninitialized WorkerRole
- Role-specific invariant checks may panic on null/uninitialized state
- Race is invisible in tests (in-memory networks have no pre-buffered messages)
Suggested fix
Options:
- Add a
Ready message that NetworkActor sends after all actors confirm initialization
- Buffer events in NetworkActor until a
StartProcessing signal is received
- Use a
tokio::sync::Barrier across actor startup
Location
crates/worker/src/runtime.rs:36-60
crates/worker/src/actors/network.rs:46-59 (background task spawned in started())
References
Found during deep implementation audit (pass 2)
Problem
In
crates/worker/src/runtime.rs:36-60, actors are spawned sequentially without synchronization:NetworkActor::started()spawns a background task that immediately begins drainingTopicEventsand forwardingEventMsgto the StateActor. If the gossip topic has buffered messages, they arrive at the StateActor before itsstarted()hook completes.There is no startup barrier — no mechanism to ensure all actors are initialized before processing begins.
Impact
Suggested fix
Options:
Readymessage that NetworkActor sends after all actors confirm initializationStartProcessingsignal is receivedtokio::sync::Barrieracross actor startupLocation
crates/worker/src/runtime.rs:36-60crates/worker/src/actors/network.rs:46-59(background task spawned in started())References
Found during deep implementation audit (pass 2)