A bridge that calls registerAgent immediately after store.init() — which is what every production bridge does via ensureRegistered — can have its agent_upsert patch lost for all existing peers. broadcastPatch sends over the transport's data connections, and the peer-introduction dials are fire-and-forget (void this.transport.connectToPeer(...)), so patches emitted in the window between init() returning and the TLS data connections completing have nowhere to go and are dropped without retry.
Reproduction trace (two TLS peers, coordinator B, joining peer A; onPatch logged on both):
222ms a1 patch: agent_upsert <- a1 broadcasts its registration
<- b NEVER receives it
525ms b patch: agent_offline ... <- later patches DO arrive once connected
B only learns of A's agent indirectly (join-time state exchange / later patches). With a 300ms settle between init() and registerAgent the upsert arrives reliably, which isolates the race to the connection-establishment window.
Consequences:
Likely fix direction: on data-connection establishment, send the local peer's current serialised state to the new peer (state_sync on connect), which converges any patches lost during the window; alternatively queue broadcasts until the first data connection completes.
Found while writing the restart-continuity test for the persistent-identity work; the test currently works around it with a settle delay.
A bridge that calls
registerAgentimmediately afterstore.init()— which is what every production bridge does viaensureRegistered— can have itsagent_upsertpatch lost for all existing peers.broadcastPatchsends over the transport's data connections, and the peer-introduction dials are fire-and-forget (void this.transport.connectToPeer(...)), so patches emitted in the window betweeninit()returning and the TLS data connections completing have nowhere to go and are dropped without retry.Reproduction trace (two TLS peers, coordinator B, joining peer A;
onPatchlogged on both):B only learns of A's agent indirectly (join-time state exchange / later patches). With a 300ms settle between
init()andregisterAgentthe upsert arrives reliably, which isolates the race to the connection-establishment window.Consequences:
list_agents(new joiners still see it via state_sync, so the mesh appears inconsistently populated — reminiscent of the symptoms in Peers on same coordinator cannot see each other — mesh state not syncing across harnesses #13).offlineon peers that missed the re-activation upsert, even though delivery routing to it works.Likely fix direction: on data-connection establishment, send the local peer's current serialised state to the new peer (state_sync on connect), which converges any patches lost during the window; alternatively queue broadcasts until the first data connection completes.
Found while writing the restart-continuity test for the persistent-identity work; the test currently works around it with a settle delay.