Expand description
In-process event bus (DESIGN.md §5.10).
Vim’s autocmd and emacs’s hooks both desugar to the same
primitive: subscribe a sink to a filtered stream of typed
events; the bus calls the sink whenever a matching event is
published. v1 ships the observation-only baseline; the
Before-event veto / mutation seam (§5.10.2) layers on later.
§v1 scope
- Filters by [
lattice_protocol::EventKind] for bucketing, then AND-combines the reservedEventFilterfields (path_glob,major_modes,predicate) at publish time on the candidates the kind bucket already selected (EF.1). Mode activation is the caller that needed them (mode-architecture.md §7.4); the checks are per-candidate constants, so dispatch stays O(subscribers-of-kind) – the filter fields never widen the publish scan. - Sinks are
SubscriptionTarget::Channel(anmpsc::Sender) orSubscriptionTarget::Invocation(aCommandInvocationthe bus runs through the document actor’s dispatch when the App wires that path). - Plugin handler target (
SubscriptionTarget::Pluginin §5.10) is omitted – WASM hosting isn’t online in v1. - Indexed dispatch: subscriptions live in a
HashMap<EventKind, Vec<Subscription>>. Publish iterates the bucket for one kind, never the global list. - Bus is
Send + Sync; the inner state is oneMutex. The publish path takes the lock only to snapshot the matching channel senders (and to queue Invocation targets onto the sharedpending_invocations); the actualtx.sendcalls run with the lock dropped. Twopublishcalls from different threads can therefore dispatch in parallel, and a future bounded subscriber cannot stall the publisher under the bus mutex (audit M1).
§What’s NOT here
BeforeSave/BeforeQuitveto. v1 publishes the event so observers see it; mutating the payload or aborting the transition is out of scope until the actor runs the bus inside its task and respects handler errors.- Backpressure. Channel sinks use unbounded mpsc. If a subscriber leaks senders the bus grows. Bounded channels + slow-consumer policy follow when LSP / plugin subscribers can actually generate the volume that needs governance.
- Per-handler fuel (§5.10.4). Plugin / Invocation handlers will eventually run with a fuel budget; v1 calls them inline or punts to caller for Invocation targets.
Structs§
- Event
Bus - Process-shared event bus. Cheap to construct (one
Mutexholding empty maps). Cheap to clone viaArc<EventBus>– callers wrap externally; the type itself isSend + Syncand can be shared by reference. - Event
Filter - Filter applied at publish time.
kindsbuckets the subscription; the remaining fields (EF.1) AND-combine on top – everySomefield must match for the event to be delivered, aNonefield is unconstrained. Mode activation (mode-architecture.md §7.4) is the caller these reserved fields were declared for. - Subscription
Id - Opaque handle returned by
EventBus::subscribe. Pass toEventBus::unsubscribeto remove the subscription.
Enums§
- Subscription
Target - What the bus does when a matching event arrives.
Type Aliases§
- Event
Ack - The completion signal an awaited publish threads through a plugin sink
(OA.14d). The bus mints one per matched plugin subscription and
EventBus::publish_awaitedreturns the matching receivers; the plugin’s actor drops it once the guest handler has returned. - Event
Predicate - A caller-supplied escape-hatch predicate (the
predicatefield ofEventFilter). Returnstrueto keep the event. - Plugin
Event Sink - A host-owned sink that delivers a matched [
Event] to a plugin’son-eventhandler (PH7.8). Returnsfalsewhen the plugin’s receiver has closed (its actor task ended), so the bus prunes the subscription lazily — the same closed-Channel/ForwardFndiscipline the rest of this module uses.