56 lines
2.5 KiB
Markdown
56 lines
2.5 KiB
Markdown
# Durable events
|
|
|
|
`events.ts` owns event tokens, the event log, the feed, and reactor cursors.
|
|
World extensions import its shared tokens from `@earendil-works/sausage-events`.
|
|
The loader supplies this synthetic module from its own bundle.
|
|
|
|
## Transaction contract
|
|
|
|
`host.emit(tx, token, data)` appends an event inside the caller's transaction.
|
|
The event and the caller's document changes commit together.
|
|
A failed transaction retains neither change.
|
|
|
|
The log uses an ownerless conversation that runs no turns.
|
|
Entry IDs provide a global order.
|
|
`EventLog` records the log conversation and each reactor's cursor on the root conversation.
|
|
|
|
`host.react(name, tokens, handler, {from})` registers a facet-scoped reactor.
|
|
Its durable name is `<extension>/<name>`.
|
|
Each handler receives its transaction and a detached event record.
|
|
The handler's document changes and cursor advance commit together.
|
|
Transactional changes occur exactly once.
|
|
External effects can repeat after a crash.
|
|
|
|
A failed handler rolls back its changes and cursor.
|
|
The next matching event commit or reactor start retries the pending event.
|
|
Reloads stop the old facet's reactors before the new facet starts.
|
|
A replacement with the same name continues from its persisted cursor.
|
|
|
|
A new reactor starts at the beginning by default.
|
|
`from: 'now'` skips existing events only when the reactor lacks a cursor.
|
|
|
|
## Read contract
|
|
|
|
`host.eventLog.recent(options)` returns detached records, newest first by default.
|
|
It supports token filters, a limit, and an ascending order.
|
|
`since` and `before` are exclusive entry IDs.
|
|
`host.eventLog.reactors()` returns cursors, lag, activity, and the latest handler failure.
|
|
|
|
`EventFeed` stores the newest 100 events, oldest first.
|
|
The existing document observation API can observe this feed.
|
|
Event emission updates the feed inside the same transaction.
|
|
|
|
Notices become `sausage.notice` events.
|
|
The host records each distinct notice once per facet load.
|
|
This task does not add Standing agent's build or supervisor startup events.
|
|
|
|
## Tests
|
|
|
|
`events-test.ts` covers atomic emission, handler rollback, cursor recovery, replacement, and harness reopen.
|
|
It also covers filtered reads, detached copies, the bounded feed, and `from: 'now'`.
|
|
World facets exchange events through their hosts and continue after a commit reload.
|
|
`host/tests/events.rs` kills a child after emission, then verifies one reaction across two restarts.
|
|
|
|
The world test builds `git.wasm` with the repository's linker setup.
|
|
It uses a persistent cache in the executor's target folder.
|