arbiter-core-0.1.0.0
arbiter-core
Safe HaskellNone
LanguageGHC2024

Arbiter.RateLimit

Description

Per-job rate limiting.

Declare which policy (if any) limits each job with a HasRateLimit instance, building the selector from noLimit / limitBy / globalLimit / chooseWhen / limitByCase. The migration statically collects every policy a selector can reach and seeds it.

Synopsis

Declaring a payload's limit

Source #class HasRateLimit payload where

A payload's per-job key selection. Defaults to unlimited. Only limited payloads need an instance.

Minimal complete definition

Nothing

Methods

Source #rateLimitFor :: RateLimitFor payload

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

Source #rateLimitCost :: payload -> Double

How many tokens this job spends. Defaults to 1.

Instances

Instances details
HasRateLimit payload Source # 
Instance details

Defined in Arbiter.Core.RateLimit.Spec

Source #type RateLimitFor payload = Selector Policy payload (Maybe RateLimitKey)

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

Source #noLimit :: RateLimitFor payload

This payload is unlimited.

Source #limitBy :: Policy -> (payload -> Text) -> RateLimitFor payload

Limit by a fixed policy, keyed by a per-job suffix (e.g. a tenant id).

Source #globalLimit :: Policy -> Text -> RateLimitFor payload

Limit by a fixed policy under one shared key (a single global bucket).

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

Select between two selectors with a job predicate. Policy collection inspects both branches.

Source #limitByCase :: (Bounded k, Enum k, Eq k) => (payload -> k) -> (k -> RateLimitFor payload) -> RateLimitFor payload

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.

Policies

Source #data Policy

A token-bucket policy. Burst policyMax, refilling policyRefill every policyInterval. A policyRefill of 0 is a manually-refilled bucket.

Instances

Instances details
AdmissionPolicy Policy Source # 
Instance details

Defined in Arbiter.Core.RateLimit.Spec

Eq Policy Source # 
Instance details

Defined in Arbiter.Core.RateLimit.Spec

Methods

#(==) :: Policy -> Policy -> Bool

#(/=) :: Policy -> Policy -> Bool

Ord Policy Source # 
Instance details

Defined in Arbiter.Core.RateLimit.Spec

Show Policy Source # 
Instance details

Defined in Arbiter.Core.RateLimit.Spec

HasRateLimit payload => CollectFor (payload :: Type) Policy Source # 
Instance details

Defined in Arbiter.Core.RateLimit.Spec

Source #tokenBucket :: Text -> Double -> NominalDiffTime -> Policy

"N per period" with burst N (max = refill = n). The period is floored to a tiny positive value. The prefix must not contain :, the key separator. The migration enforces this.

Bucket durability

Source #data Durability

Whether the rate-limit bucket table is WAL-logged. Set at migration time.

Constructors

Durable 
Unlogged 

Instances

Instances details
Eq Durability Source # 
Instance details

Defined in Arbiter.Core.RateLimit.Spec

Show Durability Source # 
Instance details

Defined in Arbiter.Core.RateLimit.Spec

Management and observability views

Source #data RateLimitPolicyView

A policy with its default and override params plus live bucket and throttle stats. The effective param is override when set, else default.

Instances

Instances details
FromJSON RateLimitPolicyView Source # 
Instance details

Defined in Arbiter.Core.RateLimit.Stats

ToJSON RateLimitPolicyView Source # 
Instance details

Defined in Arbiter.Core.RateLimit.Stats

Eq RateLimitPolicyView Source # 
Instance details

Defined in Arbiter.Core.RateLimit.Stats

Generic RateLimitPolicyView Source # 
Instance details

Defined in Arbiter.Core.RateLimit.Stats

Associated Types

type Rep RateLimitPolicyView 
Instance details

Defined in Arbiter.Core.RateLimit.Stats

Show RateLimitPolicyView Source # 
Instance details

Defined in Arbiter.Core.RateLimit.Stats

type Rep RateLimitPolicyView Source # 
Instance details

Defined in Arbiter.Core.RateLimit.Stats

Source #data RateLimitBucketView

A single key's bucket: current tokens, effective max, and fill fraction.

Instances

Instances details
FromJSON RateLimitBucketView Source # 
Instance details

Defined in Arbiter.Core.RateLimit.Stats

ToJSON RateLimitBucketView Source # 
Instance details

Defined in Arbiter.Core.RateLimit.Stats

Eq RateLimitBucketView Source # 
Instance details

Defined in Arbiter.Core.RateLimit.Stats

Generic RateLimitBucketView Source # 
Instance details

Defined in Arbiter.Core.RateLimit.Stats

Associated Types

type Rep RateLimitBucketView 
Instance details

Defined in Arbiter.Core.RateLimit.Stats

type Rep RateLimitBucketView = D1 ('MetaData "RateLimitBucketView" "Arbiter.Core.RateLimit.Stats" "arbiter-core-0.1.0.0-inplace" 'False) (C1 ('MetaCons "RateLimitBucketView" 'PrefixI 'True) ((S1 ('MetaSel ('Just "rateLimitKey") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Text) :*: (S1 ('MetaSel ('Just "policyPrefix") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Text) :*: S1 ('MetaSel ('Just "tokens") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Double))) :*: (S1 ('MetaSel ('Just "maxTokens") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Double) :*: (S1 ('MetaSel ('Just "fillFraction") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Maybe Double)) :*: S1 ('MetaSel ('Just "lastRefill") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 UTCTime)))))
Show RateLimitBucketView Source # 
Instance details

Defined in Arbiter.Core.RateLimit.Stats

type Rep RateLimitBucketView Source # 
Instance details

Defined in Arbiter.Core.RateLimit.Stats

type Rep RateLimitBucketView = D1 ('MetaData "RateLimitBucketView" "Arbiter.Core.RateLimit.Stats" "arbiter-core-0.1.0.0-inplace" 'False) (C1 ('MetaCons "RateLimitBucketView" 'PrefixI 'True) ((S1 ('MetaSel ('Just "rateLimitKey") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Text) :*: (S1 ('MetaSel ('Just "policyPrefix") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Text) :*: S1 ('MetaSel ('Just "tokens") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Double))) :*: (S1 ('MetaSel ('Just "maxTokens") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Double) :*: (S1 ('MetaSel ('Just "fillFraction") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Maybe Double)) :*: S1 ('MetaSel ('Just "lastRefill") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 UTCTime)))))

Source #data RateLimitPolicyUpdate

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

Instances

Instances details
FromJSON RateLimitPolicyUpdate Source #

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

Instance details

Defined in Arbiter.Core.RateLimit.Stats

ToJSON RateLimitPolicyUpdate Source # 
Instance details

Defined in Arbiter.Core.RateLimit.Stats

Eq RateLimitPolicyUpdate Source # 
Instance details

Defined in Arbiter.Core.RateLimit.Stats

Generic RateLimitPolicyUpdate Source # 
Instance details

Defined in Arbiter.Core.RateLimit.Stats

Associated Types

type Rep RateLimitPolicyUpdate 
Instance details

Defined in Arbiter.Core.RateLimit.Stats

type Rep RateLimitPolicyUpdate = D1 ('MetaData "RateLimitPolicyUpdate" "Arbiter.Core.RateLimit.Stats" "arbiter-core-0.1.0.0-inplace" 'False) (C1 ('MetaCons "RateLimitPolicyUpdate" 'PrefixI 'True) (S1 ('MetaSel ('Just "overrideMaxTokens") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Maybe (Maybe Double))) :*: (S1 ('MetaSel ('Just "overrideRefillAmount") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Maybe (Maybe Double))) :*: S1 ('MetaSel ('Just "overrideInterval") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Maybe (Maybe Double))))))
Show RateLimitPolicyUpdate Source # 
Instance details

Defined in Arbiter.Core.RateLimit.Stats

type Rep RateLimitPolicyUpdate Source # 
Instance details

Defined in Arbiter.Core.RateLimit.Stats

type Rep RateLimitPolicyUpdate = D1 ('MetaData "RateLimitPolicyUpdate" "Arbiter.Core.RateLimit.Stats" "arbiter-core-0.1.0.0-inplace" 'False) (C1 ('MetaCons "RateLimitPolicyUpdate" 'PrefixI 'True) (S1 ('MetaSel ('Just "overrideMaxTokens") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Maybe (Maybe Double))) :*: (S1 ('MetaSel ('Just "overrideRefillAmount") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Maybe (Maybe Double))) :*: S1 ('MetaSel ('Just "overrideInterval") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Maybe (Maybe Double))))))

Operations

Source #addRateLimitTokens :: (MonadArbiter m, RegistryTables (RegistryOf m)) => RateLimitKey -> Double -> m ()

Add tokens to a key's bucket, capped at max, and wake any of its jobs parked mid-wait. A no-op without a policy.

Source #pruneRateLimitBuckets :: MonadArbiter m => NominalDiffTime -> m Int64

Delete reclaimable idle (full) buckets. Returns the number pruned. The worker reaper runs this. A full bucket re-seeds at full on next use.

Source #resetRateLimitBuckets :: (MonadArbiter m, RegistryTables (RegistryOf m)) => Text -> m Int64

Reset every bucket for a prefix to full and wake its throttled jobs. Returns the number of buckets reset. A manual (0-refill) policy plus a cron calling this at the boundary is a fixed window.

Source #listRateLimitPolicies :: (MonadArbiter m, RegistryTables (RegistryOf m)) => m [RateLimitPolicyView]

List every rate-limit policy with its params, bucket stats, and a live count of currently-throttled jobs per prefix across the registry's queues.

Source #listRateLimitBuckets :: MonadArbiter m => Text -> Int -> Int -> m [RateLimitBucketView]

List a prefix's buckets with fill levels, paginated.

Source #updateRateLimitPolicyOverrides :: (MonadArbiter m, RegistryTables (RegistryOf m)) => Text -> RateLimitPolicyUpdate -> m Int64

Set or clear a policy's override params and wake the prefix's parked jobs. Returns rows affected (0 if absent).

Source #setRateLimit :: (MonadArbiter m, RegistryTables (RegistryOf m)) => Policy -> m Int64

Override a policy with this shape, until it is cleared. Returns rows affected.

Source #clearRateLimit :: (MonadArbiter m, RegistryTables (RegistryOf m)) => Policy -> m Int64

Drop a policy's overrides. Its declared params apply again. Returns rows affected.

Keys

Source #data RateLimitKey

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

Constructors

RateLimitKey 

Fields