Skip to main content

LostNotificationsAreRepaired

Trait LostNotificationsAreRepaired 

Source
pub trait LostNotificationsAreRepaired: NotificationChannelIsLossy { }
Expand description

Lemma (A lost notification is repaired). A client that misses a notification still reaches the state it would have reached, provided it remains connected to at least one correct validator that has the change. Three independent mechanisms do this, and none of them replays the lost message.

Redundancy. ChainClient::listen opens one subscription per validator in the committee, via update_notification_streams, and processes them concurrently. Every validator that processes a change notifies about it, so a client loses a notification only when every validator it is subscribed to fails to deliver that one — not when any single one does.

Resynchronization on (re)subscribe. Establishing a stream is not just an attachment point: the same future calls Client::synchronize_chain_state_from against that validator before yielding the stream, precisely because, in the code’s own words, “we may have missed notifications since the last time we synchronized”. Since update_notification_streams is re-run on every Reason::NewBlock, and a dropped connection is re-established through the same path, a gap in the stream is closed by state synchronization rather than by recovering the messages that fell in it.

Coalescing. No handler applies the change it was told about; each brings the chain up to date. In linera_client::chain_listener, Reason::NewIncomingBundle and Reason::NewEvents both reduce to maybe_notify_inbox_processing, whose waiting loop runs ChainClient::process_inbox_without_prepare — draining everything pending, not the one bundle named. Reason::NewBlock calls update_wallet and re-derives event subscriptions. Handlers are therefore idempotent and depend only on current state, so one run after k notifications achieves what k runs would. Notify::notify_one stores a permit when no task is waiting, so a notification arriving during a pass starts another rather than being swallowed. ∎

What is not repaired. Every mechanism above assumes a failure that is either whole-process or network-level, because those are the failures the model has. A validator that is up, answering RPCs and voting normally, but silently delivering no notifications — the partial crash NotificationChannelIsLossy describes — defeats two of the three. Redundancy survives only if such a failure is independent across validators, which a systematic one is not. Resynchronization never runs, because it is triggered by establishing a stream and no stream ever drops: the client holds a healthy connection to a validator that has stopped talking.

Coalescing is then irrelevant, since nothing arrives to coalesce. The client is not told it is learning nothing, and nothing escalates: ChainListener::next_action selects over the notification streams, the cancellation token and its command channel, and there is no timer among them. Pending bundles stay unprocessed and subscribed events unread for as long as the condition lasts, which — being outside the fault model — is not bounded by GST or by anything else the specification states.

Implementors§