Expand description
barks.jsonl: the size-capped ring of fired alerts (spec §10.4).
One Bark per line, appended by two writers in two different
processes — the bark dog when a rule fires, and the shepherd itself
when an enabled dog exhausts its restart budget — and read by a third,
shep barks. append keeps the file under a byte cap by evicting
whole lines oldest-first, rewriting the survivors plus the new record
to a sibling temp file and renameing it over the original — the same
atomic-replace shape shep-daemon’s snapshot::write_atomic uses —
rather than truncating in place, so a writer that dies mid-rewrite
never leaves the reader a fragment.
read is the forgiving half: a line that will not parse — a
partially-written record from a writer that died mid-append, or a
record from a future shep — costs the reader that one record, not the
whole history. This file is read during an incident; refusing the
whole ring over one bad line would be the wrong failure mode.
Two writer processes is also why append takes an advisory lock on
a sibling <path>.lock and holds it across the whole
read-evict-rewrite-rename sequence. Without it the two writers
interleave read-modify-write and the later rename silently discards
every record the other appended in between — reproduced, not
theorised: two processes appending 200 records each left 200 of the
expected 400 in the file. Nothing about the atomic-replace shape
prevents that; atomicity buys the reader a whole file, not the writer
a whole transaction.
Lives in shep-core, not shep-daemon, because it has two writers that are two different processes (the shepherd and the bark dog) and neither is the other’s crate — one shared cap implementation, or the two writers evict differently, and that is exactly the kind of drift nobody watches until an incident.
Structs§
- Bark
- One fired alert, as it lands in
$SHEP_HOME/barks.jsonl. - Sink
Outcome - What one sink made of one alert.
Enums§
Constants§
- DEFAULT_
MAX_ BYTES - Cap the ring keeps itself under when nobody configured one.