Help us shape the future of Go! Take the 2026 Go Developer Survey

work

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 19, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

Package work runs the persistent work queue (decision 0033): a pool of workers that lease due items, run the handler registered for each item's kind, and complete, retry or park it. Work is asked for with Enqueue inside the transaction of the change that needs it; readers that must see the work done call EnsureFresh first.

Index

Constants

View Source
const (
	DefaultWorkers     = 4
	DefaultLease       = 2 * time.Minute
	DefaultMaxAttempts = 10
	DefaultPoll        = time.Second
)

Defaults for Options left zero.

Variables

View Source
var (
	// ErrParked reports that the work a reader waits for keeps failing and
	// is parked until it is enqueued again.
	ErrParked = errors.New("work: parked")
	// ErrNoHandler reports a kind with no registered handler.
	ErrNoHandler = errors.New("work: no handler")
	// ErrOptions reports options New cannot use.
	ErrOptions = errors.New("work: invalid options")
	// ErrDuplicateHandler reports a second handler for one kind.
	ErrDuplicateHandler = errors.New("work: kind already has a handler")
	// ErrPanic reports a handler that panicked.
	ErrPanic = errors.New("work: handler panicked")
)

Functions

func Backoff

func Backoff(attempt int) time.Duration

Backoff doubles from one second after the first failure up to ten minutes.

Types

type Handler

type Handler func(ctx context.Context, item types.WorkItem) error

Handler does the work of one item. It must be idempotent: an item can run more than once, for example when a worker stops after the work but before recording it. A cancelled ctx means the queue is stopping or the lease was lost; the handler should return promptly.

type Options

type Options struct {
	// Workers is how many items run at once on this node.
	Workers int
	// Lease is how long a run holds its item before another worker may
	// take it over; a running item's lease is extended every half lease.
	Lease time.Duration
	// MaxAttempts is how many runs an item gets before it is parked.
	MaxAttempts int
	// Poll is how long an idle worker waits before asking again, when no
	// enqueue on this node wakes it sooner.
	Poll time.Duration
	// Holder names this node's leases; empty uses the host name, the
	// process id and a random suffix.
	Holder string
	// Backoff is the wait before an item's next run after its attempt'th
	// failed; nil doubles from a second up to ten minutes.
	Backoff func(attempt int) time.Duration
	Now     func() time.Time
	Log     *slog.Logger
	// Meters exports the queue's metrics (decision 0016); nil exports none.
	Meters metric.MeterProvider
}

Options configures a Queue.

type Queue

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

Queue runs the persistent work queue for one node.

func New

func New(st store.Store, o Options) (*Queue, error)

New returns a queue over st; register handlers with Handle before Run.

func (*Queue) Enqueue

func (q *Queue) Enqueue(ctx context.Context, kind, key string, payload []byte) error

Enqueue asks for kind's work on key. Call it with the context of the transaction that makes the change needing the work, so the work is asked for exactly when the change commits; this node's workers are woken once it has.

func (*Queue) EnsureFresh

func (q *Queue) EnsureFresh(ctx context.Context, kind, key string) error

EnsureFresh brings the work owed for kind and key up to date before the caller reads what it derives: it runs a waiting item now, in the caller's context, or waits for a run already in progress elsewhere. It returns nil when nothing is owed, the handler's error when the run it made fails, and ErrParked when the item is parked.

func (*Queue) Handle

func (q *Queue) Handle(kind string, h Handler) error

Handle registers h for kind. Register every handler before Run: Run leases only the kinds registered when it starts. A second handler for one kind is an error.

func (*Queue) HandleEvery

func (q *Queue) HandleEvery(kind string, every time.Duration, h Handler) error

HandleEvery registers h for kind as periodic work, for work that Artifactory does on a timer rather than as it is asked for, such as its snapshot cleanup every five minutes. An item of kind is not run as soon as it is due: it waits in the queue, so a restart keeps it, for the next tick of a timer every interval on each node, which runs every item of kind then due (RunDue). EnsureFresh still runs one at once. Register it before Run, as Handle.

func (*Queue) Run

func (q *Queue) Run(ctx context.Context) error

Run leases and runs items until ctx ends, then hands back the leases of runs it cuts short and returns once every run has settled. Periodic kinds run on their own timers, outside the workers.

func (*Queue) RunDue

func (q *Queue) RunDue(ctx context.Context, kind string) (int, error)

RunDue runs every item of kind that is due now, one after another, and returns how many runs it made. A periodic kind's timer calls it; so may a caller that need not wait for the timer, such as a test. A run that fails is retried after its backoff, never in the same pass, and an item asked for again during its run waits for the next pass: it is due again from the end of its run, after every item that was due before it, so meeting it again means the pass has taken everything else.

func (*Queue) WaitIdle

func (q *Queue) WaitIdle(ctx context.Context) error

WaitIdle returns once no item of a registered kind is pending or leased and no run is in progress on this node, for tests. Parked items do not count; an item that keeps failing keeps it waiting until ctx ends. A pending item of a periodic kind does not count either, since it waits for its timer by design; RunDue runs it.

Jump to

Keyboard shortcuts

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