The Effect State Machine is the client-side layer that sits between user actions and the network. It decides when to flush pending actions to the server, how to handle responses, and how to recover from network errors — all in a pure, verifiedDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/metareflection/dafny-replay/llms.txt
Use this file to discover all available pages before exploring further.
Step function. JavaScript handles only I/O: making network calls and feeding responses back as events.
EffectState
client is the verified ClientState from MultiCollaboration, holding baseVersion, present, and pending. The serverVersion field tracks the last known server version for freshness checks.
Events
Every input to the state machine is one of these events:| Event | Trigger |
|---|---|
UserAction(action) | User performs an action in the UI |
DispatchAccepted(newVersion, newModel) | Server accepted the dispatched action |
DispatchConflict(freshVersion, freshModel) | Server rejected due to version conflict |
DispatchRejected(freshVersion, freshModel) | Server rejected due to domain invalidity |
NetworkError | Network request failed |
NetworkRestored | Network reconnected automatically |
ManualGoOffline | User explicitly went offline |
ManualGoOnline | User explicitly went online |
Tick | Periodic check to start a flush |
Commands
The step function returns a command alongside the new state:EffectState directly.
Step function
UserAction, DispatchAccepted (when more pending exist), NetworkRestored, ManualGoOnline, or Tick. CanStartDispatch is:
Invariant
ModeConsistent ensures that dispatching mode always has pending actions to dispatch. RetriesBounded ensures retries never exceed MaxRetries.
Proved properties
StepPreservesInv — all transitions preserve the invariant
StepPreservesInv — all transitions preserve the invariant
Idle (satisfying ModeConsistent trivially) or only sets Dispatching when HasPending is confirmed.RetriesAreBounded — retries never exceed MaxRetries
RetriesAreBounded — retries never exceed MaxRetries
DispatchConflict increments retries, and it checks retries >= MaxRetries before doing so. When max is hit, the mode goes Idle.TickStartsDispatch — Tick initiates dispatch when eligible
TickStartsDispatch — Tick initiates dispatch when eligible
Tick always starts dispatch. This enables the retry-after-max-retries pattern: go idle, wait for Tick, retry with fresh retry count.MaxRetriesLeadsToIdle — conflict at max retries transitions to Idle
MaxRetriesLeadsToIdle — conflict at max retries transitions to Idle
pending and will be retried on the next Tick.PendingNeverLost — pending actions are never arbitrarily lost
PendingNeverLost — pending actions are never arbitrarily lost
UserAction grows pending, DispatchAccepted/DispatchRejected remove at most one, and all other events leave pending unchanged.PendingSequencePreserved — exact sequence equality on accept/reject
PendingSequencePreserved — exact sequence equality on accept/reject
pending[1..]. The dispatched action is removed and the rest are preserved in order.ConflictPreservesPendingExactly — conflict leaves pending unchanged
ConflictPreservesPendingExactly — conflict leaves pending unchanged
pending. The action is retried after rebasing to the fresh server state.UserActionAppendsExact — user action appends the exact action
UserActionAppendsExact — user action appends the exact action
pending in both the optimistic-success and optimistic-failure cases.System properties
EffectSystemProperties.dfy proves four system-level properties over sequences of events:
NoSilentDataLoss — actions never disappear without being processed
NoSilentDataLoss — actions never disappear without being processed
pending either remains in pending or is explicitly processed (accepted or rejected while at position 0 in dispatching mode). There is no case where an action silently disappears.UserActionEntersPending — user actions are captured
UserActionEntersPending — user actions are captured
pending immediately, regardless of network state.FIFOProcessing — actions are processed in order
FIFOProcessing — actions are processed in order
i > 0 are never removed by any event except by first becoming position 0.OnlineIdlePendingMakesProgress — system makes progress
OnlineIdlePendingMakesProgress — system makes progress
Tick always produces a SendDispatch command. This connects the bounded retry mechanism to eventual progress.Retry design
The retry design provides two layers of protection:- Bounded immediate retries —
DispatchConflictretries up toMaxRetries(default 5) times, rebasing each time. - Persistent eventual retry — after exceeding
MaxRetries, the mode goesIdlebut the action stays inpending. The nextTickresets retries to 0 and tries again.
Integration boundary (trusted)
- Mapping browser/network events to
EffectStateMachineevents - Actual I/O execution of
SendDispatchandFetchFreshStatecommands - End-to-end liveness assumptions (fairness of
Tickdelivery)
Related pages
Multi-Collaboration kernel
ClientState that the Effect State Machine wraps.