Module writer
Expand description
JSONL append-only writer + rolling rotation.
RAM contract: a single event lands in two allocations (the JSON line
that goes to disk + the serde_json::Value clone that goes to the
broadcast hook). Rolling rotation streams through BufReader::lines
into a temp file rather than slurping the whole file into a String.
§Hot-path write concurrency model
Disk persistence runs on a dedicated std::thread named
zeroclaw-log-writer so record_event does not block on file I/O
or fsync. The async runtime emits an event by serializing it once
and try_send-ing onto a bounded std::sync::mpsc::sync_channel;
when the channel is full (worker is slow or disk is stalled) the
event is dropped with a tracing::warn! so a single slow disk
cannot wedge an agent turn. The worker re-opens the active file
per write (matching the prior single-threaded semantics — required
because rolling trim and size-based rotation rename the file out
from under an open handle), runs the rotation hooks inline, and
calls sync_all on a periodic cadence (every
SYNC_EVERY_N_WRITES writes or SYNC_INTERVAL of wall-clock
time, whichever comes first). This trades per-event durability
(the prior behaviour was sync_data after every write) for bounded
write latency: a process crash may lose up to one sync interval of
pending writes.
Constants§
- EPHEMERAL_
BROADCAST_ MARKER - Top-level marker stamped onto a broadcast frame when it carries
ephemeral_attributes(short-lived pairing secrets deep-merged into the live copy). Broadcast consumers use it to withhold the frame from any stream that is not bearer-authenticated — the frame’s secrets must fail closed rather than ride an unauthenticated/api/eventssubscriber. It is stamped only on the broadcast copy (never the persisted value, which dropsephemeral_attributesviaserde(skip)) and is stripped by the SSE layer before delivery, so the public event shape is unchanged.
Functions§
- flush_
for_ test - frame_
carries_ ephemeral_ credentials - True when a broadcast frame was stamped with
EPHEMERAL_BROADCAST_MARKERbyrecord_event— i.e. it carries broadcast-only pairing secrets (QR payloads, pair codes) deep-merged intoattributes. - init_
from_ config - llm_
request_ payload_ policy - Resolved LLM-request-payload capture policy + the truncate cap, for the
turn engine’s
announce_llm_request.Nonewhen no writer is installed (the policy defaults tooff, so callers treat “no writer” as “off”). - record_
event - Emit one event. Always fans out to the broadcast hook + tracing event.
If persistence is enabled, hands the serialized value to the disk
worker via a bounded
try_send. The hot path performs no file I/O. - runtime_
trace_ path - Public accessor for the canonical log file path. Used by the gateway’s
/api/logsendpoint to know which file to stream. - strip_
ephemeral_ broadcast_ marker - Strip the internal
EPHEMERAL_BROADCAST_MARKERfrom a broadcast frame before it is delivered to a consumer, so the public event shape is unchanged. Returns whether the marker was present.