Documentation
¶
Overview ¶
Package queue provides the durable task store and the Queue facade.
The Store interface is the persistence boundary; the sqlite Store is the embedded default. Every mutating operation also appends a fact to the journal in the same transaction, so the journal is always a complete, consistent history of the queue.
Index ¶
- Variables
- type Filter
- type Queue
- type SQLiteStore
- func (s *SQLiteStore) Cancel(ctx context.Context, id task.ID) error
- func (s *SQLiteStore) ClaimDue(ctx context.Context, owner string, lease time.Duration) (task.Task, error)
- func (s *SQLiteStore) Close() error
- func (s *SQLiteStore) Complete(ctx context.Context, id task.ID, owner string, result json.RawMessage) error
- func (s *SQLiteStore) Enqueue(ctx context.Context, n task.New) (task.Task, error)
- func (s *SQLiteStore) Facts(ctx context.Context, after int64) ([]journal.Fact, error)
- func (s *SQLiteStore) Fail(ctx context.Context, id task.ID, owner string, errText string, ...) error
- func (s *SQLiteStore) FailPermanent(ctx context.Context, id task.ID, owner string, errText string) error
- func (s *SQLiteStore) Get(ctx context.Context, id task.ID) (task.Task, error)
- func (s *SQLiteStore) Heartbeat(ctx context.Context, id task.ID, owner string, extend time.Duration) error
- func (s *SQLiteStore) List(ctx context.Context, f Filter) ([]task.Task, error)
- func (s *SQLiteStore) RescueDead(ctx context.Context, id task.ID, maxAttempts int) error
- type Store
- type StoreOption
Constants ¶
This section is empty.
Variables ¶
var ErrNoTaskDue = errors.New("queue: no due task")
ErrNoTaskDue is returned by ClaimDue when nothing is claimable right now.
Functions ¶
This section is empty.
Types ¶
type Queue ¶
type Queue struct {
Store
}
Queue is the facade most consumers use: a Store plus convenience methods.
type SQLiteStore ¶
type SQLiteStore struct {
// contains filtered or unexported fields
}
SQLiteStore is the embedded, durable Store. One queue per database file.
Concurrency model: a single serialized write connection (MaxOpenConns(1)) plus WAL journal mode. All task mutations and their journal facts happen in one transaction, so the journal can never disagree with the task table. Multiple processes may open the same file; busy_timeout + WAL serialize cross-process writers.
func OpenSQLite ¶
func OpenSQLite(path string, opts ...StoreOption) (*SQLiteStore, error)
OpenSQLite opens (creating if needed) the queue database at path.
func (*SQLiteStore) ClaimDue ¶
func (s *SQLiteStore) ClaimDue(ctx context.Context, owner string, lease time.Duration) (task.Task, error)
ClaimDue atomically claims one due task for owner.
func (*SQLiteStore) Close ¶
func (s *SQLiteStore) Close() error
Close releases the database connection.
func (*SQLiteStore) Complete ¶
func (s *SQLiteStore) Complete(ctx context.Context, id task.ID, owner string, result json.RawMessage) error
Complete marks a Running task Completed.
func (*SQLiteStore) Enqueue ¶
Enqueue persists a new task and records task.enqueued. When New.DedupKey is set and a task with that key already exists, the stored task is returned unchanged — no duplicate row, no duplicate fact (idempotent enqueue).
func (*SQLiteStore) Fail ¶
func (s *SQLiteStore) Fail(ctx context.Context, id task.ID, owner string, errText string, backoff time.Duration) error
Fail records a failed attempt: retry with backoff or dead-letter.
func (*SQLiteStore) FailPermanent ¶
func (s *SQLiteStore) FailPermanent(ctx context.Context, id task.ID, owner string, errText string) error
FailPermanent dead-letters immediately: a permanent error means the identical retry would fail identically, so the remaining attempt budget is worthless (and, for agent tasks, expensive). The failing attempt is still counted. Facts: task.failed + task.dead-lettered with class "permanent".
func (*SQLiteStore) Heartbeat ¶
func (s *SQLiteStore) Heartbeat(ctx context.Context, id task.ID, owner string, extend time.Duration) error
Heartbeat extends the lease of a Running task held by owner.
func (*SQLiteStore) RescueDead ¶
RescueDead re-queues a Dead task with a fresh attempt budget (DLQ rescue).
type Store ¶
type Store interface {
// Enqueue persists a new task (ID and defaults assigned here) and records
// the task.enqueued fact.
Enqueue(ctx context.Context, n task.New) (task.Task, error)
// ClaimDue atomically claims at most one due task for owner: pending,
// NotBefore passed, all deps completed. Sets Running + lease. Returns
// ErrNoTaskDue when nothing is claimable.
ClaimDue(ctx context.Context, owner string, lease time.Duration) (task.Task, error)
// Complete marks a Running task Completed (lease must be held) and records
// the task.completed fact.
Complete(ctx context.Context, id task.ID, owner string, result json.RawMessage) error
// Fail records a failed attempt. When attempts remain the task returns to
// Pending with NotBefore = now + backoff(attempt); otherwise it is
// Dead-lettered. Facts: task.failed (+ task.dead-lettered).
Fail(ctx context.Context, id task.ID, owner string, errText string, backoff time.Duration) error
// FailPermanent dead-letters a Running task immediately, regardless of
// the attempt budget: the error class makes retrying pointless. The
// attempt is still counted. Facts: task.failed + task.dead-lettered
// (class "permanent").
FailPermanent(ctx context.Context, id task.ID, owner string, errText string) error
// Heartbeat extends the lease of a Running task held by owner.
Heartbeat(ctx context.Context, id task.ID, owner string, extend time.Duration) error
// Cancel withdraws a Pending task.
Cancel(ctx context.Context, id task.ID) error
// RescueDead re-queues a Dead task with a fresh attempt budget.
RescueDead(ctx context.Context, id task.ID, maxAttempts int) error
// Get returns the current task record.
Get(ctx context.Context, id task.ID) (task.Task, error)
// List returns tasks matching the filter.
List(ctx context.Context, f Filter) ([]task.Task, error)
// Facts exposes the journal (same store, same transaction domain).
Facts(ctx context.Context, after int64) ([]journal.Fact, error)
// Close releases resources.
Close() error
}
Store is the persistence boundary for tasks and facts.
type StoreOption ¶
type StoreOption func(*storeOptions)
StoreOption configures optional SQLiteStore behavior.
func WithProjectExclusivity ¶
func WithProjectExclusivity() StoreOption
WithProjectExclusivity turns on store-level per-project serialization: ClaimDue will not claim a task whose project already has another running task — across ALL pools and processes sharing the same database file, not just within one pool. This is the per-repo guarantee for agent pools: two agents never work the same repo simultaneously. Every pool sharing the DB must opt in; pools that do not opt in ignore the guard. Tasks with an empty project are exempt (they are not tied to a repo).