| Safe Haskell | None |
|---|---|
| Language | GHC2024 |
Arbiter.RateLimit
Description
Per-job rate limiting.
This is the user-facing rate-limit module. The Arbiter.Core.RateLimit.* modules are internal.
Declare which policy (if any) limits each job with a HasRateLimit instance.
The migration seeds every policy a selector can reach.
Synopsis
- class HasRateLimit payload where
- rateLimitFor :: RateLimitFor payload
- rateLimitCost :: payload -> Double
- type RateLimitFor payload = Selector RateLimitPolicy payload (Maybe RateLimitKey)
- type Selector policy payload = Select (Prim policy payload)
- noLimit :: RateLimitFor payload
- limitBy :: RateLimitPolicy -> (payload -> Text) -> RateLimitFor payload
- globalLimit :: RateLimitPolicy -> Text -> RateLimitFor payload
- chooseWhen :: (payload -> Bool) -> Selector policy payload a -> Selector policy payload a -> Selector policy payload a
- limitByCase :: (Bounded k, Enum k, Eq k) => (payload -> k) -> (k -> RateLimitFor payload) -> RateLimitFor payload
- type RegistryRateLimitPolicies (registry :: JobPayloadRegistry) = RegistryPolicies registry RateLimitPolicy
- data RateLimitPolicy = RateLimitPolicy {}
- tokenBucket :: Text -> Double -> NominalDiffTime -> RateLimitPolicy
- class Ord p => AdmissionPolicy p where
- policyPrefixOf :: p -> Text
- data Durability
- data RateLimitKey = RateLimitKey {}
- data RateLimitPolicyView = RateLimitPolicyView {
- prefix :: Text
- defaultMaxTokens :: Double
- defaultRefillAmount :: Double
- defaultInterval :: Double
- overrideMaxTokens :: Maybe Double
- overrideRefillAmount :: Maybe Double
- overrideInterval :: Maybe Double
- bucketCount :: Int64
- throttledCount :: Int64
- throttledQueues :: [Text]
- minTokens :: Maybe Double
- avgTokens :: Maybe Double
- data RateLimitBucketView = RateLimitBucketView {}
- data RateLimitPolicyUpdate = RateLimitPolicyUpdate {}
- addRateLimitTokens :: (MonadArbiter m, RegistryTables (RegistryOf m)) => RateLimitKey -> Double -> m Int64
- pruneRateLimitBuckets :: MonadArbiter m => NominalDiffTime -> m Int64
- resetRateLimitBuckets :: (MonadArbiter m, RegistryTables (RegistryOf m)) => Text -> m Int64
- listRateLimitPolicies :: (MonadArbiter m, RegistryTables (RegistryOf m)) => m [RateLimitPolicyView]
- listRateLimitBuckets :: MonadArbiter m => Text -> Int -> Int -> m [RateLimitBucketView]
- updateRateLimitPolicyOverrides :: (MonadArbiter m, RegistryTables (RegistryOf m)) => Text -> RateLimitPolicyUpdate -> m Int64
- setRateLimit :: (MonadArbiter m, RegistryTables (RegistryOf m)) => RateLimitPolicy -> m Int64
- clearRateLimit :: (MonadArbiter m, RegistryTables (RegistryOf m)) => RateLimitPolicy -> m Int64
- getRateLimitPolicy :: (MonadArbiter m, RegistryTables (RegistryOf m)) => Text -> m (Maybe RateLimitPolicyView)
- rateLimitPolicyExists :: MonadArbiter m => Text -> m Bool
Declaring a payload's policy
class HasRateLimit payload whereSource #
A payload's per-job policy selection. Defaults to unlimited. Only limited payloads need an instance.
Minimal complete definition
Nothing
Methods
rateLimitFor :: RateLimitFor payloadSource #
The selector deciding which policy (if any) limits a given job.
rateLimitCost :: payload -> DoubleSource #
How many tokens this job spends, clamped to the bucket's range. Defaults to 1.
Instances
| HasRateLimit payload Source # | |
Defined in Arbiter.Core.RateLimit.Spec | |
type RateLimitFor payload = Selector RateLimitPolicy payload (Maybe RateLimitKey)Source #
A selective description of the rate-limit 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.
noLimit :: RateLimitFor payloadSource #
This payload is unlimited.
limitBy :: RateLimitPolicy -> (payload -> Text) -> RateLimitFor payloadSource #
Limit by a fixed policy, keyed by a per-job suffix, such as a tenant id.
globalLimit :: RateLimitPolicy -> Text -> RateLimitFor payloadSource #
Limit by a fixed policy under one shared key (a single global bucket).
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.
limitByCase :: (Bounded k, Enum k, Eq k) => (payload -> k) -> (k -> RateLimitFor payload) -> RateLimitFor 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 RegistryRateLimitPolicies (registry :: JobPayloadRegistry) = RegistryPolicies registry RateLimitPolicySource #
The constraint that lets the migration collect a registry's declared policies.
Policies
data RateLimitPolicySource #
A token-bucket policy. Burst policyMax, refilling continuously at policyRefill
per policyInterval. A policyRefill of 0 is a manually-refilled bucket. Fields are
non-negative and the interval is positive. The migration rejects other values.
Constructors
| RateLimitPolicy | |
Fields
| |
Instances
tokenBucket :: Text -> Double -> NominalDiffTime -> RateLimitPolicySource #
count per period, with a burst of count. The period is floored to a
tiny positive value. 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.
Instances
| AdmissionPolicy ConcurrencyPolicy Source # | |
Defined in Arbiter.Core.Concurrency.Spec Methods | |
| AdmissionPolicy RateLimitPolicy Source # | |
Defined in Arbiter.Core.RateLimit.Spec Methods | |
Bucket durability
data DurabilitySource #
Whether the rate-limit bucket table is WAL-logged. Set by the migration config.
Constructors
| Durable | WAL-logged. Buckets survive a crash. |
| Unlogged | Not WAL-logged. A crash resets the buckets. The migrations use this by default. |
Instances
| Eq Durability Source # | |
Defined in Arbiter.Core.RateLimit.Spec | |
| Show Durability Source # | |
Defined in Arbiter.Core.RateLimit.Spec Methods showsPrec :: Int -> Durability -> ShowS# show :: Durability -> String# showList :: [Durability] -> ShowS# | |
Keys
data RateLimitKeySource #
A resolved key with a prefix and per-key suffix. The stored form is
prefix:suffix.
Constructors
| RateLimitKey | |
Instances
| FromJSON RateLimitKey Source # | |
Defined in Arbiter.Core.RateLimit.Spec | |
| ToJSON RateLimitKey Source # | |
Defined in Arbiter.Core.RateLimit.Spec Methods toJSON :: RateLimitKey -> Value# toEncoding :: RateLimitKey -> Encoding# toJSONList :: [RateLimitKey] -> Value# toEncodingList :: [RateLimitKey] -> Encoding# omitField :: RateLimitKey -> Bool# | |
| Eq RateLimitKey Source # | |
Defined in Arbiter.Core.RateLimit.Spec | |
| Show RateLimitKey Source # | |
Defined in Arbiter.Core.RateLimit.Spec Methods showsPrec :: Int -> RateLimitKey -> ShowS# show :: RateLimitKey -> String# showList :: [RateLimitKey] -> ShowS# | |
Management and observability views
data RateLimitPolicyViewSource #
A policy with its default and override params plus live bucket and throttle
stats. Each effective param is its override* field when set, else its default* field.
Constructors
| RateLimitPolicyView | |
Fields
| |
Instances
data RateLimitBucketViewSource #
A single key's bucket: current tokens, effective max, and fill fraction.
Constructors
| RateLimitBucketView | |
Fields
| |
Instances
| FromJSON RateLimitBucketView Source # | |||||
Defined in Arbiter.Core.RateLimit.Stats Methods parseJSON :: Value -> Parser RateLimitBucketView# parseJSONList :: Value -> Parser [RateLimitBucketView]# | |||||
| ToJSON RateLimitBucketView Source # | |||||
Defined in Arbiter.Core.RateLimit.Stats Methods toJSON :: RateLimitBucketView -> Value# toEncoding :: RateLimitBucketView -> Encoding# toJSONList :: [RateLimitBucketView] -> Value# | |||||
| Eq RateLimitBucketView Source # | |||||
Defined in Arbiter.Core.RateLimit.Stats Methods (==) :: RateLimitBucketView -> RateLimitBucketView -> Bool# (/=) :: RateLimitBucketView -> RateLimitBucketView -> Bool# | |||||
| Generic RateLimitBucketView Source # | |||||
Defined in Arbiter.Core.RateLimit.Stats Associated Types
Methods from :: RateLimitBucketView -> Rep RateLimitBucketView x# to :: Rep RateLimitBucketView x -> RateLimitBucketView# | |||||
| Show RateLimitBucketView Source # | |||||
Defined in Arbiter.Core.RateLimit.Stats Methods showsPrec :: Int -> RateLimitBucketView -> ShowS# show :: RateLimitBucketView -> String# showList :: [RateLimitBucketView] -> ShowS# | |||||
| type Rep RateLimitBucketView Source # | |||||
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 "rateLimitPrefix") '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))))) | |||||
data RateLimitPolicyUpdateSource #
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.
Constructors
| RateLimitPolicyUpdate | |
Fields
| |
Instances
| FromJSON RateLimitPolicyUpdate Source # | A missing key leaves the field unchanged. An explicit | ||||
Defined in Arbiter.Core.RateLimit.Stats Methods parseJSON :: Value -> Parser RateLimitPolicyUpdate# | |||||
| ToJSON RateLimitPolicyUpdate Source # | |||||
Defined in Arbiter.Core.RateLimit.Stats Methods toJSON :: RateLimitPolicyUpdate -> Value# toEncoding :: RateLimitPolicyUpdate -> Encoding# toJSONList :: [RateLimitPolicyUpdate] -> Value# | |||||
| Eq RateLimitPolicyUpdate Source # | |||||
Defined in Arbiter.Core.RateLimit.Stats Methods (==) :: RateLimitPolicyUpdate -> RateLimitPolicyUpdate -> Bool# (/=) :: RateLimitPolicyUpdate -> RateLimitPolicyUpdate -> Bool# | |||||
| Generic RateLimitPolicyUpdate Source # | |||||
Defined in Arbiter.Core.RateLimit.Stats Associated Types
Methods from :: RateLimitPolicyUpdate -> Rep RateLimitPolicyUpdate x# | |||||
| Show RateLimitPolicyUpdate Source # | |||||
Defined in Arbiter.Core.RateLimit.Stats Methods showsPrec :: Int -> RateLimitPolicyUpdate -> ShowS# show :: RateLimitPolicyUpdate -> String# showList :: [RateLimitPolicyUpdate] -> ShowS# | |||||
| type Rep RateLimitPolicyUpdate Source # | |||||
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
addRateLimitTokens :: (MonadArbiter m, RegistryTables (RegistryOf m)) => RateLimitKey -> Double -> m Int64Source #
Add tokens to a key's bucket, clamped to [0, max], and wake any of its throttled
jobs. A key without a bucket gets a full bucket and the amount has no effect. Without a
policy the bucket stays unchanged and the wake still runs. Returns the number of jobs
woken.
pruneRateLimitBuckets :: MonadArbiter m => NominalDiffTime -> m Int64Source #
Delete reclaimable idle (full) buckets. Returns the number pruned. The worker pool reaper runs this. A full bucket re-seeds at full on next use.
resetRateLimitBuckets :: (MonadArbiter m, RegistryTables (RegistryOf m)) => Text -> m Int64Source #
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.
listRateLimitPolicies :: (MonadArbiter m, RegistryTables (RegistryOf m)) => m [RateLimitPolicyView]Source #
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.
listRateLimitBuckets :: MonadArbiter m => Text -> Int -> Int -> m [RateLimitBucketView]Source #
Arguments
| :: MonadArbiter m | |
| => Text | Prefix |
| -> Int | Limit |
| -> Int | Offset |
| -> m [RateLimitBucketView] |
List a prefix's buckets with fill levels, emptiest first.
updateRateLimitPolicyOverrides :: (MonadArbiter m, RegistryTables (RegistryOf m)) => Text -> RateLimitPolicyUpdate -> m Int64Source #
Set or clear a policy's override params and wake the prefix's throttled jobs. Returns rows affected (0 if absent).
setRateLimit :: (MonadArbiter m, RegistryTables (RegistryOf m)) => RateLimitPolicy -> m Int64Source #
Override a policy with this shape, until it is cleared. Returns rows affected.
clearRateLimit :: (MonadArbiter m, RegistryTables (RegistryOf m)) => RateLimitPolicy -> m Int64Source #
Drop a policy's overrides. Its declared params apply again. Returns rows affected.
getRateLimitPolicy :: (MonadArbiter m, RegistryTables (RegistryOf m)) => Text -> m (Maybe RateLimitPolicyView)Source #
One prefix's rate-limit policy with its params, bucket stats, and live throttled
count. Nothing when the prefix has no policy.
rateLimitPolicyExists :: MonadArbiter m => Text -> m BoolSource #
Whether a rate-limit policy exists for a prefix.