Skip to main content

Module wake

Module wake 

Source
Expand description

OC.2 — the periodic wake seam: wake-every / cancel-wake / on-wake.

§Why a plugin needs one

A plugin whose display changes without the buffer changing has no way to say so. Org’s running clock is the motivating case: the file it wrote is already correct and nothing edits it again, but the modeline segment (◷ 0:14 …) has to re-render once a minute. Nothing in the editor fires on “a minute passed”, so before this the segment could only advance on the next keystroke — which is the “it works, but only after I hit something” failure the boot-composition rules exist to design out.

The host could have owned an elapsed-since(T) element and ticked it with zero WASM calls. That was rejected (design D7): it moves duration semantics into the host, and the general wake is a primitive design.md Appendix B already wants for idle hooks. One typed call per minute against a <500 ns p99 budget is negligible on magnitude.

§Where the time comes from, and why it is injected

lattice-plugin-host owns no runtime — tokio is a dev-dependency and futures was chosen over tokio::sync specifically to keep it that way, so the lib stays executor-agnostic and the caller spawns every actor. A timer is the first thing that would have broken that, so the timer is injected: the host holds a SleeperHandle, the loader supplies one backed by tokio::time::sleep, and a harness that supplies none leaves wake-every answering 0 — the same honest degradation every other unwired context here uses.

§Where a wake fires

On the plugin’s own actor task, in the same select as on-event (event_task.rs). That is the whole reason this shape was chosen over a host-owned scheduler thread: the wake inherits the actor’s budget, its quarantine, and its teardown for free, and there is no cross-thread hop between the timer and the guest call. Aborting the actor task — what the loader does on unload — drops the pending sleeps with it, so “cancelled en masse on deactivate” is structural rather than a step someone must remember.

The events interface is not on the sync grammar linker, so a wake is unreachable from the keystroke path by construction (paramount #4).

Traits§

Sleeper
The timer the wake seam sleeps on, injected so this crate needs no runtime.

Type Aliases§

SleeperHandle
The shared handle a PluginHost is given once at boot.