Documentation
¶
Overview ¶
Package eventlog is the reference in-memory event log for the agentsessions walking skeleton. It realizes three parts of the durable-log & replay contract:
- single-writer enforcement via compare-and-swap on the log head (expected_last_seq);
- an incarnation fencing token that rejects writes from a superseded incarnation;
- a per-record hash-chain (tamper-evident; becomes a hash-tree at a fork).
content_hash is the language-neutral value from package canon (RFC 8785 JCS over proto3-JSON), so the chain is verifiable by any implementation — not only this Go host — and the integrity definition lives in exactly one place. A sqlite/Durable Task backend implements the same shape later. See agentsessions-replay-determinism-contract.md (§1, §5, §7).
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrConflict = errors.New("eventlog: seq conflict (single-writer compare-and-swap failed)")
ErrConflict is returned when Append's expectedLastSeq does not equal the log head (another writer advanced the log). This is the single-writer CAS.
var ErrFenced = errors.New("eventlog: stale fencing token (incarnation superseded)")
ErrFenced is returned when Append is called with a fencing token older than the current one — a superseded (zombie) incarnation trying to write.
Functions ¶
func RecordToProto ¶
RecordToProto wraps a committed Record as a wire LogRecord: the host-assigned envelope (seq, prev_hash, content_hash, fence) plus the hash-free Event. content_hash is the language-neutral hash from package canon (carried verbatim; not recomputed here).
Types ¶
type Log ¶
type Log struct {
// contains filtered or unexported fields
}
Log is an append-only, single-writer event log with a hash-chain and fencing.
func NewFrom ¶
NewFrom returns a log seeded with a prefix (used to realize a replay-fork: the child starts from a copy of the parent's records up to the fork point).
func (*Log) Append ¶
Append commits ev as the next record iff expectedLastSeq == head (CAS) and fence is current. It assigns Seq and links the hash-chain. The caller must not rely on ev.Seq.
func (*Log) NewFence ¶
NewFence advances and returns the current fencing token. A new incarnation calls this to take over; older incarnations holding a smaller token can no longer Append.
func (*Log) Read ¶
Read returns a copy of all records with Seq >= fromSeq, in order. Replay reads from a baseline (or 0) up to the resume point.
type Record ¶
Record is one committed log entry: the payload plus ordering, integrity, and fencing metadata. Hash = SHA-256(prevHash || canonical(payload)); a fork sets a child's first prevHash to the parent record's Hash, turning the chain into a tree.
func RecordFromProto ¶
RecordFromProto converts a wire LogRecord back to a Record.
type Store ¶
type Store interface {
// Append commits ev as the next record iff expectedLastSeq == head (single-writer CAS) and
// fence is current.
Append(expectedLastSeq, fence int64, ev api.Event) (Record, error)
// Head returns the seq of the last committed record (0 if empty).
Head() (int64, error)
// NewFence advances and returns the incarnation fencing token.
NewFence() (int64, error)
// Read returns all records with seq >= fromSeq, in order.
Read(fromSeq int64) ([]Record, error)
// Verify walks the chain and reports the first integrity violation.
Verify() error
}
Store is the error-returning event-log contract the controller depends on, so it can run against either the in-memory Log (via AsStore) or the persistent sqlitelog.Log interchangeably. Every operation can fail because a durable backend does I/O; the in-memory adapter simply never returns an error. The unified shape is the error-returning one because the controller must handle read/head/fence failures from the persistent backend.