arbiter-core-0.1.0.0
arbiter-core
Safe HaskellNone
LanguageGHC2024

Arbiter.Concurrency

Description

Per-job concurrency limits.

This is the user-facing concurrency module. The Arbiter.Core.Concurrency.* modules are internal.

Declare which policy (if any) caps each job with a HasConcurrency instance. The migration seeds every policy a selector can reach. The policy holds the limit.

Synopsis

Declaring a payload's policy

class HasConcurrency payload whereSource #

A payload's per-job policy selection. Defaults to unbounded. Only capped payloads need an instance.

Minimal complete definition

Nothing

Methods

concurrencyFor :: ConcurrencyFor payloadSource #

The selector deciding which policy (if any) caps a given job.

Instances

Instances details
HasConcurrency payload Source # 
Instance details

Defined in Arbiter.Core.Concurrency.Spec

type ConcurrencyFor payload = Selector ConcurrencyPolicy payload (Maybe ConcurrencyKey)Source #

A selective description of the concurrency key for a payload. Evaluation returns the job key. Static inspection returns the reachable policies.

type Selector policy payload = Select (Prim policy payload)Source #

A selective description over a payload. Evaluation for a job returns an a. Static inspection returns the reachable policies.

noConcurrency :: ConcurrencyFor payloadSource #

This payload is unbounded.

concurrencyBy :: ConcurrencyPolicy -> (payload -> Text) -> ConcurrencyFor payloadSource #

Cap by a fixed policy, keyed by a per-job suffix, such as a tenant id.

globalConcurrency :: ConcurrencyPolicy -> Text -> ConcurrencyFor payloadSource #

Cap by a fixed policy under one shared key.

chooseWhen :: (payload -> Bool) -> Selector policy payload a -> Selector policy payload a -> Selector policy payload aSource #

The first selector when the predicate holds, else the second. Policy collection inspects both branches.

concurrencyByCase :: (Bounded k, Enum k, Eq k) => (payload -> k) -> (k -> ConcurrencyFor payload) -> ConcurrencyFor payloadSource #

N-way chooseWhen. Maps the job to a finite tag, then each tag to its selector. Policy collection evaluates every tag in [minBound..maxBound]. The tag's Bounded/Enum and the selector must be total over k.

type RegistryConcurrencyPolicies (registry :: JobPayloadRegistry) = RegistryPolicies registry ConcurrencyPolicySource #

The constraint that lets the migration collect a registry's declared policies.

Policies

data ConcurrencyPolicySource #

A concurrency policy. At most cpLimit jobs are in flight per key under cpPrefix. The default is seeded. An operator override on the policy takes precedence.

Constructors

ConcurrencyPolicy 

Fields

  • cpPrefix :: Text

    The key prefix. It must not contain :.

  • cpLimit :: Int32

    The default in-flight limit per key, in jobs. The migration rejects a declared limit below 1.

concurrencyPolicy :: Text -> Int32 -> ConcurrencyPolicySource #

A policy named prefix admitting at most limit concurrent jobs per key. The cap is floored at 1. Pause it with setConcurrencyLimit policy {cpLimit = 0}. The prefix must not contain :, the key separator. The migration enforces this.

class Ord p => AdmissionPolicy p whereSource #

A policy that admits jobs under a named prefix.

Methods

policyPrefixOf :: p -> TextSource #

The prefix the policy's keys start with.

Keys

data ConcurrencyKeySource #

A resolved concurrency key with a policy prefix and per-key suffix. The stored form is prefix:suffix.

Constructors

ConcurrencyKey 

Fields

Management and observability views

data ConcurrencyPolicyViewSource #

A concurrency policy with its default and override limits plus live key and in-flight stats. The effective cap is overrideLimit when set, else defaultLimit.

Constructors

ConcurrencyPolicyView 

Fields

Instances

Instances details
FromJSON ConcurrencyPolicyView Source # 
Instance details

Defined in Arbiter.Core.Concurrency.Stats

ToJSON ConcurrencyPolicyView Source # 
Instance details

Defined in Arbiter.Core.Concurrency.Stats

Eq ConcurrencyPolicyView Source # 
Instance details

Defined in Arbiter.Core.Concurrency.Stats

Generic ConcurrencyPolicyView Source # 
Instance details

Defined in Arbiter.Core.Concurrency.Stats

Associated Types

type Rep ConcurrencyPolicyView 
Instance details

Defined in Arbiter.Core.Concurrency.Stats

type Rep ConcurrencyPolicyView = D1 ('MetaData "ConcurrencyPolicyView" "Arbiter.Core.Concurrency.Stats" "arbiter-core-0.1.0.0-inplace" 'False) (C1 ('MetaCons "ConcurrencyPolicyView" 'PrefixI 'True) ((S1 ('MetaSel ('Just "prefix") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Text) :*: (S1 ('MetaSel ('Just "defaultLimit") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Int32) :*: S1 ('MetaSel ('Just "overrideLimit") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Maybe Int32)))) :*: (S1 ('MetaSel ('Just "keyCount") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Int64) :*: (S1 ('MetaSel ('Just "totalInFlight") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Int64) :*: S1 ('MetaSel ('Just "maxInFlight") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Maybe Int32))))))
Show ConcurrencyPolicyView Source # 
Instance details

Defined in Arbiter.Core.Concurrency.Stats

type Rep ConcurrencyPolicyView Source # 
Instance details

Defined in Arbiter.Core.Concurrency.Stats

type Rep ConcurrencyPolicyView = D1 ('MetaData "ConcurrencyPolicyView" "Arbiter.Core.Concurrency.Stats" "arbiter-core-0.1.0.0-inplace" 'False) (C1 ('MetaCons "ConcurrencyPolicyView" 'PrefixI 'True) ((S1 ('MetaSel ('Just "prefix") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Text) :*: (S1 ('MetaSel ('Just "defaultLimit") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Int32) :*: S1 ('MetaSel ('Just "overrideLimit") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Maybe Int32)))) :*: (S1 ('MetaSel ('Just "keyCount") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Int64) :*: (S1 ('MetaSel ('Just "totalInFlight") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Int64) :*: S1 ('MetaSel ('Just "maxInFlight") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Maybe Int32))))))

data ConcurrencyKeyViewSource #

A single key's in-flight count, its effective cap, and fill fraction.

Constructors

ConcurrencyKeyView 

Fields

Instances

Instances details
FromJSON ConcurrencyKeyView Source # 
Instance details

Defined in Arbiter.Core.Concurrency.Stats

ToJSON ConcurrencyKeyView Source # 
Instance details

Defined in Arbiter.Core.Concurrency.Stats

Eq ConcurrencyKeyView Source # 
Instance details

Defined in Arbiter.Core.Concurrency.Stats

Generic ConcurrencyKeyView Source # 
Instance details

Defined in Arbiter.Core.Concurrency.Stats

Associated Types

type Rep ConcurrencyKeyView 
Instance details

Defined in Arbiter.Core.Concurrency.Stats

type Rep ConcurrencyKeyView = D1 ('MetaData "ConcurrencyKeyView" "Arbiter.Core.Concurrency.Stats" "arbiter-core-0.1.0.0-inplace" 'False) (C1 ('MetaCons "ConcurrencyKeyView" 'PrefixI 'True) ((S1 ('MetaSel ('Just "concurrencyKey") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Text) :*: S1 ('MetaSel ('Just "concurrencyPrefix") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Text)) :*: (S1 ('MetaSel ('Just "inFlight") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Int32) :*: (S1 ('MetaSel ('Just "effectiveLimit") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Int32) :*: S1 ('MetaSel ('Just "fillFraction") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Maybe Double))))))
Show ConcurrencyKeyView Source # 
Instance details

Defined in Arbiter.Core.Concurrency.Stats

type Rep ConcurrencyKeyView Source # 
Instance details

Defined in Arbiter.Core.Concurrency.Stats

type Rep ConcurrencyKeyView = D1 ('MetaData "ConcurrencyKeyView" "Arbiter.Core.Concurrency.Stats" "arbiter-core-0.1.0.0-inplace" 'False) (C1 ('MetaCons "ConcurrencyKeyView" 'PrefixI 'True) ((S1 ('MetaSel ('Just "concurrencyKey") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Text) :*: S1 ('MetaSel ('Just "concurrencyPrefix") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Text)) :*: (S1 ('MetaSel ('Just "inFlight") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Int32) :*: (S1 ('MetaSel ('Just "effectiveLimit") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Int32) :*: S1 ('MetaSel ('Just "fillFraction") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Maybe Double))))))

data ConcurrencyPolicyUpdateSource #

A patch over a concurrency policy's override limit. Nothing leaves it unchanged, Just Nothing clears the override (reverts to the default), and Just (Just v) sets it.

Constructors

ConcurrencyPolicyUpdate 

Fields

Instances

Instances details
FromJSON ConcurrencyPolicyUpdate Source #

A missing key leaves the field unchanged. An explicit null clears the override.

Instance details

Defined in Arbiter.Core.Concurrency.Stats

ToJSON ConcurrencyPolicyUpdate Source # 
Instance details

Defined in Arbiter.Core.Concurrency.Stats

Eq ConcurrencyPolicyUpdate Source # 
Instance details

Defined in Arbiter.Core.Concurrency.Stats

Generic ConcurrencyPolicyUpdate Source # 
Instance details

Defined in Arbiter.Core.Concurrency.Stats

Associated Types

type Rep ConcurrencyPolicyUpdate 
Instance details

Defined in Arbiter.Core.Concurrency.Stats

type Rep ConcurrencyPolicyUpdate = D1 ('MetaData "ConcurrencyPolicyUpdate" "Arbiter.Core.Concurrency.Stats" "arbiter-core-0.1.0.0-inplace" 'False) (C1 ('MetaCons "ConcurrencyPolicyUpdate" 'PrefixI 'True) (S1 ('MetaSel ('Just "overrideLimit") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Maybe (Maybe Int32)))))
Show ConcurrencyPolicyUpdate Source # 
Instance details

Defined in Arbiter.Core.Concurrency.Stats

type Rep ConcurrencyPolicyUpdate Source # 
Instance details

Defined in Arbiter.Core.Concurrency.Stats

type Rep ConcurrencyPolicyUpdate = D1 ('MetaData "ConcurrencyPolicyUpdate" "Arbiter.Core.Concurrency.Stats" "arbiter-core-0.1.0.0-inplace" 'False) (C1 ('MetaCons "ConcurrencyPolicyUpdate" 'PrefixI 'True) (S1 ('MetaSel ('Just "overrideLimit") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Maybe (Maybe Int32)))))

Operations

updateConcurrencyPolicyOverrides :: MonadArbiter m => Text -> ConcurrencyPolicyUpdate -> m Int64Source #

Apply a concurrency policy's override-limit patch on its policy row, retuning every key under the prefix live. Lowering it never preempts in-flight jobs. Returns rows affected.

setConcurrencyLimit :: MonadArbiter m => ConcurrencyPolicy -> m Int64Source #

Override the policy's limit with its cpLimit, until it is cleared. Returns rows affected.

clearConcurrencyLimit :: MonadArbiter m => ConcurrencyPolicy -> m Int64Source #

Drop a concurrency policy's override. Its declared limit applies again. Returns rows affected.

pruneConcurrencyKeys :: (MonadArbiter m, RegistryTables (RegistryOf m)) => m Int64Source #

Delete drained concurrency rows with no live job. Returns the number pruned.

reconcileConcurrencyCounts :: (MonadArbiter m, RegistryTables (RegistryOf m)) => m Int64Source #

Recompute the concurrency counts from live jobs, repairing any trigger drift. Returns the rows repaired.

reconcileConcurrencyCountsIfStale :: (MonadArbiter m, RegistryTables (RegistryOf m)) => m Int64Source #

Rebuild the concurrency counts when a crash truncated the UNLOGGED table. Returns the rows repaired.

reconcileAndPruneConcurrency :: (MonadArbiter m, RegistryTables (RegistryOf m)) => m Int64Source #

Reconcile then prune. Skipped when no concurrency key exists. Returns the rows repaired plus the rows pruned.

listConcurrencyPolicies :: MonadArbiter m => m [ConcurrencyPolicyView]Source #

List every concurrency policy with its default/override limit and live key and in-flight aggregates.

listConcurrencyKeys :: MonadArbiter m => Text -> Int -> Int -> m [ConcurrencyKeyView]Source #

Arguments

:: MonadArbiter m 
=> Text

Prefix

-> Int

Limit

-> Int

Offset

-> m [ConcurrencyKeyView] 

List a prefix's keys with effective cap and in-flight fill fraction, fullest first.

getConcurrencyPolicy :: MonadArbiter m => Text -> m (Maybe ConcurrencyPolicyView)Source #

One prefix's concurrency policy with its default/override limit and live aggregates. Nothing when the prefix has no policy.

concurrencyPolicyExists :: MonadArbiter m => Text -> m BoolSource #

Whether a concurrency policy exists for a prefix.