journal

package module
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Oct 6, 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 is an OPEN string type whose lifecycle values are byte-identical to the engine's (pinned in internal/queue/companion's vocabulary test; this package stays go-cqrs-lite-free for DAG purity, ADR-0014 D2). Lifecycle facts come from the engine's own same-transaction transitions; tq-only families (heartbeat, session.*, question-*) stay tq-side constants written through the engine's FactTx sink. Fact reads come from the ENGINE's queue.Store contract, mapped at the companion seam — never mirrored SQL.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Fact

type Fact struct {
	Seq     int64          `json:"seq"`
	Time    time.Time      `json:"time"`
	TaskID  string         `json:"taskId"`
	Type    FactType       `json:"type"`
	Owner   string         `json:"owner,omitempty"`
	Attempt int            `json:"attempt,omitempty"`
	Error   string         `json:"error,omitempty"`
	Detail  jsontext.Value `json:"detail,omitempty"`
}

Fact is one immutable observation about one task.

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 string

FactType enumerates the kinds of facts that can be recorded.

const (
	Enqueued     FactType = "task.enqueued"
	Claimed      FactType = "task.claimed"
	Heartbeat    FactType = "task.heartbeat"
	Completed    FactType = "task.completed"
	Failed       FactType = "task.failed"        // attempt failed, will retry
	DeadLettered FactType = "task.dead-lettered" // attempts exhausted
	Cancelled    FactType = "task.cancelled"
	// CancelRequested records an operator's request to stop a Running
	// task. The fact IS the flag: the executing worker observes it at its
	// next heartbeat, cancels the execution context, and records
	// task.cancelled; a crashed worker's expired lease finalizes the same
	// cancel at reclaim. No task-row column mirrors it.
	CancelRequested FactType = "task.cancel-requested"
	Released        FactType = "task.released" // lease expired, back to pending
	Requeued        FactType = "task.requeued" // preflight refusal, no attempt burned
	// Orphaned records that a Running task's lease expired and NO worker
	// reclaimed it (the worker died with the pool down). It is an
	// observation, not a state change: the task stays Running until a
	// ClaimDue reclaim (or a human) picks it up. Appended idempotently by
	// Store.MarkOrphaned, so `tq show` can explain a stranded task.
	Orphaned FactType = "task.orphaned"
	// Reprioritized records that a PENDING task's priority changed
	// (ADR-0015 §5): the mutation is UpdatePendingPriority's in-tx fact,
	// carrying old/new priority, the source (marker|importance|ai|keyword|
	// manual|unblock|migration) and why. Priority never mutates
	// running/terminal tasks — those facts do not exist by construction.
	Reprioritized FactType = "task.reprioritized"
	// 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"
)

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.

Directories

Path Synopsis
cqrs module

Jump to

Keyboard shortcuts

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