Behaviour for a session's durable append-only journal — the source of truth for the durable tier of events (see the package README, "The journal").
A journal is an ordered, append-only log of events. Each appended event is
assigned a monotonic offset (= the event's id) and framed as one complete,
self-delimited JSON object per line. Replaying a journal yields the events
back in offset order.
The behaviour exists so alternate storage backends (S3, a database, ...) can
slot in later behind the same contract. The concrete file-backed
implementation is Raxol.Agent.Journal.FileStore — one directory per session,
size-capped JSONL segments, torn-tail recovery on replay.
Callbacks
open/2— open (creating if needed) the journal for a session, returning an opaque handle.append/2— append one event, returning{:ok, offset}.read/2— replay durable events in offset order.close/2— release the handle (flush + stop the writer).status/1—:okfor a healthy journal,{:damaged, offset}if corruption was detected.verify/1— walk a hash-chained journal::okor{:broken, offset}.
Durability & recovery
Only complete records are ever returned. On replay a parse failure on the
final line of the last segment is treated as a torn tail (a crash mid-write)
and truncated away — everything before it is recovered and status/1 stays
:ok. A parse failure anywhere interior marks the session damaged, raises a
hard alarm, deletes nothing, and never returns the damaged content downstream.
Hash chain
A backend may offer hash-chained journals (Raxol.Agent.Journal.FileStore
does with chain: true): each record links to the hash of the one before
it, so changing, removing or truncating any committed record is detected.
verify/1 reports the offset of the first record that fails, and
status/1 reports the same offset as damage.
Summary
Types
An event to append — any JSON-encodable map.
Opaque, backend-specific handle returned by open/2.
A durable record read back from the journal (a decoded map with an "id").
Monotonic offset assigned to an appended event (= its id).
Stable identifier for a session (also the on-disk directory name).
Callbacks
Append one event. Returns the assigned monotonic offset.
Release the handle (flush pending writes and stop the writer).
Open (creating if needed) the journal for session_id. Returns an opaque handle.
Replay durable events in offset order.
:ok for a healthy journal, {:damaged, offset} naming the first offset
where corruption (or, on a chained journal, a chain break) was detected.
Walk the hash chain. :ok when every record links and verifies,
{:broken, offset} for the first that does not, {:error, :unchained} for
a journal created without a chain.
Types
@type event() :: map()
An event to append — any JSON-encodable map.
@type handle() :: term()
Opaque, backend-specific handle returned by open/2.
@type journal_record() :: map()
A durable record read back from the journal (a decoded map with an "id").
@type offset() :: non_neg_integer()
Monotonic offset assigned to an appended event (= its id).
@type session_id() :: String.t()
Stable identifier for a session (also the on-disk directory name).
Callbacks
Append one event. Returns the assigned monotonic offset.
@callback close(handle()) :: :ok
Release the handle (flush pending writes and stop the writer).
@callback open(session_id(), opts :: keyword()) :: {:ok, handle()} | {:error, term()}
Open (creating if needed) the journal for session_id. Returns an opaque handle.
@callback read(handle(), opts :: keyword()) :: {:ok, [journal_record()]} | {:error, term()}
Replay durable events in offset order.
Returns {:ok, records} for a healthy (or torn-tail-recovered) journal, or
{:error, :damaged} when interior corruption was detected — in which case the
damaged content is never returned.
Options:
:from_offset— only return records whose id is>=this value.
:ok for a healthy journal, {:damaged, offset} naming the first offset
where corruption (or, on a chained journal, a chain break) was detected.
Walk the hash chain. :ok when every record links and verifies,
{:broken, offset} for the first that does not, {:error, :unchained} for
a journal created without a chain.