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