Documentation
¶
Overview ¶
Package queue is the job queue over the application's database.
The contract lives in the core, in framework/jobs: Job, Handler, Queue and the Worker. This package is one implementation of it, and it is the default one for a reason -- it needs nothing installed. The jobs table sits in the database the application already has, and a job is committed by the same transaction as the row it is about.
That last part is what a Redis queue cannot offer. Pushing a job inside data.Transaction means the job exists if and only if the write did, which is the outbox guarantee applied to work instead of to events.
For volume beyond what a table handles comfortably, github.com/arandu-io/queue/kv is the same contract over RESP. Same Worker, same handlers, one line different in main.
Index ¶
- type CreateJobsTable
- type Module
- type Store
- func (s *Store) Ack(ctx context.Context, j jobs.Job) error
- func (s *Store) Fail(ctx context.Context, j jobs.Job, cause error, retryAt time.Time, park bool) error
- func (s *Store) Oldest(ctx context.Context, queue string) (time.Duration, error)
- func (s *Store) Parked(ctx context.Context, limit int) ([]jobs.Job, error)
- func (s *Store) Pending(ctx context.Context, queue string) (int, error)
- func (s *Store) Push(ctx context.Context, g security.Grant, j jobs.Job) error
- func (s *Store) Reserve(ctx context.Context, queue string, n int, lease time.Duration) ([]jobs.Job, error)
- func (s *Store) Retry(ctx context.Context, id string) error
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type CreateJobsTable ¶ added in v0.4.0
type CreateJobsTable struct{ migrations.BaseMigration }
CreateJobsTable is the jobs table this driver reads and writes.
func (CreateJobsTable) Down ¶ added in v0.4.0
func (CreateJobsTable) Down(ctx context.Context, conn migrations.Connection) error
Down drops the table, which takes its indexes with it.
func (CreateJobsTable) GetName ¶ added in v0.4.0
func (CreateJobsTable) GetName() string
GetName is the migration's identity, and carries its order.
func (CreateJobsTable) Up ¶ added in v0.4.0
func (CreateJobsTable) Up(ctx context.Context, conn migrations.Connection) error
Up creates the table and the two indexes the reserve and diagnosis queries need.
One statement per call: the connection sends what it is given, and a pair separated by a semicolon only reaches a server that was asked for multi-statement support.
type Module ¶
type Module struct {
// contains filtered or unexported fields
}
Module brings the jobs table, and reports on the queue.
It registers no routes and runs no worker: the worker is `aru work`, a separate process from the same image. What this module owns is the schema and the answer to "is anything draining this".
func NewModule ¶
NewModule returns the module.
Name the queues the application actually uses. A queue nobody watches is a queue that can stop draining without anyone noticing, which is the failure this module exists to make visible.
func (*Module) Diagnose ¶
Diagnose reports a backlog and a dead letter queue, on the error page.
Next to the failure somebody is already looking at, which is the moment they are most likely to act on it.
func (*Module) Migrations ¶
func (*Module) Migrations() []migrations.Migration
Migrations returns the jobs table.
The module is asked rather than registering itself: an application on a different driver has no jobs table, and a package-level init would create one for every project that imports this one.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is the queue backed by the application's database.
func (*Store) Ack ¶
Ack removes a finished job.
Deleted rather than marked done. A jobs table that keeps every job ever run is a table that needs its own cleanup job, and the history that matters -- what ran, how long it took, what it queried -- is on the console.
func (*Store) Fail ¶
func (s *Store) Fail(ctx context.Context, j jobs.Job, cause error, retryAt time.Time, park bool) error
Fail records the failure and schedules the retry, or parks the job.
func (*Store) Oldest ¶
Oldest is how long the oldest waiting job has been waiting.
A stopped worker looks exactly like an idle one, and this is what tells them apart. It feeds the health check.
func (*Store) Push ¶
Push adds a job.
Inside data.Transaction it joins it, which is the property this driver exists for: the job is committed by the same transaction as the row it describes, so it cannot refer to a write that rolled back.
func (*Store) Reserve ¶
func (s *Store) Reserve(ctx context.Context, queue string, n int, lease time.Duration) ([]jobs.Job, error)
Reserve takes jobs off the queue and hides them for the lease.
Two statements rather than one, and the reason is portability: the tight form is UPDATE ... RETURNING with a FOR UPDATE SKIP LOCKED subquery, which Postgres has and SQLite does not. Selecting the candidates and then claiming each one by its id -- with reserved_until in the WHERE -- is correct on every engine, because the claim itself is the compare-and-set.
The cost is that two workers can pick the same candidate and one of them loses the claim. It gets nothing back, which is exactly right.