Expand description
Per-actor LspDocumentChanged -> ActorCmd::RecordEdit fan-in.
Subscribes one typed channel per actor to the editor’s event
bus (M.5.5: EventBus::subscribe_typed::<LspDocumentChanged>).
On every event whose path resolves to a URI the actor cares
about, it forwards one RecordEdit actor command per applied
edit.
The publisher (App’s publish_document_changed) only fires
LspDocumentChanged when lsp-mode is active for the edited
buffer, so the gate happens at the publish site – fan_in
never sees edits the user gated off via :lsp-mode. The
generic Event::DocumentChanged keeps firing for non-LSP
subscribers regardless.
§Why per-actor and not one shared dispatcher
Each actor owns its own DocSync mirror; the only writer to
that mirror is the actor’s own task. Routing edits straight
into the actor’s mailbox makes the edit path lock-free
end-to-end (publish on the UI thread is a single mutex grab
on the bus inner; the rest is fully async). A central
dispatcher would re-introduce a shared lock on the
attachments map and serialise every edit through it – the
exact contention pattern this refactor exists to remove.
§Lifecycle
- The supervisor calls
spawnright after a new actor is running. The returned [SubscriptionId] is stored next to the actor so it can be unsubscribed at shutdown. - The fan-in task exits when the bus drops the channel
(supervisor called
unsubscribe, dropping the sender) or when the actor’srecord_editreturnsLspError::ActorGone(the supervisor dropped the handle).
§Filtering by attached URIs
The fan-in does not know which URIs are attached to which
actor. Instead it forwards every LspDocumentChanged whose
path is Some(_) to its actor; the actor’s DocSync
warns + skips on URIs it doesn’t track. This trades a small
amount of per-event work (one Uri build + one mpsc send)
against keeping the supervisor’s attachment map out of the
hot path.
Functions§
- spawn
- Subscribe
handleto everyLspDocumentChangedevent onbus(M.5.5; previouslyEvent::DocumentChanged) and spawn a tokio task that forwards them asRecordEditactor commands. Returns the subscription id; the supervisor must hand this to [EventBus::unsubscribe] when the actor is dropped to keep the bus’s bucket from accumulating dead entries.