| 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
class HasRateLimit payload where Source #
A payload's per-job key selection. Defaults to unlimited. Only limited payloads need an instance.
Minimal complete definition
Nothing
Methods
rateLimitFor :: RateLimitFor payload Source #
The selector deciding which policy (if any) limits a given job.
rateLimitCost :: payload -> Double Source #
How many tokens this job spends. Defaults to 1.
Instances
| HasRateLimit payload Source # | |
Defined in Arbiter.Core.RateLimit.Spec | |
type RateLimitFor payload = Selector Policy 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.
noLimit :: RateLimitFor payload Source #
This payload is unlimited.
limitBy :: Policy -> (payload -> Text) -> RateLimitFor payload Source #
Limit by a fixed policy, keyed by a per-job suffix (e.g. a tenant id).
globalLimit :: Policy -> Text -> RateLimitFor payload Source #
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 a Source #
Select between two selectors with a job predicate. Policy collection inspects both branches.
limitByCase :: (Bounded k, Enum k, Eq k) => (payload -> k) -> (k -> RateLimitFor payload) -> RateLimitFor payload Source #
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 policyPrefixOf :: Policy -> Text Source # | |
| Show Policy Source # | |
| Eq Policy Source # | |
| Ord Policy Source # | |
| HasRateLimit payload => CollectFor (payload :: Type) Policy Source # | |
Defined in Arbiter.Core.RateLimit.Spec Methods collectFor :: Set Policy Source # | |
tokenBucket :: Text -> Double -> NominalDiffTime -> Policy Source #
"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.
policyPrefixOf :: AdmissionPolicy p => p -> Text Source #
Bucket durability
data Durability Source #
Whether the rate-limit bucket table is WAL-logged. Set at migration time.
Instances
| Show Durability Source # | |
Defined in Arbiter.Core.RateLimit.Spec Methods showsPrec :: Int -> Durability -> ShowS # show :: Durability -> String # showList :: [Durability] -> ShowS # | |
| Eq Durability Source # | |
Defined in Arbiter.Core.RateLimit.Spec | |
Management and observability views
data RateLimitPolicyView Source #
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
data RateLimitBucketView Source #
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 Source # parseJSONList :: Value -> Parser [RateLimitBucketView] Source # | |||||
| ToJSON RateLimitBucketView Source # | |||||
Defined in Arbiter.Core.RateLimit.Stats Methods toJSON :: RateLimitBucketView -> Value Source # toEncoding :: RateLimitBucketView -> Encoding Source # toJSONList :: [RateLimitBucketView] -> Value Source # toEncodingList :: [RateLimitBucketView] -> Encoding Source # omitField :: RateLimitBucketView -> Bool Source # | |||||
| 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 # | |||||
| Eq RateLimitBucketView Source # | |||||
Defined in Arbiter.Core.RateLimit.Stats Methods (==) :: RateLimitBucketView -> RateLimitBucketView -> Bool # (/=) :: RateLimitBucketView -> RateLimitBucketView -> Bool # | |||||
| 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-Kcm43gPyDGYL5vaZ4cZIJF" '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))))) | |||||
data RateLimitPolicyUpdate Source #
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 Source # parseJSONList :: Value -> Parser [RateLimitPolicyUpdate] Source # | |||||
| ToJSON RateLimitPolicyUpdate Source # | |||||
Defined in Arbiter.Core.RateLimit.Stats Methods toJSON :: RateLimitPolicyUpdate -> Value Source # toEncoding :: RateLimitPolicyUpdate -> Encoding Source # toJSONList :: [RateLimitPolicyUpdate] -> Value Source # toEncodingList :: [RateLimitPolicyUpdate] -> Encoding Source # | |||||
| Generic RateLimitPolicyUpdate Source # | |||||
Defined in Arbiter.Core.RateLimit.Stats Associated Types
Methods from :: RateLimitPolicyUpdate -> Rep RateLimitPolicyUpdate x # to :: Rep RateLimitPolicyUpdate x -> RateLimitPolicyUpdate # | |||||
| Show RateLimitPolicyUpdate Source # | |||||
Defined in Arbiter.Core.RateLimit.Stats Methods showsPrec :: Int -> RateLimitPolicyUpdate -> ShowS # show :: RateLimitPolicyUpdate -> String # showList :: [RateLimitPolicyUpdate] -> ShowS # | |||||
| Eq RateLimitPolicyUpdate Source # | |||||
Defined in Arbiter.Core.RateLimit.Stats Methods (==) :: RateLimitPolicyUpdate -> RateLimitPolicyUpdate -> Bool # (/=) :: RateLimitPolicyUpdate -> RateLimitPolicyUpdate -> Bool # | |||||
| 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-Kcm43gPyDGYL5vaZ4cZIJF" '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 () Source #
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.
pruneRateLimitBuckets :: MonadArbiter m => NominalDiffTime -> m Int64 Source #
Delete reclaimable idle (full) buckets. Returns the number pruned. The worker reaper runs this. A full bucket re-seeds at full on next use.
resetRateLimitBuckets :: (MonadArbiter m, RegistryTables (RegistryOf m)) => Text -> m Int64 Source #
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 #
List a prefix's buckets with fill levels, paginated.
updateRateLimitPolicyOverrides :: (MonadArbiter m, RegistryTables (RegistryOf m)) => Text -> RateLimitPolicyUpdate -> m Int64 Source #
Set or clear a policy's override params and wake the prefix's parked jobs. Returns rows affected (0 if absent).
setRateLimit :: (MonadArbiter m, RegistryTables (RegistryOf m)) => Policy -> m Int64 Source #
Override a policy with this shape, until it is cleared. Returns rows affected.
clearRateLimit :: (MonadArbiter m, RegistryTables (RegistryOf m)) => Policy -> m Int64 Source #
Drop a policy's overrides. Its declared params apply again. Returns rows affected.
Keys
data RateLimitKey Source #
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 Methods parseJSON :: Value -> Parser RateLimitKey Source # parseJSONList :: Value -> Parser [RateLimitKey] Source # | |
| ToJSON RateLimitKey Source # | |
Defined in Arbiter.Core.RateLimit.Spec Methods toJSON :: RateLimitKey -> Value Source # toEncoding :: RateLimitKey -> Encoding Source # toJSONList :: [RateLimitKey] -> Value Source # toEncodingList :: [RateLimitKey] -> Encoding Source # omitField :: RateLimitKey -> Bool Source # | |
| Show RateLimitKey Source # | |
Defined in Arbiter.Core.RateLimit.Spec Methods showsPrec :: Int -> RateLimitKey -> ShowS # show :: RateLimitKey -> String # showList :: [RateLimitKey] -> ShowS # | |
| Eq RateLimitKey Source # | |
Defined in Arbiter.Core.RateLimit.Spec | |