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

worker

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: May 10, 2026 License: AGPL-3.0 Imports: 15 Imported by: 0

Documentation

Overview

Package worker drives the Postgres-backed job queue introduced in S14. The pool dispatches one Job per goroutine, claiming rows via FOR UPDATE SKIP LOCKED so concurrent workers don't double-process.

Job kinds, their payload schema, and their handlers live alongside this package in sub-packages (jobs/<kind>.go). The pool itself is kind-agnostic: a Handler is just a func that takes a payload and returns nil-or-error.

Index

Constants

View Source
const NotifyChannel = "shithub_jobs"

NotifyChannel is the Postgres LISTEN/NOTIFY channel the pool subscribes to so it wakes up immediately when a job is enqueued, instead of polling. Callers wrapping enqueue in a tx must NOTIFY inside the same tx so the notification only fires on commit.

Variables

View Source
var ErrPoison = errors.New("worker: poison job")

ErrPoison wraps a handler error that should NOT be retried. The pool jumps the job straight to MarkJobFailed instead of rescheduling.

Functions

func Backoff

func Backoff(attempts int, jitter func() float64) time.Duration

Backoff returns the delay before retrying a job that is about to be rescheduled. The formula is `30s * 2^attempts` capped at 1 hour, with ±20% jitter so a fleet doesn't synchronize retries on a sibling dependency outage.

`attempts` is the number of attempts already made (1-indexed: the just-failed attempt counts as 1).

func Enqueue

func Enqueue(ctx context.Context, db DBTX, kind Kind, payload any, opts EnqueueOptions) (int64, error)

Enqueue inserts a job row and returns its id. Callers running inside a transaction should pass the tx as db so the enqueue is rolled back alongside any related state changes; same goes for the NOTIFY (issued separately by the caller via Notify).

func Notify

func Notify(ctx context.Context, db DBTX) error

Notify wakes any LISTENing workers. Safe to call after a successful commit; if called inside a tx, the NOTIFY only delivers when the tx commits (Postgres semantics). Errors are non-fatal — workers also poll at a slow interval as a backstop.

func PoisonError

func PoisonError(cause error) error

PoisonError wraps cause as a poison error. The cause is preserved in last_error for operator inspection.

Types

type DBTX

type DBTX = workerdb.DBTX

DBTX matches the pgx interface that sqlc-generated methods accept (anything providing Exec/Query/QueryRow). The pool, a tx, and the helpers in dbtest all satisfy it.

type EnqueueOptions

type EnqueueOptions struct {
	RunAt       pgtype.Timestamptz
	MaxAttempts int32
}

EnqueueOptions tunes a single enqueue. RunAt zero means "now"; pass a future time to delay the first run. MaxAttempts zero means use the table default (5).

type Handler

type Handler func(ctx context.Context, payload json.RawMessage) error

Handler runs one job. The framework supplies the raw JSON payload; handlers Unmarshal into their own typed schema. A nil error reports success and the job is marked completed; any non-nil error triggers the backoff/retry path. ErrPoison is the explicit "do not retry" signal — useful when the input is malformed and retrying can't help.

type Kind

type Kind string

Kind is the canonical name of a job. Use lowercase letters and colon-separated namespaces (e.g. "push:process", "repo:size_recalc"). Kind doubles as the dispatch index — workers query `WHERE kind = $1` so adding new kinds doesn't disturb existing ones.

const (
	KindPushProcess    Kind = "push:process"
	KindRepoSizeRecalc Kind = "repo:size_recalc"
	KindJobsPurge      Kind = "jobs:purge_completed"
)

Built-in kinds shipped in S14.

const (
	KindPRSynchronize  Kind = "pr:synchronize"
	KindPRMergeability Kind = "pr:mergeability"
)

S22 pull-request kinds. Synchronize refreshes commits + files after a head-side push; mergeability runs the merge-tree probe.

(No async-merge kind: the POST .../merge handler executes the merge synchronously so the redirect lands on the merged state. If we add async merging later — for very large repos — re-introduce a KindPRMerge here and a matching jobs.PRMerge handler.)

const (
	KindRepoIndexCode      Kind = "repo:index_code"
	KindRepoIndexReconcile Kind = "repo:index_reconcile"
)

S28 code-search kinds. index_code re-indexes a repo's default branch (paths + content). Enqueued by push:process when the default branch advances; also by index_reconcile when drift between default_branch_oid and last_indexed_oid is detected.

const (
	KindLifecycleSweep Kind = "lifecycle:sweep"
)

S16 lifecycle housekeeping kind.

const (
	KindNotifyFanout Kind = "notify:fanout"
)

S29 notification kinds. notify:fanout drains the domain_events table past the persisted cursor and materializes inbox rows + (optional) emails. Self-throttling per FanoutBatch; loop-friendly (the handler returns the count so the pool can re-enqueue when a drain didn't catch up).

const (
	KindRepoForkClone Kind = "repo:fork_clone"
)

S27 fork kinds. fork_clone runs `git clone --bare --shared` for a freshly created fork shell; the fork's init_status flips from init_pending → initialized (or init_failed) on success/failure.

type Pool

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

Pool dispatches jobs from the queue. Construct via NewPool, register handlers via Register, run via Run.

func NewPool

func NewPool(db *pgxpool.Pool, cfg PoolConfig) *Pool

NewPool wires a pool against an open pgx pool. Callers register handlers before calling Run.

func (*Pool) Register

func (p *Pool) Register(kind Kind, h Handler)

Register associates a handler with a kind. Re-registering replaces the previous handler. Registration is goroutine-safe so test harnesses can swap handlers between runs.

func (*Pool) Run

func (p *Pool) Run(ctx context.Context) error

Run blocks until ctx is cancelled. Spawns cfg.Workers worker goroutines plus one LISTEN goroutine that fans out wake-ups. Returns nil after a clean drain; returns ctx.Err() if drain timed out.

type PoolConfig

type PoolConfig struct {
	Workers    int           // default 4
	IdlePoll   time.Duration // default 5s — backstop when LISTEN drops a wake
	JobTimeout time.Duration // default 5min, applied per-job via context
	InstanceID string        // default "<hostname>:<pid>"
	Logger     *slog.Logger  // default discards
}

PoolConfig configures Pool. Leave fields zero for the documented defaults.

Directories

Path Synopsis
Package jobs holds the concrete worker handlers wired into the pool at boot.
Package jobs holds the concrete worker handlers wired into the pool at boot.

Jump to

Keyboard shortcuts

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