journal

package module
v0.3.4 Latest Latest
Warning

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

Go to latest
Published: Oct 11, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package journal defines the append-only fact log that records everything that ever happened to tasks. All derived views (queue, DLQ, stats) are projections over these facts.

S2 (ADR-0019): the fact vocabulary RIDES the upstream engine's go-cqrs-lite queue/v4/facts vocabulary — FactType and Fact are TYPE ALIASES of facts.FactType/facts.Fact (the lifecycle spellings are byte-identical, pinned in internal/queue/companion's vocabulary test), and lifecycle facts come from the engine's own same-transaction transitions. Tq-only families (heartbeat, session.*, question-*, error/incident) stay tq-side constants of the aliased type, written through the engine's FactTx sink; tq invariants on lifecycle facts (which transitions may emit them, e.g. ADR-0015 §5 on Reprioritized) live at their construction sites. Fact reads come from the ENGINE's queue.Store contract, mapped at the companion seam — never mirrored SQL.

Index

Constants

View Source
const (
	Enqueued        = facts.Enqueued
	Claimed         = facts.Claimed
	Completed       = facts.Completed
	Failed          = facts.Failed
	DeadLettered    = facts.DeadLettered
	Cancelled       = facts.Cancelled
	CancelRequested = facts.CancelRequested
	Released        = facts.Released
	Requeued        = facts.Requeued
	Orphaned        = facts.Orphaned
	Reprioritized   = facts.Reprioritized
)

Lifecycle vocabulary (task.enqueued … task.reprioritized) IS the engine's facts.FactType (ADR-0019 S2): these re-exports are IDENTITY aliases of the upstream constants, so consumers keep the journal import surface while the spellings cannot drift by construction.

Variables

This section is empty.

Functions

This section is empty.

Types

type EffectStatus added in v0.3.4

type EffectStatus string

EffectStatus is the disposition of a run's side effect, recorded on the task.released detail when a leased Running task is reclaimed. It exists so a crash mid-effect is distinguishable from a clean re-run: turnstone's rule is "crashes aren't finishes" and "unknown is not none". The observer that reclaims cannot prove the effect never ran, so it records unknown, never a false none (a learned/derived label may not lower a certainty).

const (
	// EffectCommitted: the effect is observed to have landed.
	EffectCommitted EffectStatus = "committed"
	// EffectNone: the effect provably never executed. Reserved: no tq
	// path can prove this today (the reclaiming observer sees no
	// dispatch-started marker), so nothing stamps it yet.
	EffectNone EffectStatus = "none"
	// EffectUnknown: the run crashed mid-effect; it may or may not have
	// landed. What the reclaim path records.
	EffectUnknown EffectStatus = "unknown"
	// EffectPartial: some steps of a multi-step effect landed.
	EffectPartial EffectStatus = "partial"
	// EffectRolledBack: the effect was compensated.
	EffectRolledBack EffectStatus = "rolled_back"
)

type Fact

type Fact = facts.Fact

Fact is one immutable observation about one task; it IS the engine's facts.Fact (ADR-0019 S2). Tq-only detail shapes ride the same Detail bytes.

func AfterSeq added in v0.3.1

func AfterSeq(facts []Fact, after int64, limit int) []Fact

AfterSeq filters facts to Seq strictly greater than after, in order, bounded to the most recent limit when > 0 — the cursor semantics shared by slice-backed sources and test fakes.

type FactType

type FactType = facts.FactType

FactType enumerates the kinds of facts that can be recorded; it IS the engine's facts.FactType (ADR-0019 S2), so tq constants and upstream constants are interchangeable by construction.

const (
	Heartbeat FactType = "task.heartbeat"
	// SessionOpened / SessionClosed record the lifecycle of an INTERACTIVE
	// crush session (the session-close bridge, internal/session). They are
	// observations, not task state: TaskID carries the synthetic
	// "session:<id>" identity, never a real task row, so no enqueue/claim
	// machinery can ever pick them up. SessionClosed's detail names the
	// attributed commits and the minted review/status task IDs.
	SessionOpened FactType = "session.opened"
	SessionClosed FactType = "session.closed"
	// QuestionAsked records an agent's request for a human decision while
	// its task is parked (PapDashboard questions). TaskID is the PARKED
	// task; detail carries the question contract (ref, type, text,
	// options, repo, expiry). The task stays PENDING — the park is a
	// requeue without attempt burn — until RecordAnswer unblocks it.
	QuestionAsked FactType = "task.question-asked"
	// QuestionAnswered records the owner's decision arriving from
	// PapDashboard. Written by Store.RecordAnswer in the SAME transaction
	// that injects the answer into the parked task's payload and clears
	// its NotBefore, so "answered but still parked" is unrepresentable.
	// Idempotent per question ref: a replayed pickup appends nothing.
	QuestionAnswered FactType = "task.question-answered"
	// ErrorObserved records one error report from a production surface
	// (web-client beacon or server panic/5xx middleware): an observation,
	// not task state — the session:* precedent. TaskID carries the
	// synthetic "incident:<fingerprint>" identity, never a real task row,
	// so no enqueue/claim machinery can ever pick it up. Detail carries
	// the full redacted Report (message, stack, release, route, trace
	// link); the incident policy (internal/incident) folds these facts
	// into incidents and mints agent fix tasks as reactions (ADR-0021).
	ErrorObserved FactType = "error.observed"
	// IncidentTaskMinted records that the incident policy enqueued a fix
	// task for one incident: TaskID is the incident identity, detail names
	// the minted task (taskID, sourceSeq, regression, priority). Written
	// after Enqueue succeeds; replayed deliveries converge on the task's
	// dedup key instead of minting duplicates. The task's own lifecycle
	// facts (task.completed, task.dead-lettered) close or fail the
	// incident in the fold — never a mirrored column.
	IncidentTaskMinted FactType = "incident.task-minted"
)

type Journal

type Journal interface {
	// Append records a fact. Implementations must assign Seq and Time when zero.
	Append(ctx context.Context, f Fact) (Fact, error)
	// All returns every fact in Seq order.
	All(ctx context.Context) ([]Fact, error)
	// Since returns facts with Seq strictly greater than after, in Seq order.
	Since(ctx context.Context, after int64) ([]Fact, error)
}

Journal is the persistence boundary for facts.

type MemoryJournal

type MemoryJournal struct {
	// contains filtered or unexported fields
}

MemoryJournal is an in-memory Journal for tests and ephemeral queues.

func NewMemoryJournal

func NewMemoryJournal() *MemoryJournal

NewMemoryJournal returns an empty in-memory journal.

func (*MemoryJournal) All

func (m *MemoryJournal) All(_ context.Context) ([]Fact, error)

All returns every fact in Seq order.

func (*MemoryJournal) Append

func (m *MemoryJournal) Append(_ context.Context, f Fact) (Fact, error)

Append records the fact, assigning Seq and Time when zero.

func (*MemoryJournal) Since

func (m *MemoryJournal) Since(_ context.Context, after int64) ([]Fact, error)

Since returns facts with Seq strictly greater than after.

type ReleasedDetail added in v0.3.4

type ReleasedDetail struct {
	Effect EffectStatus `json:"effect"`
	Reason string       `json:"reason,omitempty"` // lease-expiry | cancelled-mid-run
}

ReleasedDetail is the task.released fact detail: the prior attempt's effect disposition, so a reclaim is distinguishable from a clean first run.

Directories

Path Synopsis
cqrs module

Jump to

Keyboard shortcuts

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