| Safe Haskell | None |
|---|---|
| Language | GHC2024 |
Arbiter.Servant
Description
Servant REST API for Arbiter: queue operations and remote job consumers. See
ArbiterAPI for the route tree.
Quick Start
import Arbiter.Servant import Arbiter.Simple (createSimpleEnv, runSimpleDb) import Data.Proxy (Proxy(..)) main :: IO () main = do -- Run migrations with event streaming enabled before starting the server. -- The server runs over any backend env. env <- createSimpleEnv (Proxy @MyRegistry) connStr "arbiter" config <- createArbiterServer (runSimpleDb env) -- Start API server on port 8080 runArbiterAPI 8080 config
Synopsis
- data QueueSpec = QueueWithResult Symbol Type Type
- type Queue (table :: Symbol) payload = 'QueueWithResult table payload ()
- arbiterServer :: forall (registry :: JobPayloadRegistry) (m :: Type -> Type). (BuildServer registry registry, HasRegistry m registry) => ArbiterServerConfig m registry -> ServerT (ArbiterAPI registry) Handler
- arbiterServerHoisted :: forall (registry :: JobPayloadRegistry) (m :: Type -> Type) n. (BuildServer registry registry, HasRegistry m registry, HasServer (ArbiterAPI registry) ('[] :: [Type])) => (forall x. Handler x -> n x) -> ArbiterServerConfig m registry -> ServerT (ArbiterAPI registry) n
- arbiterApp :: forall (registry :: JobPayloadRegistry) (m :: Type -> Type). (BuildServer registry registry, HasRegistry m registry, HasServer (ArbiterAPI registry) ('[] :: [Type])) => ArbiterServerConfig m registry -> Application
- runArbiterAPI :: forall (registry :: JobPayloadRegistry) (m :: Type -> Type). (BuildServer registry registry, HasRegistry m registry, HasServer (ArbiterAPI registry) ('[] :: [Type])) => Port -> ArbiterServerConfig m registry -> IO ()
- data ArbiterServerConfig (m :: Type -> Type) (registry :: JobPayloadRegistry) = ArbiterServerConfig {
- serverRun :: forall a. m a -> IO a
- serverSchema :: Text
- enableSSE :: Bool
- rateLimitPoliciesCache :: CacheCell RateLimitPoliciesResponse
- concurrencyPoliciesCache :: CacheCell ConcurrencyPoliciesResponse
- allQueueStatsCache :: CacheCell AllStatsResponse
- queueStatsCache :: CacheCell StatsResponse
- statsCacheTtl :: NominalDiffTime
- healthCache :: CacheCell HealthResponse
- maintenanceInterval :: NominalDiffTime
- maintenanceSparseInterval :: NominalDiffTime
- maintenanceBucketIdle :: NominalDiffTime
- maintenanceTimeout :: NominalDiffTime
- serverLogConfig :: LogConfig
- deadLetterGates :: FailureGates
- createArbiterServer :: forall m (registry :: JobPayloadRegistry). HasRegistry m registry => (forall a. m a -> IO a) -> IO (ArbiterServerConfig m registry)
- defaultStatsCacheTtl :: NominalDiffTime
- defaultMaintenanceInterval :: NominalDiffTime
- defaultMaintenanceBucketIdle :: NominalDiffTime
- defaultMaintenanceSparseInterval :: NominalDiffTime
- defaultMaintenanceTimeout :: NominalDiffTime
- class BuildServer (registry :: JobPayloadRegistry) (reg :: JobPayloadRegistry) where
- buildServer :: forall (m :: Type -> Type). HasRegistry m registry => ArbiterServerConfig m registry -> ServerT (RegistryToAPI reg) Handler
- data CacheCell a
- type ArbiterAPI (registry :: JobPayloadRegistry) = "api" :> RegistryToAPI registry
- type family RegistryToAPI (registry :: JobPayloadRegistry) where ...
- data TableAPI payload result (mode :: k) = TableAPI {
- jobs :: mode :- ("jobs" :> NamedRoutes (JobsAPI payload result :: Type -> Type))
- claimJobs :: mode :- (Summary "Claim jobs" :> (Description "Leases up to maxJobs visible jobs for leaseSeconds. Each job carries the claimSeq and claimedBy that ack, nack and extend need. The server does not renew the lease. A paused queue returns no jobs." :> ("claim" :> (ReqBody '[JSON] ClaimRequest :> Post '[JSON] (ClaimResponse payload)))))
- dlq :: mode :- ("dlq" :> NamedRoutes (DLQAPI payload :: Type -> Type))
- archive :: mode :- ("archive" :> NamedRoutes (ArchiveAPI payload :: Type -> Type))
- stats :: mode :- ("stats" :> NamedRoutes (StatsAPI :: Type -> Type))
- listKinds :: mode :- (Summary "List payload kinds" :> ("kinds" :> Get '[JSON] [Text]))
- listGroups :: mode :- (Summary "List open groups" :> (Description "The largest groups come first." :> ("groups" :> (QueryParam "limit" PageLimit :> (QueryParam "offset" Int :> (QueryParam "group_key" Text :> Get '[JSON] GroupsResponse))))))
- getDetails :: mode :- (Summary "Show a queue's pause state and DLQ retention" :> (Description "Null when the queue has no row. Migrations create one for each queue." :> ("details" :> Get '[JSON] (Maybe QueueRow))))
- pauseQueue :: mode :- (Summary "Pause a queue" :> (Description "Workers do not claim from the queue. Claims through this API return no jobs." :> ("pause" :> PostNoContent)))
- resumeQueue :: mode :- (Summary "Resume a queue" :> ("resume" :> PostNoContent))
- setDLQRetention :: mode :- (Summary "Set a queue's DLQ retention" :> (Description "The reaper deletes the queue's DLQ jobs that failed more than retentionSeconds ago. A null retentionSeconds keeps them. Every worker pool sharing the schema applies it." :> (Throws 400 "retentionSeconds is not positive." :> ("dlq-retention" :> (ReqBody '[JSON] DLQRetentionRequest :> PutNoContent)))))
- type SharedAPI = ("queues" :> NamedRoutes (QueuesAPI :: Type -> Type)) :<|> (("maintenance" :> NamedRoutes (MaintenanceAPI :: Type -> Type)) :<|> (("events" :> EventsAPI) :<|> (("cron" :> NamedRoutes (CronAPI :: Type -> Type)) :<|> (("workers" :> NamedRoutes (WorkersAPI :: Type -> Type)) :<|> (("rate-limits" :> NamedRoutes (RateLimitsAPI :: Type -> Type)) :<|> (("concurrency" :> NamedRoutes (ConcurrencyAPI :: Type -> Type)) :<|> ("health" :> NamedRoutes (HealthAPI :: Type -> Type))))))))
- type PayloadEditNote = "Optional. A payload replaces the stored payload, and the kind, rate-limit and concurrency columns come from it again. An empty body keeps the stored payload."
- type LeaseRefusal = "This lease does not hold the job, a registered worker holds it, the job is suspended, or the job was force-cancelled."
- data Throws' (status :: Nat) (reason :: Symbol) (body :: Maybe Type)
- type Throws (status :: Nat) (reason :: Symbol) = Throws' status reason ('Nothing :: Maybe Type)
- type ThrowsBody (status :: Nat) (reason :: Symbol) body = Throws' status reason ('Just body)
- type EventsAPI = "stream" :> Raw
- data QueuesAPI (mode :: k) = QueuesAPI {
- listQueues :: mode :- (Summary "List queues" :> Get '[JSON] QueuesResponse)
- getAllStats :: mode :- (Summary "Show stats for every queue" :> ("stats" :> Get '[JSON] AllStatsResponse))
- data JobsAPI payload result (mode :: k) = JobsAPI {
- listJobs :: mode :- (Summary "List jobs" :> (Description "Filters combine. The payload filter searches the payload text." :> (QueryParam "limit" PageLimit :> (QueryParam "offset" Int :> (QueryParam "group_key" Text :> (QueryParam "parent_id" Int64 :> (QueryParam "job_id" Int64 :> (QueryFlag "roots_only" :> (QueryParam "status" JobStatus :> (QueryParam "claimed_by" UUID :> (QueryParam "kind" Text :> (QueryParam "payload" Text :> (QueryParam "rate_limit_prefix" Text :> (QueryParam "concurrency_prefix" Text :> (QueryParam "sort_by" JobSortColumn :> (QueryParam "sort_dir" SortDir :> Get '[JSON] (JobsResponse payload)))))))))))))))))
- insertJob :: mode :- (Summary "Enqueue a job" :> (Description "A duplicate of an ignore dedup key returns the job that exists. A duplicate of a replace dedup key replaces the job in the queue." :> (Throws 409 "A replace dedup key matched a job that is in flight, flagged for cancel, or has children." :> (Throws 409 "An ignore dedup key matched a job that was deleted before the server could read it." :> (ReqBody '[JSON] (ApiJobWrite payload) :> Post '[JSON] (JobResponse (JobRead payload)))))))
- insertJobsBatch :: mode :- (Summary "Enqueue many jobs" :> (Description "Returns the jobs inserted or replaced. The response omits a job that an ignore dedup key skips, and a job that a replace dedup key cannot replace." :> ("batch" :> (ReqBody '[JSON] (BatchInsertRequest payload) :> Post '[JSON] (BatchInsertResponse payload)))))
- getJob :: mode :- (Summary "Show a job" :> (Description "The response includes the derived status." :> (Capture "id" Int64 :> Get '[JSON] (JobResponse (ApiJobWithStatus (Stored payload))))))
- cancelJob :: mode :- (Summary "Cancel a job and its descendants" :> (Description "Deletes the job and every descendant, also the jobs in flight. The handler of a job in flight continues, and its ack finds no job. Use force-cancel to stop the handler." :> (Capture "id" Int64 :> DeleteNoContent)))
- forceCancelJob :: mode :- (Summary "Cancel a job and interrupt its handlers" :> (Description "Deletes the jobs in the tree that are not in flight. A job in flight receives a cancel flag and cannot be claimed again. A worker pool stops its handler. An HTTP claimant with a live lease receives 409 on its next ack, nack or extend, until the reaper deletes the job. Then it receives 404. A claimant whose lease expired before the force-cancel receives 404." :> (Capture "id" Int64 :> ("force-cancel" :> PostNoContent))))
- ackClaimedJob :: mode :- (Summary "Complete a held job" :> (Description "Send the claimSeq and claimedBy from the claim. The server stores the optional result for the parent rollup or the archive." :> (Throws 409 LeaseRefusal :> (Capture "id" Int64 :> ("ack" :> (ReqBody '[JSON] (AckRequest result) :> PostNoContent))))))
- nackClaimedJob :: mode :- (Summary "Return a held job" :> (Description "Restores the attempt that the claim used. The job becomes claimable when its lease expires." :> (Throws 409 LeaseRefusal :> (Capture "id" Int64 :> ("nack" :> (ReqBody '[JSON] JobLease :> PostNoContent))))))
- extendClaimedJob :: mode :- (Summary "Extend a held lease" :> (Description "Sets the lease to expire leaseSeconds from now." :> (Throws 409 LeaseRefusal :> (Capture "id" Int64 :> ("extend" :> (ReqBody '[JSON] ExtendRequest :> PostNoContent))))))
- promoteJob :: mode :- (Summary "Make a job visible now" :> (Throws 409 "The job is already visible, suspended, in flight, or flagged for cancel." :> (Capture "id" Int64 :> ("promote" :> PostNoContent))))
- rescheduleJob :: mode :- (Summary "Set when a job becomes visible" :> (Throws 409 "The job is in flight, suspended, flagged for cancel, or out of attempts, or another operation changed it." :> (Capture "id" Int64 :> ("reschedule" :> (ReqBody '[JSON] RescheduleRequest :> PostNoContent)))))
- moveToDLQ :: mode :- (Summary "Move a job to the DLQ" :> (Description "A rollup takes its descendants with it. A job in flight is moved too. Its handler continues, and its ack finds no job." :> (Throws 409 "Another operation changed or deleted the job between the read and the move." :> (Capture "id" Int64 :> ("move-to-dlq" :> PostNoContent)))))
- pauseChildren :: mode :- (Summary "Suspend the visible descendants of a job" :> (Description "The operation skips descendants that are in flight, delayed or throttled. Succeeds when nothing is suspended. 404 when the job is gone." :> (Capture "id" Int64 :> ("pause-children" :> PostNoContent))))
- resumeChildren :: mode :- (Summary "Resume the suspended descendants of a job" :> (Description "A finalizer with children in the queue stays suspended. Succeeds when nothing is resumed. 404 when the job is gone." :> (Capture "id" Int64 :> ("resume-children" :> PostNoContent))))
- suspendJob :: mode :- (Summary "Suspend a job" :> (Description "A suspended job cannot be claimed." :> (Throws 409 "The job is already suspended, or it is in flight." :> (Capture "id" Int64 :> ("suspend" :> PostNoContent)))))
- resumeJob :: mode :- (Summary "Resume a suspended job" :> (Throws 409 "The job is not suspended, it is a finalizer with children in the queue, or another operation changed it." :> (Capture "id" Int64 :> ("resume" :> PostNoContent))))
- data DLQAPI payload (mode :: k) = DLQAPI {
- listDLQ :: mode :- (Summary "List dead-lettered jobs" :> (Description "The payload and error filters search the payload and the last error." :> (QueryParam "limit" PageLimit :> (QueryParam "offset" Int :> (QueryParam "parent_id" Int64 :> (QueryParam "job_id" Int64 :> (QueryParam "group_key" Text :> (QueryParam "kind" Text :> (QueryParam "payload" Text :> (QueryParam "error" Text :> (QueryParam "sort_by" DLQSortColumn :> (QueryParam "sort_dir" SortDir :> Get '[JSON] (DLQResponse payload)))))))))))))
- retryFromDLQ :: mode :- (Summary "Retry a dead-lettered job" :> (Description "Moves the job back to the queue." :> (Throws 409 "The parent of the job is gone from the queue and the DLQ." :> (Capture "id" Int64 :> ("retry" :> (ReqBody' '[Description PayloadEditNote] '[OptionalJSON] (Maybe (PayloadEdit payload)) :> PostNoContent))))))
- deleteDLQ :: mode :- (Summary "Delete a dead-lettered job" :> (Description "Resumes its parent when no child of the parent is left in the queue." :> (Capture "id" Int64 :> DeleteNoContent)))
- deleteDLQBatch :: mode :- (Summary "Delete dead-lettered jobs" :> (Description "Returns the number deleted. The server skips unknown ids." :> ("batch-delete" :> (ReqBody '[JSON] BatchDeleteRequest :> Post '[JSON] BatchDeleteResponse))))
- retryDLQBatch :: mode :- (Summary "Retry dead-lettered jobs" :> (Description "Retries each job's tree in its own transaction. Returns the number of ids whose retry restored a tree. The server skips unknown ids and ids restored with an earlier id's tree." :> ("batch-retry" :> (ReqBody '[JSON] BatchRetryRequest :> Post '[JSON] BatchRetryResponse))))
- retryDLQMatching :: mode :- (Summary "Retry every matching dead-lettered job" :> (Description "Retries every job the filters match, oldest first, as batch-retry does. With no filters it retries the whole DLQ. The payload and error filters search the payload and the last error." :> ("retry-matching" :> (QueryParam "parent_id" Int64 :> (QueryParam "job_id" Int64 :> (QueryParam "group_key" Text :> (QueryParam "kind" Text :> (QueryParam "payload" Text :> (QueryParam "error" Text :> Post '[JSON] BatchRetryResponse)))))))))
- data ArchiveAPI payload (mode :: k) = ArchiveAPI {
- listArchive :: mode :- (Summary "List archived jobs" :> (Description "The payload filter searches the payload text." :> (QueryParam "limit" PageLimit :> (QueryParam "offset" Int :> (QueryParam "parent_id" Int64 :> (QueryParam "job_id" Int64 :> (QueryParam "group_key" Text :> (QueryParam "kind" Text :> (QueryParam "payload" Text :> (QueryParam "completed_after" UTCTime :> (QueryParam "completed_before" UTCTime :> (QueryParam "sort_by" ArchiveSortColumn :> (QueryParam "sort_dir" SortDir :> Get '[JSON] (ArchiveResponse payload))))))))))))))
- reEnqueueArchive :: mode :- (Summary "Run an archived job again" :> (Description "Inserts a new job. The archive entry stays." :> (Capture "id" Int64 :> ("reenqueue" :> (ReqBody' '[Description PayloadEditNote] '[OptionalJSON] (Maybe (PayloadEdit payload)) :> PostNoContent)))))
- deleteArchive :: mode :- (Summary "Delete an archived job" :> (Capture "id" Int64 :> DeleteNoContent))
- deleteArchiveBatch :: mode :- (Summary "Delete archived jobs" :> (Description "Returns the number deleted. The server skips unknown ids." :> ("batch-delete" :> (ReqBody '[JSON] BatchDeleteRequest :> Post '[JSON] BatchDeleteResponse))))
- data StatsAPI (mode :: k) = StatsAPI {}
- newtype MaintenanceAPI (mode :: k) = MaintenanceAPI {
- runMaintenance :: mode :- (Summary "Run a maintenance pass" :> (Description "Runs the work of the reaper once. An operation that another caller runs at the same time is skipped and is not in the response." :> Post '[JSON] MaintenanceResponse))
- data CronAPI (mode :: k) = CronAPI {
- listSchedules :: mode :- (Summary "List cron schedules" :> ("schedules" :> (QueryParam "queue" Text :> Get '[JSON] CronSchedulesResponse)))
- updateSchedule :: mode :- (Summary "Override a cron schedule" :> (Description "A null field clears its override. An absent field keeps it." :> (Throws 400 "An override is not valid." :> ("schedules" :> (Capture "name" Text :> (ReqBody '[JSON] CronScheduleUpdate :> Patch '[JSON] CronScheduleView))))))
- runSchedule :: mode :- (Summary "Run a cron schedule now" :> (Throws 409 "The schedule is disabled, or it already has a run that waits to start." :> ("schedules" :> (Capture "name" Text :> ("run" :> PostNoContent)))))
- data WorkersAPI (mode :: k) = WorkersAPI {
- listWorkers :: mode :- (Summary "List workers" :> (QueryParam "queue" Text :> (QueryParam "live" Double :> Get '[JSON] WorkersResponse)))
- pauseWorker :: mode :- (Summary "Pause a worker" :> (Description "The worker does not claim new jobs." :> (Capture "id" UUID :> ("pause" :> PostNoContent))))
- resumeWorker :: mode :- (Summary "Resume a worker" :> (Capture "id" UUID :> ("resume" :> PostNoContent)))
- data HealthAPI (mode :: k) = HealthAPI {
- getHealth :: mode :- (Summary "Check readiness" :> (ThrowsBody 503 "The database is not reachable." HealthResponse :> Get '[JSON] HealthResponse))
- getLiveness :: mode :- (Summary "Check liveness" :> ("live" :> Get '[JSON] LivenessResponse))
- data RateLimitsAPI (mode :: k) = RateLimitsAPI {
- listRateLimits :: mode :- (Summary "List rate-limit policies" :> Get '[JSON] RateLimitPoliciesResponse)
- listRateLimitBuckets :: mode :- (Summary "List the buckets of a rate-limit policy" :> (Capture "prefix" Text :> ("buckets" :> (QueryParam "limit" KeyPageLimit :> (QueryParam "offset" Int :> Get '[JSON] RateLimitBucketsResponse)))))
- updateRateLimitPolicy :: mode :- (Summary "Override a rate-limit policy" :> (Description "A null field clears its override. An absent field keeps it." :> (Throws 400 "An override value is not valid." :> (Capture "prefix" Text :> (ReqBody '[JSON] RateLimitPolicyUpdate :> Patch '[JSON] RateLimitPolicyView)))))
- resetRateLimitBuckets :: mode :- (Summary "Refill the buckets of a rate-limit policy" :> (Description "Refills every bucket under the prefix to full. Returns the number refilled." :> (Capture "prefix" Text :> ("reset" :> Post '[JSON] RateLimitResetResponse))))
- addRateLimitTokens :: mode :- (Summary "Add tokens to a rate-limit bucket" :> (Description "Wakes the throttled jobs of the key." :> (Throws 400 "The token count is 0 or less, or the key is not under the prefix." :> (Capture "prefix" Text :> ("buckets" :> (Capture "key" Text :> ("tokens" :> (ReqBody '[JSON] AddTokensRequest :> Post '[JSON] AddTokensResponse))))))))
- pruneRateLimitBuckets :: mode :- (Summary "Prune idle rate-limit buckets" :> (Throws 400 "The idle value is negative." :> ("prune" :> (QueryParam "idle" Double :> Post '[JSON] PruneResponse))))
- data ConcurrencyAPI (mode :: k) = ConcurrencyAPI {
- listConcurrency :: mode :- (Summary "List concurrency policies" :> Get '[JSON] ConcurrencyPoliciesResponse)
- listConcurrencyKeys :: mode :- (Summary "List the keys of a concurrency policy" :> (Capture "prefix" Text :> ("keys" :> (QueryParam "limit" KeyPageLimit :> (QueryParam "offset" Int :> Get '[JSON] ConcurrencyKeysResponse)))))
- updateConcurrencyPolicy :: mode :- (Summary "Override a concurrency limit" :> (Description "A null overrideLimit clears the override. An absent one keeps it." :> (Throws 400 "The override limit is negative." :> (Capture "prefix" Text :> (ReqBody '[JSON] ConcurrencyPolicyUpdate :> Patch '[JSON] ConcurrencyPolicyView)))))
- reconcileConcurrency :: mode :- (Summary "Recount in-flight jobs per concurrency key" :> (Description "Repairs each in-flight count from the live jobs. Returns the rows repaired." :> ("reconcile" :> Post '[JSON] ConcurrencyReconcileResponse)))
- pruneConcurrencyKeys :: mode :- (Summary "Prune drained concurrency keys" :> (Description "Deletes keys with no live job." :> ("prune" :> Post '[JSON] PruneResponse)))
- data JobSortColumn
- data DLQSortColumn
- data ArchiveSortColumn
- data SortDir
- module Arbiter.Servant.Types
Registry
A queue's table name, payload type, and handler result type. A type data
constructor. It takes no promotion tick.
Constructors
| QueueWithResult Symbol Type Type |
Instances
type Queue (table :: Symbol) payload = 'QueueWithResult table payload ()#
A queue whose handlers store no result. A module with its own Queue type
needs import Arbiter.Core hiding (Queue) or a qualified import.
Server
arbiterServer :: forall (registry :: JobPayloadRegistry) (m :: Type -> Type). (BuildServer registry registry, HasRegistry m registry) => ArbiterServerConfig m registry -> ServerT (ArbiterAPI registry) HandlerSource #
Complete Arbiter server at /api/....
arbiterServerHoisted :: forall (registry :: JobPayloadRegistry) (m :: Type -> Type) n. (BuildServer registry registry, HasRegistry m registry, HasServer (ArbiterAPI registry) ('[] :: [Type])) => (forall x. Handler x -> n x) -> ArbiterServerConfig m registry -> ServerT (ArbiterAPI registry) nSource #
Hoisted server for integration into a route tree using a custom monad.
arbiterApp :: forall (registry :: JobPayloadRegistry) (m :: Type -> Type). (BuildServer registry registry, HasRegistry m registry, HasServer (ArbiterAPI registry) ('[] :: [Type])) => ArbiterServerConfig m registry -> ApplicationSource #
Convert to WAI Application.
runArbiterAPI :: forall (registry :: JobPayloadRegistry) (m :: Type -> Type). (BuildServer registry registry, HasRegistry m registry, HasServer (ArbiterAPI registry) ('[] :: [Type])) => Port -> ArbiterServerConfig m registry -> IO ()Source #
Run the API server on a port. Prints a start line to stdout.
data ArbiterServerConfig (m :: Type -> Type) (registry :: JobPayloadRegistry)Source #
Configuration for the API server. m is the backend monad every handler's
statements run in. createArbiterServer fills the cache fields.
Constructors
| ArbiterServerConfig | |
Fields
| |
createArbiterServer :: forall m (registry :: JobPayloadRegistry). HasRegistry m registry => (forall a. m a -> IO a) -> IO (ArbiterServerConfig m registry)Source #
Create an ArbiterServerConfig over a backend runner. SSE needs the
enableEventStreaming migration option and a backend with a listener.
defaultStatsCacheTtl :: NominalDiffTimeSource #
Stats are read live by default.
defaultMaintenanceInterval :: NominalDiffTimeSource #
No minimum gap. Each call runs every ordinary operation. Concurrent callers exclude each other on the gate.
defaultMaintenanceBucketIdle :: NominalDiffTime#
Age after which an idle rate-limit bucket is pruned.
defaultMaintenanceSparseInterval :: NominalDiffTime#
Gap the bucket prune and the concurrency reconcile-and-prune keep.
defaultMaintenanceTimeout :: NominalDiffTime#
Statement timeout for one maintenance operation.
class BuildServer (registry :: JobPayloadRegistry) (reg :: JobPayloadRegistry) whereSource #
Builds a registry's per-queue server implementations. registry is the whole
registry. reg is the part still to build. Each result type needs FromJSON and an
EncodeJobResult instance. Each payload type needs JobPayload.
Methods
buildServer :: forall (m :: Type -> Type). HasRegistry m registry => ArbiterServerConfig m registry -> ServerT (RegistryToAPI reg) HandlerSource #
The server for the queues in reg, then the shared routes.
Instances
| (RegistryAdmissionPolicies registry, RegistryTables registry) => BuildServer registry ('[] :: [QueueSpec]) Source # | |
Defined in Arbiter.Servant.Server Methods buildServer :: forall (m :: Type -> Type). HasRegistry m registry => ArbiterServerConfig m registry -> ServerT (RegistryToAPI ('[] :: [QueueSpec])) HandlerSource # | |
| (BuildServer registry rest, EncodeJobResult (SpecResult spec), JobPayload (SpecPayload spec), KnownSymbol (SpecName spec)) => BuildServer registry (spec ': rest) Source # | |
Defined in Arbiter.Servant.Server Methods buildServer :: forall (m :: Type -> Type). HasRegistry m registry => ArbiterServerConfig m registry -> ServerT (RegistryToAPI (spec ': rest)) HandlerSource # | |
Keyed TTL cache. createArbiterServer creates each cell.
API types
type ArbiterAPI (registry :: JobPayloadRegistry) = "api" :> RegistryToAPI registrySource #
Top-level Arbiter API, mounted at /api. The route tree under that
prefix is generated from the registry. See RegistryToAPI for the shape.
type family RegistryToAPI (registry :: JobPayloadRegistry) where ...Source #
A TableAPI route per registry entry, followed by the shared
top-level routes.
Equations
| RegistryToAPI ('[] :: [QueueSpec]) = SharedAPI | |
| RegistryToAPI (spec ': rest) = ("queues" :> (SpecName spec :> NamedRoutes (TableAPI (SpecPayload spec) (SpecResult spec) :: Type -> Type))) :<|> RegistryToAPI rest |
data TableAPI payload result (mode :: k)Source #
One queue's routes.
Constructors
| TableAPI | |
Fields
| |
Instances
| Generic (TableAPI payload result mode) Source # | |||||
Defined in Arbiter.Servant.API Associated Types
| |||||
| type Rep (TableAPI payload result mode) Source # | |||||
Defined in Arbiter.Servant.API type Rep (TableAPI payload result mode) = D1 ('MetaData "TableAPI" "Arbiter.Servant.API" "arbiter-servant-0.1.0.0-inplace" 'False) (C1 ('MetaCons "TableAPI" 'PrefixI 'True) (((S1 ('MetaSel ('Just "jobs") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- ("jobs" :> NamedRoutes (JobsAPI payload result :: Type -> Type)))) :*: S1 ('MetaSel ('Just "claimJobs") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Claim jobs" :> (Description "Leases up to maxJobs visible jobs for leaseSeconds. Each job carries the claimSeq and claimedBy that ack, nack and extend need. The server does not renew the lease. A paused queue returns no jobs." :> ("claim" :> (ReqBody '[JSON] ClaimRequest :> Post '[JSON] (ClaimResponse payload)))))))) :*: (S1 ('MetaSel ('Just "dlq") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- ("dlq" :> NamedRoutes (DLQAPI payload :: Type -> Type)))) :*: (S1 ('MetaSel ('Just "archive") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- ("archive" :> NamedRoutes (ArchiveAPI payload :: Type -> Type)))) :*: S1 ('MetaSel ('Just "stats") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- ("stats" :> NamedRoutes (StatsAPI :: Type -> Type))))))) :*: ((S1 ('MetaSel ('Just "listKinds") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "List payload kinds" :> ("kinds" :> Get '[JSON] [Text])))) :*: (S1 ('MetaSel ('Just "listGroups") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "List open groups" :> (Description "The largest groups come first." :> ("groups" :> (QueryParam "limit" PageLimit :> (QueryParam "offset" Int :> (QueryParam "group_key" Text :> Get '[JSON] GroupsResponse)))))))) :*: S1 ('MetaSel ('Just "getDetails") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Show a queue's pause state and DLQ retention" :> (Description "Null when the queue has no row. Migrations create one for each queue." :> ("details" :> Get '[JSON] (Maybe QueueRow)))))))) :*: (S1 ('MetaSel ('Just "pauseQueue") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Pause a queue" :> (Description "Workers do not claim from the queue. Claims through this API return no jobs." :> ("pause" :> PostNoContent))))) :*: (S1 ('MetaSel ('Just "resumeQueue") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Resume a queue" :> ("resume" :> PostNoContent)))) :*: S1 ('MetaSel ('Just "setDLQRetention") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Set a queue's DLQ retention" :> (Description "The reaper deletes the queue's DLQ jobs that failed more than retentionSeconds ago. A null retentionSeconds keeps them. Every worker pool sharing the schema applies it." :> (Throws 400 "retentionSeconds is not positive." :> ("dlq-retention" :> (ReqBody '[JSON] DLQRetentionRequest :> PutNoContent)))))))))))) | |||||
type SharedAPI = ("queues" :> NamedRoutes (QueuesAPI :: Type -> Type)) :<|> (("maintenance" :> NamedRoutes (MaintenanceAPI :: Type -> Type)) :<|> (("events" :> EventsAPI) :<|> (("cron" :> NamedRoutes (CronAPI :: Type -> Type)) :<|> (("workers" :> NamedRoutes (WorkersAPI :: Type -> Type)) :<|> (("rate-limits" :> NamedRoutes (RateLimitsAPI :: Type -> Type)) :<|> (("concurrency" :> NamedRoutes (ConcurrencyAPI :: Type -> Type)) :<|> ("health" :> NamedRoutes (HealthAPI :: Type -> Type))))))))Source #
Shared top-level routes appended after the per-table routes.
type PayloadEditNote = "Optional. A payload replaces the stored payload, and the kind, rate-limit and concurrency columns come from it again. An empty body keeps the stored payload."Source #
How the optional retry and re-enqueue body reads.
type LeaseRefusal = "This lease does not hold the job, a registered worker holds it, the job is suspended, or the job was force-cancelled."Source #
Why a lease route refuses the lease it was sent.
data Throws' (status :: Nat) (reason :: Symbol) (body :: Maybe Type)Source #
A documented error response with an optional JSON body. The server, client and links ignore it.
Instances
| HasLink api => HasLink (Throws' status reason body :> api :: Type) Source # | |||||
| HasClient m api => HasClient m (Throws' status reason body :> api) Source # | |||||
Defined in Arbiter.Servant.API Associated Types
Methods clientWithRoute :: Proxy m -> Proxy (Throws' status reason body :> api) -> Request -> Client m (Throws' status reason body :> api)# hoistClientMonad :: Proxy m -> Proxy (Throws' status reason body :> api) -> (forall x. mon x -> mon' x) -> Client mon (Throws' status reason body :> api) -> Client mon' (Throws' status reason body :> api)# | |||||
| HasServer api context => HasServer (Throws' status reason body :> api :: Type) context Source # | |||||
Defined in Arbiter.Servant.API Methods route :: Proxy (Throws' status reason body :> api) -> Context context -> Delayed env (Server (Throws' status reason body :> api)) -> Router env# hoistServerWithContext :: Proxy (Throws' status reason body :> api) -> Proxy context -> (forall x. m x -> n x) -> ServerT (Throws' status reason body :> api) m -> ServerT (Throws' status reason body :> api) n# | |||||
| type Client m (Throws' status reason body :> api) Source # | |||||
Defined in Arbiter.Servant.API | |||||
| type MkLink (Throws' status reason body :> api :: Type) link Source # | |||||
| type ServerT (Throws' status reason body :> api :: Type) m Source # | |||||
type Throws (status :: Nat) (reason :: Symbol) = Throws' status reason ('Nothing :: Maybe Type)Source #
An error response with no declared content type.
type ThrowsBody (status :: Nat) (reason :: Symbol) body = Throws' status reason ('Just body)Source #
An error response with a JSON body of type body.
data QueuesAPI (mode :: k)Source #
The queue registry routes.
Constructors
| QueuesAPI | |
Fields
| |
Instances
| Generic (QueuesAPI mode) Source # | |||||
Defined in Arbiter.Servant.API Associated Types
| |||||
| type Rep (QueuesAPI mode) Source # | |||||
Defined in Arbiter.Servant.API type Rep (QueuesAPI mode) = D1 ('MetaData "QueuesAPI" "Arbiter.Servant.API" "arbiter-servant-0.1.0.0-inplace" 'False) (C1 ('MetaCons "QueuesAPI" 'PrefixI 'True) (S1 ('MetaSel ('Just "listQueues") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "List queues" :> Get '[JSON] QueuesResponse))) :*: S1 ('MetaSel ('Just "getAllStats") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Show stats for every queue" :> ("stats" :> Get '[JSON] AllStatsResponse)))))) | |||||
data JobsAPI payload result (mode :: k)Source #
One queue's job routes.
Constructors
| JobsAPI | |
Fields
| |
Instances
| Generic (JobsAPI payload result mode) Source # | |||||
Defined in Arbiter.Servant.API Associated Types
| |||||
| type Rep (JobsAPI payload result mode) Source # | |||||
Defined in Arbiter.Servant.API type Rep (JobsAPI payload result mode) = D1 ('MetaData "JobsAPI" "Arbiter.Servant.API" "arbiter-servant-0.1.0.0-inplace" 'False) (C1 ('MetaCons "JobsAPI" 'PrefixI 'True) ((((S1 ('MetaSel ('Just "listJobs") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "List jobs" :> (Description "Filters combine. The payload filter searches the payload text." :> (QueryParam "limit" PageLimit :> (QueryParam "offset" Int :> (QueryParam "group_key" Text :> (QueryParam "parent_id" Int64 :> (QueryParam "job_id" Int64 :> (QueryFlag "roots_only" :> (QueryParam "status" JobStatus :> (QueryParam "claimed_by" UUID :> (QueryParam "kind" Text :> (QueryParam "payload" Text :> (QueryParam "rate_limit_prefix" Text :> (QueryParam "concurrency_prefix" Text :> (QueryParam "sort_by" JobSortColumn :> (QueryParam "sort_dir" SortDir :> Get '[JSON] (JobsResponse payload))))))))))))))))))) :*: S1 ('MetaSel ('Just "insertJob") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Enqueue a job" :> (Description "A duplicate of an ignore dedup key returns the job that exists. A duplicate of a replace dedup key replaces the job in the queue." :> (Throws 409 "A replace dedup key matched a job that is in flight, flagged for cancel, or has children." :> (Throws 409 "An ignore dedup key matched a job that was deleted before the server could read it." :> (ReqBody '[JSON] (ApiJobWrite payload) :> Post '[JSON] (JobResponse (JobRead payload)))))))))) :*: (S1 ('MetaSel ('Just "insertJobsBatch") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Enqueue many jobs" :> (Description "Returns the jobs inserted or replaced. The response omits a job that an ignore dedup key skips, and a job that a replace dedup key cannot replace." :> ("batch" :> (ReqBody '[JSON] (BatchInsertRequest payload) :> Post '[JSON] (BatchInsertResponse payload))))))) :*: S1 ('MetaSel ('Just "getJob") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Show a job" :> (Description "The response includes the derived status." :> (Capture "id" Int64 :> Get '[JSON] (JobResponse (ApiJobWithStatus (Stored payload)))))))))) :*: ((S1 ('MetaSel ('Just "cancelJob") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Cancel a job and its descendants" :> (Description "Deletes the job and every descendant, also the jobs in flight. The handler of a job in flight continues, and its ack finds no job. Use force-cancel to stop the handler." :> (Capture "id" Int64 :> DeleteNoContent))))) :*: S1 ('MetaSel ('Just "forceCancelJob") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Cancel a job and interrupt its handlers" :> (Description "Deletes the jobs in the tree that are not in flight. A job in flight receives a cancel flag and cannot be claimed again. A worker pool stops its handler. An HTTP claimant with a live lease receives 409 on its next ack, nack or extend, until the reaper deletes the job. Then it receives 404. A claimant whose lease expired before the force-cancel receives 404." :> (Capture "id" Int64 :> ("force-cancel" :> PostNoContent))))))) :*: (S1 ('MetaSel ('Just "ackClaimedJob") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Complete a held job" :> (Description "Send the claimSeq and claimedBy from the claim. The server stores the optional result for the parent rollup or the archive." :> (Throws 409 LeaseRefusal :> (Capture "id" Int64 :> ("ack" :> (ReqBody '[JSON] (AckRequest result) :> PostNoContent)))))))) :*: S1 ('MetaSel ('Just "nackClaimedJob") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Return a held job" :> (Description "Restores the attempt that the claim used. The job becomes claimable when its lease expires." :> (Throws 409 LeaseRefusal :> (Capture "id" Int64 :> ("nack" :> (ReqBody '[JSON] JobLease :> PostNoContent))))))))))) :*: (((S1 ('MetaSel ('Just "extendClaimedJob") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Extend a held lease" :> (Description "Sets the lease to expire leaseSeconds from now." :> (Throws 409 LeaseRefusal :> (Capture "id" Int64 :> ("extend" :> (ReqBody '[JSON] ExtendRequest :> PostNoContent)))))))) :*: S1 ('MetaSel ('Just "promoteJob") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Make a job visible now" :> (Throws 409 "The job is already visible, suspended, in flight, or flagged for cancel." :> (Capture "id" Int64 :> ("promote" :> PostNoContent))))))) :*: (S1 ('MetaSel ('Just "rescheduleJob") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Set when a job becomes visible" :> (Throws 409 "The job is in flight, suspended, flagged for cancel, or out of attempts, or another operation changed it." :> (Capture "id" Int64 :> ("reschedule" :> (ReqBody '[JSON] RescheduleRequest :> PostNoContent))))))) :*: S1 ('MetaSel ('Just "moveToDLQ") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Move a job to the DLQ" :> (Description "A rollup takes its descendants with it. A job in flight is moved too. Its handler continues, and its ack finds no job." :> (Throws 409 "Another operation changed or deleted the job between the read and the move." :> (Capture "id" Int64 :> ("move-to-dlq" :> PostNoContent))))))))) :*: ((S1 ('MetaSel ('Just "pauseChildren") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Suspend the visible descendants of a job" :> (Description "The operation skips descendants that are in flight, delayed or throttled. Succeeds when nothing is suspended. 404 when the job is gone." :> (Capture "id" Int64 :> ("pause-children" :> PostNoContent)))))) :*: S1 ('MetaSel ('Just "resumeChildren") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Resume the suspended descendants of a job" :> (Description "A finalizer with children in the queue stays suspended. Succeeds when nothing is resumed. 404 when the job is gone." :> (Capture "id" Int64 :> ("resume-children" :> PostNoContent))))))) :*: (S1 ('MetaSel ('Just "suspendJob") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Suspend a job" :> (Description "A suspended job cannot be claimed." :> (Throws 409 "The job is already suspended, or it is in flight." :> (Capture "id" Int64 :> ("suspend" :> PostNoContent))))))) :*: S1 ('MetaSel ('Just "resumeJob") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Resume a suspended job" :> (Throws 409 "The job is not suspended, it is a finalizer with children in the queue, or another operation changed it." :> (Capture "id" Int64 :> ("resume" :> PostNoContent))))))))))) | |||||
data DLQAPI payload (mode :: k)Source #
One queue's DLQ routes.
Constructors
| DLQAPI | |
Fields
| |
Instances
| Generic (DLQAPI payload mode) Source # | |||||
Defined in Arbiter.Servant.API Associated Types
| |||||
| type Rep (DLQAPI payload mode) Source # | |||||
Defined in Arbiter.Servant.API type Rep (DLQAPI payload mode) = D1 ('MetaData "DLQAPI" "Arbiter.Servant.API" "arbiter-servant-0.1.0.0-inplace" 'False) (C1 ('MetaCons "DLQAPI" 'PrefixI 'True) ((S1 ('MetaSel ('Just "listDLQ") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "List dead-lettered jobs" :> (Description "The payload and error filters search the payload and the last error." :> (QueryParam "limit" PageLimit :> (QueryParam "offset" Int :> (QueryParam "parent_id" Int64 :> (QueryParam "job_id" Int64 :> (QueryParam "group_key" Text :> (QueryParam "kind" Text :> (QueryParam "payload" Text :> (QueryParam "error" Text :> (QueryParam "sort_by" DLQSortColumn :> (QueryParam "sort_dir" SortDir :> Get '[JSON] (DLQResponse payload))))))))))))))) :*: (S1 ('MetaSel ('Just "retryFromDLQ") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Retry a dead-lettered job" :> (Description "Moves the job back to the queue." :> (Throws 409 "The parent of the job is gone from the queue and the DLQ." :> (Capture "id" Int64 :> ("retry" :> (ReqBody' '[Description PayloadEditNote] '[OptionalJSON] (Maybe (PayloadEdit payload)) :> PostNoContent)))))))) :*: S1 ('MetaSel ('Just "deleteDLQ") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Delete a dead-lettered job" :> (Description "Resumes its parent when no child of the parent is left in the queue." :> (Capture "id" Int64 :> DeleteNoContent))))))) :*: (S1 ('MetaSel ('Just "deleteDLQBatch") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Delete dead-lettered jobs" :> (Description "Returns the number deleted. The server skips unknown ids." :> ("batch-delete" :> (ReqBody '[JSON] BatchDeleteRequest :> Post '[JSON] BatchDeleteResponse)))))) :*: (S1 ('MetaSel ('Just "retryDLQBatch") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Retry dead-lettered jobs" :> (Description "Retries each job's tree in its own transaction. Returns the number of ids whose retry restored a tree. The server skips unknown ids and ids restored with an earlier id's tree." :> ("batch-retry" :> (ReqBody '[JSON] BatchRetryRequest :> Post '[JSON] BatchRetryResponse)))))) :*: S1 ('MetaSel ('Just "retryDLQMatching") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Retry every matching dead-lettered job" :> (Description "Retries every job the filters match, oldest first, as batch-retry does. With no filters it retries the whole DLQ. The payload and error filters search the payload and the last error." :> ("retry-matching" :> (QueryParam "parent_id" Int64 :> (QueryParam "job_id" Int64 :> (QueryParam "group_key" Text :> (QueryParam "kind" Text :> (QueryParam "payload" Text :> (QueryParam "error" Text :> Post '[JSON] BatchRetryResponse))))))))))))))) | |||||
data ArchiveAPI payload (mode :: k)Source #
One queue's archive routes.
Constructors
| ArchiveAPI | |
Fields
| |
Instances
| Generic (ArchiveAPI payload mode) Source # | |||||
Defined in Arbiter.Servant.API Associated Types
Methods from :: ArchiveAPI payload mode -> Rep (ArchiveAPI payload mode) x# to :: Rep (ArchiveAPI payload mode) x -> ArchiveAPI payload mode# | |||||
| type Rep (ArchiveAPI payload mode) Source # | |||||
Defined in Arbiter.Servant.API type Rep (ArchiveAPI payload mode) = D1 ('MetaData "ArchiveAPI" "Arbiter.Servant.API" "arbiter-servant-0.1.0.0-inplace" 'False) (C1 ('MetaCons "ArchiveAPI" 'PrefixI 'True) ((S1 ('MetaSel ('Just "listArchive") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "List archived jobs" :> (Description "The payload filter searches the payload text." :> (QueryParam "limit" PageLimit :> (QueryParam "offset" Int :> (QueryParam "parent_id" Int64 :> (QueryParam "job_id" Int64 :> (QueryParam "group_key" Text :> (QueryParam "kind" Text :> (QueryParam "payload" Text :> (QueryParam "completed_after" UTCTime :> (QueryParam "completed_before" UTCTime :> (QueryParam "sort_by" ArchiveSortColumn :> (QueryParam "sort_dir" SortDir :> Get '[JSON] (ArchiveResponse payload)))))))))))))))) :*: S1 ('MetaSel ('Just "reEnqueueArchive") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Run an archived job again" :> (Description "Inserts a new job. The archive entry stays." :> (Capture "id" Int64 :> ("reenqueue" :> (ReqBody' '[Description PayloadEditNote] '[OptionalJSON] (Maybe (PayloadEdit payload)) :> PostNoContent)))))))) :*: (S1 ('MetaSel ('Just "deleteArchive") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Delete an archived job" :> (Capture "id" Int64 :> DeleteNoContent)))) :*: S1 ('MetaSel ('Just "deleteArchiveBatch") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Delete archived jobs" :> (Description "Returns the number deleted. The server skips unknown ids." :> ("batch-delete" :> (ReqBody '[JSON] BatchDeleteRequest :> Post '[JSON] BatchDeleteResponse))))))))) | |||||
data StatsAPI (mode :: k)Source #
One queue's stats route.
Constructors
| StatsAPI | |
Instances
| Generic (StatsAPI mode) Source # | |||||
Defined in Arbiter.Servant.API Associated Types
| |||||
| type Rep (StatsAPI mode) Source # | |||||
Defined in Arbiter.Servant.API type Rep (StatsAPI mode) = D1 ('MetaData "StatsAPI" "Arbiter.Servant.API" "arbiter-servant-0.1.0.0-inplace" 'False) (C1 ('MetaCons "StatsAPI" 'PrefixI 'True) (S1 ('MetaSel ('Just "getStats") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Show queue stats" :> Get '[JSON] StatsResponse))))) | |||||
newtype MaintenanceAPI (mode :: k)Source #
Schema-wide maintenance. A running worker pool does the same work.
Constructors
| MaintenanceAPI | |
Fields
| |
Instances
| Generic (MaintenanceAPI mode) Source # | |||||
Defined in Arbiter.Servant.API Associated Types
Methods from :: MaintenanceAPI mode -> Rep (MaintenanceAPI mode) x# to :: Rep (MaintenanceAPI mode) x -> MaintenanceAPI mode# | |||||
| type Rep (MaintenanceAPI mode) Source # | |||||
Defined in Arbiter.Servant.API type Rep (MaintenanceAPI mode) = D1 ('MetaData "MaintenanceAPI" "Arbiter.Servant.API" "arbiter-servant-0.1.0.0-inplace" 'True) (C1 ('MetaCons "MaintenanceAPI" 'PrefixI 'True) (S1 ('MetaSel ('Just "runMaintenance") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Run a maintenance pass" :> (Description "Runs the work of the reaper once. An operation that another caller runs at the same time is skipped and is not in the response." :> Post '[JSON] MaintenanceResponse)))))) | |||||
data CronAPI (mode :: k)Source #
The cron schedule routes.
Constructors
| CronAPI | |
Fields
| |
Instances
| Generic (CronAPI mode) Source # | |||||
Defined in Arbiter.Servant.API Associated Types
| |||||
| type Rep (CronAPI mode) Source # | |||||
Defined in Arbiter.Servant.API type Rep (CronAPI mode) = D1 ('MetaData "CronAPI" "Arbiter.Servant.API" "arbiter-servant-0.1.0.0-inplace" 'False) (C1 ('MetaCons "CronAPI" 'PrefixI 'True) (S1 ('MetaSel ('Just "listSchedules") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "List cron schedules" :> ("schedules" :> (QueryParam "queue" Text :> Get '[JSON] CronSchedulesResponse))))) :*: (S1 ('MetaSel ('Just "updateSchedule") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Override a cron schedule" :> (Description "A null field clears its override. An absent field keeps it." :> (Throws 400 "An override is not valid." :> ("schedules" :> (Capture "name" Text :> (ReqBody '[JSON] CronScheduleUpdate :> Patch '[JSON] CronScheduleView)))))))) :*: S1 ('MetaSel ('Just "runSchedule") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Run a cron schedule now" :> (Throws 409 "The schedule is disabled, or it already has a run that waits to start." :> ("schedules" :> (Capture "name" Text :> ("run" :> PostNoContent)))))))))) | |||||
data WorkersAPI (mode :: k)Source #
The worker registry routes.
Constructors
| WorkersAPI | |
Fields
| |
Instances
| Generic (WorkersAPI mode) Source # | |||||
Defined in Arbiter.Servant.API Associated Types
Methods from :: WorkersAPI mode -> Rep (WorkersAPI mode) x# to :: Rep (WorkersAPI mode) x -> WorkersAPI mode# | |||||
| type Rep (WorkersAPI mode) Source # | |||||
Defined in Arbiter.Servant.API type Rep (WorkersAPI mode) = D1 ('MetaData "WorkersAPI" "Arbiter.Servant.API" "arbiter-servant-0.1.0.0-inplace" 'False) (C1 ('MetaCons "WorkersAPI" 'PrefixI 'True) (S1 ('MetaSel ('Just "listWorkers") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "List workers" :> (QueryParam "queue" Text :> (QueryParam "live" Double :> Get '[JSON] WorkersResponse))))) :*: (S1 ('MetaSel ('Just "pauseWorker") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Pause a worker" :> (Description "The worker does not claim new jobs." :> (Capture "id" UUID :> ("pause" :> PostNoContent)))))) :*: S1 ('MetaSel ('Just "resumeWorker") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Resume a worker" :> (Capture "id" UUID :> ("resume" :> PostNoContent)))))))) | |||||
data HealthAPI (mode :: k)Source #
Liveness and readiness.
Constructors
| HealthAPI | |
Fields
| |
Instances
| Generic (HealthAPI mode) Source # | |||||
Defined in Arbiter.Servant.API Associated Types
| |||||
| type Rep (HealthAPI mode) Source # | |||||
Defined in Arbiter.Servant.API type Rep (HealthAPI mode) = D1 ('MetaData "HealthAPI" "Arbiter.Servant.API" "arbiter-servant-0.1.0.0-inplace" 'False) (C1 ('MetaCons "HealthAPI" 'PrefixI 'True) (S1 ('MetaSel ('Just "getHealth") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Check readiness" :> (ThrowsBody 503 "The database is not reachable." HealthResponse :> Get '[JSON] HealthResponse)))) :*: S1 ('MetaSel ('Just "getLiveness") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Check liveness" :> ("live" :> Get '[JSON] LivenessResponse)))))) | |||||
data RateLimitsAPI (mode :: k)Source #
Rate limits API routes, schema-wide.
Constructors
| RateLimitsAPI | |
Fields
| |
Instances
| Generic (RateLimitsAPI mode) Source # | |||||
Defined in Arbiter.Servant.API Associated Types
Methods from :: RateLimitsAPI mode -> Rep (RateLimitsAPI mode) x# to :: Rep (RateLimitsAPI mode) x -> RateLimitsAPI mode# | |||||
| type Rep (RateLimitsAPI mode) Source # | |||||
Defined in Arbiter.Servant.API type Rep (RateLimitsAPI mode) = D1 ('MetaData "RateLimitsAPI" "Arbiter.Servant.API" "arbiter-servant-0.1.0.0-inplace" 'False) (C1 ('MetaCons "RateLimitsAPI" 'PrefixI 'True) ((S1 ('MetaSel ('Just "listRateLimits") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "List rate-limit policies" :> Get '[JSON] RateLimitPoliciesResponse))) :*: (S1 ('MetaSel ('Just "listRateLimitBuckets") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "List the buckets of a rate-limit policy" :> (Capture "prefix" Text :> ("buckets" :> (QueryParam "limit" KeyPageLimit :> (QueryParam "offset" Int :> Get '[JSON] RateLimitBucketsResponse))))))) :*: S1 ('MetaSel ('Just "updateRateLimitPolicy") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Override a rate-limit policy" :> (Description "A null field clears its override. An absent field keeps it." :> (Throws 400 "An override value is not valid." :> (Capture "prefix" Text :> (ReqBody '[JSON] RateLimitPolicyUpdate :> Patch '[JSON] RateLimitPolicyView))))))))) :*: (S1 ('MetaSel ('Just "resetRateLimitBuckets") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Refill the buckets of a rate-limit policy" :> (Description "Refills every bucket under the prefix to full. Returns the number refilled." :> (Capture "prefix" Text :> ("reset" :> Post '[JSON] RateLimitResetResponse)))))) :*: (S1 ('MetaSel ('Just "addRateLimitTokens") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Add tokens to a rate-limit bucket" :> (Description "Wakes the throttled jobs of the key." :> (Throws 400 "The token count is 0 or less, or the key is not under the prefix." :> (Capture "prefix" Text :> ("buckets" :> (Capture "key" Text :> ("tokens" :> (ReqBody '[JSON] AddTokensRequest :> Post '[JSON] AddTokensResponse)))))))))) :*: S1 ('MetaSel ('Just "pruneRateLimitBuckets") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Prune idle rate-limit buckets" :> (Throws 400 "The idle value is negative." :> ("prune" :> (QueryParam "idle" Double :> Post '[JSON] PruneResponse)))))))))) | |||||
data ConcurrencyAPI (mode :: k)Source #
Concurrency API routes, schema-wide.
Constructors
| ConcurrencyAPI | |
Fields
| |
Instances
| Generic (ConcurrencyAPI mode) Source # | |||||
Defined in Arbiter.Servant.API Associated Types
Methods from :: ConcurrencyAPI mode -> Rep (ConcurrencyAPI mode) x# to :: Rep (ConcurrencyAPI mode) x -> ConcurrencyAPI mode# | |||||
| type Rep (ConcurrencyAPI mode) Source # | |||||
Defined in Arbiter.Servant.API type Rep (ConcurrencyAPI mode) = D1 ('MetaData "ConcurrencyAPI" "Arbiter.Servant.API" "arbiter-servant-0.1.0.0-inplace" 'False) (C1 ('MetaCons "ConcurrencyAPI" 'PrefixI 'True) ((S1 ('MetaSel ('Just "listConcurrency") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "List concurrency policies" :> Get '[JSON] ConcurrencyPoliciesResponse))) :*: S1 ('MetaSel ('Just "listConcurrencyKeys") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "List the keys of a concurrency policy" :> (Capture "prefix" Text :> ("keys" :> (QueryParam "limit" KeyPageLimit :> (QueryParam "offset" Int :> Get '[JSON] ConcurrencyKeysResponse)))))))) :*: (S1 ('MetaSel ('Just "updateConcurrencyPolicy") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Override a concurrency limit" :> (Description "A null overrideLimit clears the override. An absent one keeps it." :> (Throws 400 "The override limit is negative." :> (Capture "prefix" Text :> (ReqBody '[JSON] ConcurrencyPolicyUpdate :> Patch '[JSON] ConcurrencyPolicyView))))))) :*: (S1 ('MetaSel ('Just "reconcileConcurrency") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Recount in-flight jobs per concurrency key" :> (Description "Repairs each in-flight count from the live jobs. Returns the rows repaired." :> ("reconcile" :> Post '[JSON] ConcurrencyReconcileResponse))))) :*: S1 ('MetaSel ('Just "pruneConcurrencyKeys") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (mode :- (Summary "Prune drained concurrency keys" :> (Description "Deletes keys with no live job." :> ("prune" :> Post '[JSON] PruneResponse))))))))) | |||||
data JobSortColumn#
Sortable columns on the main jobs table.
Constructors
| JsId | By |
| JsPriority | By |
| JsAttempts | By |
| JsInsertedAt | By |
| JsNotVisibleUntil | By |
| JsGroupKey | By |
| JsParentId | By |
| JsLastAttemptedAt | By |
Instances
data DLQSortColumn#
Constructors
| DlqId | By |
| DlqFailedAt | By |
| DlqJobId | By |
| DlqPriority | By |
| DlqAttempts | By |
| DlqInsertedAt | By |
| DlqGroupKey | By |
| DlqParentId | By |
| DlqLastAttemptedAt | By |
Instances
data ArchiveSortColumn#
Sortable columns on the archive table. ArchiveId is the archive primary
key and ArchiveJobId the original job id.
Constructors
| ArchiveId | By |
| ArchiveCompletedAt | By |
| ArchiveInsertedAt | By |
| ArchiveJobId | By |
| ArchiveAttempts | By |
| ArchiveGroupKey | By |
| ArchiveParentId | By |
Instances
Sort direction.
Instances
| Eq SortDir # | |
| Bounded SortDir # | |
| Enum SortDir # | |
| Show SortDir # | |
| FromHttpApiData SortDir Source # | |
Defined in Arbiter.Servant.API Methods parseUrlPiece :: Text -> Either Text SortDir# parseHeader :: ByteString -> Either Text SortDir# | |
| ToHttpApiData SortDir Source # | |
Defined in Arbiter.Servant.API Methods toUrlPiece :: SortDir -> Text# toEncodedUrlPiece :: SortDir -> Builder# toHeader :: SortDir -> ByteString# toQueryParam :: SortDir -> Text# | |
Request and response types
module Arbiter.Servant.Types