| Safe Haskell | None |
|---|---|
| Language | GHC2024 |
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
- class HasRateLimit payload where
- rateLimitFor :: RateLimitFor payload
- rateLimitCost :: payload -> Double
- type RateLimitFor payload = Selector Policy payload (Maybe RateLimitKey)
- noLimit :: RateLimitFor payload
- limitBy :: Policy -> (payload -> Text) -> RateLimitFor payload
- globalLimit :: Policy -> 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
- data Policy = Policy {}
- tokenBucket :: Text -> Double -> NominalDiffTime -> Policy
- policyPrefixOf :: AdmissionPolicy p => p -> Text
- data Durability
- data RateLimitPolicyView = RateLimitPolicyView {}
- data RateLimitBucketView = RateLimitBucketView {
- rateLimitKey :: Text
- policyPrefix :: Text
- tokens :: Double
- maxTokens :: Double
- fillFraction :: Maybe Double
- lastRefill :: UTCTime
- data RateLimitPolicyUpdate = RateLimitPolicyUpdate {}
- addRateLimitTokens :: (MonadArbiter m, RegistryTables (RegistryOf m)) => RateLimitKey -> Double -> m ()
- 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)) => Policy -> m Int64
- clearRateLimit :: (MonadArbiter m, RegistryTables (RegistryOf m)) => Policy -> m Int64
- data RateLimitKey = RateLimitKey {}
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
| HasRateLimit payload Source # | |
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
A token-bucket policy. Burst policyMax, refilling policyRefill every
policyInterval. A policyRefill of 0 is a manually-refilled bucket.
Constructors
| Policy | |
Fields | |
Instances
| AdmissionPolicy Policy Source # | |
Defined in Arbiter.Core.RateLimit.Spec Methods Source #policyPrefixOf :: Policy -> Text | |
| Eq Policy Source # | |
| Ord Policy Source # | |
| Show Policy Source # | |
| HasRateLimit payload => CollectFor (payload :: Type) Policy Source # | |
Defined in Arbiter.Core.RateLimit.Spec Methods | |
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.
Source #policyPrefixOf :: AdmissionPolicy p => p -> Text
Bucket durability
Source #data Durability
Whether the rate-limit bucket table is WAL-logged. Set at migration time.
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 | |
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.
Constructors
| RateLimitPolicyView | |
Fields | |
Instances
Source #data RateLimitBucketView
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 "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.
Constructors
| RateLimitPolicyUpdate | |
Fields
| |
Instances
| FromJSON RateLimitPolicyUpdate Source # | Hand-written. 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
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 | |
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 | |