eventlog

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 16, 2026 License: MIT Imports: 7 Imported by: 0

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

View Source
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.

View Source
var ErrDeleted = errors.New("eventlog: session is permanently deleted")

ErrDeleted refuses writes to a permanently tombstoned session, independent of its fence or head.

View Source
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 CheckWritable

func CheckWritable(log Store) error

CheckWritable performs the optional durable-deletion preflight. Unknown fresh logs remain writable. Wrappers around durable stores must forward CheckWritable to preserve refusal before compute work; Append and NewFence still enforce the authoritative storage barrier.

func RecordToProto

func RecordToProto(r Record) *v1.LogRecord

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 New

func New() *Log

New returns an empty log.

func NewFrom

func NewFrom(prefix []Record) *Log

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

func (l *Log) Append(expectedLastSeq, fence int64, ev api.Event) (Record, error)

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) Head

func (l *Log) Head() int64

Head returns the seq of the last committed record (0 if empty).

func (*Log) NewFence

func (l *Log) NewFence() int64

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

func (l *Log) Read(fromSeq int64) []Record

Read returns a copy of all records with Seq >= fromSeq, in order. Replay reads from a baseline (or 0) up to the resume point.

func (*Log) Snapshot

func (l *Log) Snapshot() []Record

Snapshot returns a copy of the full record slice (used to seed a fork).

func (*Log) Verify

func (l *Log) Verify() error

Verify walks the chain and returns an error if any link is broken.

type Record

type Record struct {
	Seq      int64
	PrevHash string
	Hash     string
	Fence    int64
	Event    api.Event
}

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

func RecordFromProto(p *v1.LogRecord) Record

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.

func AsStore

func AsStore(l *Log) Store

AsStore adapts the in-memory Log (whose reads cannot fail) to the error-returning Store.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL