EventLog is a persistent, replayable progress-event stream over ordered KV storage.
emit(type, payload) assigns a strictly increasing seq and persists the row, so
consumers can replay events in order after a restart, or resume from a cursor
(read(afterSeq)).
Retention is count-based: the log keeps at most retain rows (default 1000), and each
emit past that bound prunes the oldest rows — the storage footprint stays bounded
regardless of emit rate, and pruning never reuses a seq.
Obtaining an EventLog
An agent constructs its own log over the actor’s durable storage — typically once, as a field:ctx.storage, so the log shares the actor’s
durability and single-writer guarantees; retain bounds how many rows are kept
(default 1000). One actor can hold several logs for unrelated streams — each
EventLog keys its rows independently.
Worked example: streaming progress from a long-running task
The pattern has three parts: the task emits durable events, the socket server replays and pushes them, and the client subscribes from a cursor. 1. Emit from the task, push to live watchers.emit persists the row and returns
its seq; reading strictly after seq - 1 yields the stored row to hand to
AgentSocketServer’s
broadcastEvent:
onEvents delivers each event in seq order; from replays missed events after a
disconnect, so a page that reconnects mid-task picks up exactly where it left off:
seq never regresses, this survives agent restarts
mid-task: the replay comes from storage, not from anything held in memory.
emit()
emit(Append one event; returns its assigned seq. Atomic (counter + row + pruning). If the log is at its retention bound, the oldest row(s) are pruned in the same transaction. Parameterstype,payload):Promise<number>
Returns
Promise<number>
read()
read(Read retained events in seq order.afterSeq?,limit?):Promise<StoredEvent[]>
afterSeq is an exclusive cursor:
only events with seq > afterSeq are returned (default 0 = from the
start). limit caps the number of rows; omitted = all retained rows
(paginates internally past the per-list cap).
Parameters
Returns
Promise<StoredEvent[]>
count()
count():Total events ever emitted (the current seq high-water mark). ReturnsPromise<number>
Promise<number>
StoredEvent
A progress event as persisted: assigned a monotonic seq + wall-clock stamp. Properties at
at: Date
Wall-clock stamp at emit time; informational only (ordering is by seq).
payload
payload: unknown
Arbitrary payload. MUST be codec-safe (JSON-native + Date/Map/Set/
ArrayBuffer/TypedArray/Buffer/BigInt/RegExp) — it is stored via
ctx.storage.put, which throws CodecError on functions, class instances,
or circular refs.
seq
seq: number
Monotonic sequence number, assigned on emit — never reused, only moves forward.
type
type: string
Caller-chosen event kind (e.g. “progress”).
EventLogOptions
Options for the event log. Properties retain?Maximum number of event rows kept (count-based retention). Once the log holds this many rows, each new emit prunes the oldest. Default 1000.optionalretain?:number