Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

REST API and Admin UI

The arbiter-servant and arbiter-servant-ui packages provide a REST API and admin dashboard. Use them as standalone WAI applications or integrate them into an existing Servant API.

import Arbiter.Servant qualified as Servant

config <- Servant.initArbiterServer (Proxy @AppRegistry) connStr "arbiter"
Servant.runArbiterAPI 8080 config

Embed as a sub-route in an existing Servant application:

import Arbiter.Servant qualified as Servant
import Arbiter.Servant.UI qualified as ServantUI

type MyAPI =
  "api" :> MyBusinessRoutes
    :<|> "arbiter" :> (Servant.ArbiterAPI AppRegistry :<|> ServantUI.AdminUI)

See the arbiter-servant-ui haddocks for the UI's route type.

POST jobs and POST jobs/batch enqueue jobs. Services in other languages can use these endpoints without an Arbiter library. The admin UI uses the other per-queue endpoints for operator functions.

Endpoints

Per-queue endpoints under /api/v1/:queue/:

MethodPathDescription
GETjobsList jobs
POSTjobsInsert a job
POSTjobs/batchInsert multiple jobs
GETjobs/:idGet job by ID
DELETEjobs/:idCancel job (cascade-deletes children)
POSTjobs/:id/force-cancelCascade-delete and interrupt the running handler
POSTjobs/:id/promoteMake a delayed job immediately visible
POSTjobs/:id/move-to-dlqMove job to dead-letter queue
POSTclaimLease visible jobs, returning each job with its lease
POSTjobs/:id/ackComplete a job the lease still holds, storing its result
POSTjobs/:id/nackHand a job back without spending its attempt
POSTjobs/:id/extendPush out a held lease
POSTjobs/:id/suspendSuspend job
POSTjobs/:id/resumeResume suspended job
POSTjobs/:id/pause-childrenPause all visible children of a job
POSTjobs/:id/resume-childrenResume all suspended children
GETdlqList DLQ entries
POSTdlq/:id/retryRetry from DLQ
DELETEdlq/:idDelete from DLQ
POSTdlq/batch-deleteBatch delete multiple DLQ entries
GETarchiveList archived (completed) jobs
POSTarchive/:id/reenqueueRe-run an archived job as a fresh job
DELETEarchive/:idPurge one archive entry
POSTarchive/batch-deleteBatch purge archive entries
GETstatsQueue statistics
GETkindsList the payload variant labels the queue declares

Global endpoints under /api/v1/:

MethodPathDescription
GETqueuesList all registered queues
GETqueues/statsStatistics for every registered queue
GETqueues/:queue/detailsGet queue override details
POSTqueues/:queue/pausePause a queue (all workers stop claiming)
POSTqueues/:queue/resumeResume a paused queue
GETevents/streamSSE stream for real-time notifications
GETcron/schedulesList cron schedules
PATCHcron/schedules/:nameOverride cron expression at runtime
POSTcron/schedules/:name/runRun an enabled schedule once, out of band
GETworkersList registered workers
POSTworkers/:id/pausePause a single worker pool
POSTworkers/:id/resumeResume a single worker pool
GETrate-limitsList policies with bucket and throttle stats
GETrate-limits/:prefix/bucketsList a prefix's per-key buckets
PATCHrate-limits/:prefixSet or clear a policy's override params
POSTrate-limits/:prefix/resetReset (clear) a prefix's buckets
GETconcurrencyList pools with limit and in-flight stats
GETconcurrency/:prefix/keysList a pool's per-key in-flight counts
PATCHconcurrency/:prefixSet or clear a pool's override limit
POSTconcurrency/reconcileRepair the in-flight counts of every pool
POSTmaintenanceRun one gated maintenance pass
GEThealthReadiness check. Returns 503 when the database is unavailable
GEThealth/liveLiveness check. Does not query the database

Consuming over HTTP

POST claim applies the worker-pool claim operation. It uses admission tokens, increments the attempt count, records a claimant, and makes each job invisible for the lease period. A paused queue does not return leases. The pause applies to HTTP consumers and worker pools.

POST /api/v1/email_queue/claim
{"maxJobs": 5, "leaseSeconds": 60}

maxJobs defaults to 1 and clamps to 1000. leaseSeconds defaults to 60 and clamps to 3600.

Each response job contains claimSeq and claimedBy. These fields identify the lease. Each finalization request must include them:

POST /api/v1/email_queue/jobs/41/ack
{"claimSeq": 7, "claimedBy": "0f5e...c31"}

On a queue declared with QueueWithResult, ack also takes the result:

POST /api/v1/email_queue/jobs/41/ack
{"claimSeq": 7, "claimedBy": "0f5e...c31", "result": ["delivered"]}

Arbiter stores the result in the parent rollup for a child job, or in the archive entry for an archived root job. This is the same behavior as ackWith. A body that does not match the queue result type returns 400. Omit result to store no result. Mounting this route requires FromJSON and ToJSON for the result type.

ack completes the job. nack restores the used attempt and keeps the job invisible for the remainder of its lease. extend sets a later lease expiration, as a worker heartbeat does. The request body requires seconds. Arbiter limits the value to 3600 and measures it from the request time. If the lease fields do not match the row, the endpoint returns 409. A previous lease holder cannot ack a reclaimed job.

These routes finalize leases created by POST claim. They return 409 for a lease held by a worker pool.

The server does not renew an HTTP lease automatically. The consumer must call extend. After an unextended lease expires, another consumer can claim the job. This behavior provides at-least-once delivery after a consumer failure.

[!IMPORTANT] Arbiter does not authenticate claim or finalization requests. Add authentication before exposing these routes. Use WAI middleware, a Servant authentication combinator, or an authenticating proxy.

Maintenance

POST maintenance performs one pass of schema maintenance. It processes stale workers, exhausted and cancelled jobs, rate-limit buckets, concurrency counts, archive retention, and group summaries.

Concurrent callers cannot run the same operation. The default has no minimum interval. Set maintenanceInterval in the server configuration to define the minimum interval for each operation. maintenanceTimeout limits one statement.

maintenanceSparseInterval defines a separate minimum interval for schema-wide operations. maintenanceBucketIdle specifies how long a rate-limit bucket must be inactive before removal.

The response gives the affected row count for each completed operation and the names of failed operations. Operations absent from both lists were skipped:

{"ops": {"sweep-stale-workers": 2, "purge-archives": 140}, "failed": []}

Worker pools run this maintenance in their reaper. Use the endpoint when a deployment does not run a worker pool.