{-# LANGUAGE AllowAmbiguousTypes #-}
{-# OPTIONS_HADDOCK not-home #-}
module Arbiter.Core.RateLimit.Spec
(
Durability (..)
, RateLimitKey (..)
, toRateLimitKey
, rateLimitKeyText
, RateLimitPolicy (..)
, tokenBucket
, HasRateLimit (..)
, RateLimitFor
, noLimit
, limitBy
, globalLimit
, chooseWhen
, limitByCase
, collectPolicies
, RegistryRateLimitPolicies
, registryRateLimitPolicies
, registryRateLimitTables
) where
import Data.Aeson (FromJSON (..), ToJSON (..))
import Data.Set (Set)
import Data.Text (Text)
import Data.Time (NominalDiffTime)
import Arbiter.Core.Admission
( AdmissionPolicy (..)
, CollectFor (..)
, RegistryPolicies (..)
, prefixedKeyParseJSON
, prefixedKeyText
, prefixedKeyToJSON
, registryPolicies
, registryPolicyTables
, selectBy
, selectNone
)
import Arbiter.Core.Selector (Selector, chooseWhen, collectPolicies, selectByCase)
data Durability
=
Durable
|
Unlogged
deriving stock (Durability -> Durability -> Bool
(Durability -> Durability -> Bool)
-> (Durability -> Durability -> Bool) -> Eq Durability
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Durability -> Durability -> Bool
== :: Durability -> Durability -> Bool
$c/= :: Durability -> Durability -> Bool
/= :: Durability -> Durability -> Bool
Eq, Int -> Durability -> ShowS
[Durability] -> ShowS
Durability -> String
(Int -> Durability -> ShowS)
-> (Durability -> String)
-> ([Durability] -> ShowS)
-> Show Durability
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Durability -> ShowS
showsPrec :: Int -> Durability -> ShowS
$cshow :: Durability -> String
show :: Durability -> String
$cshowList :: [Durability] -> ShowS
showList :: [Durability] -> ShowS
Show)
data RateLimitKey = RateLimitKey
{ RateLimitKey -> Text
rlkPrefix :: Text
, RateLimitKey -> Text
rlkSuffix :: Text
}
deriving stock (RateLimitKey -> RateLimitKey -> Bool
(RateLimitKey -> RateLimitKey -> Bool)
-> (RateLimitKey -> RateLimitKey -> Bool) -> Eq RateLimitKey
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RateLimitKey -> RateLimitKey -> Bool
== :: RateLimitKey -> RateLimitKey -> Bool
$c/= :: RateLimitKey -> RateLimitKey -> Bool
/= :: RateLimitKey -> RateLimitKey -> Bool
Eq, Int -> RateLimitKey -> ShowS
[RateLimitKey] -> ShowS
RateLimitKey -> String
(Int -> RateLimitKey -> ShowS)
-> (RateLimitKey -> String)
-> ([RateLimitKey] -> ShowS)
-> Show RateLimitKey
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RateLimitKey -> ShowS
showsPrec :: Int -> RateLimitKey -> ShowS
$cshow :: RateLimitKey -> String
show :: RateLimitKey -> String
$cshowList :: [RateLimitKey] -> ShowS
showList :: [RateLimitKey] -> ShowS
Show)
toRateLimitKey :: Text -> Text -> RateLimitKey
toRateLimitKey :: Text -> Text -> RateLimitKey
toRateLimitKey Text
prefix Text
suffix = RateLimitKey {rlkPrefix :: Text
rlkPrefix = Text
prefix, rlkSuffix :: Text
rlkSuffix = Text
suffix}
instance ToJSON RateLimitKey where
toJSON :: RateLimitKey -> Value
toJSON (RateLimitKey Text
prefix Text
suffix) = Text -> Text -> Value
prefixedKeyToJSON Text
prefix Text
suffix
instance FromJSON RateLimitKey where
parseJSON :: Value -> Parser RateLimitKey
parseJSON = String
-> (Text -> Text -> RateLimitKey) -> Value -> Parser RateLimitKey
forall a. String -> (Text -> Text -> a) -> Value -> Parser a
prefixedKeyParseJSON String
"RateLimitKey" Text -> Text -> RateLimitKey
toRateLimitKey
rateLimitKeyText :: RateLimitKey -> Text
rateLimitKeyText :: RateLimitKey -> Text
rateLimitKeyText (RateLimitKey Text
prefix Text
suffix) = Text -> Text -> Text
prefixedKeyText Text
prefix Text
suffix
data RateLimitPolicy = RateLimitPolicy
{ RateLimitPolicy -> Text
policyPrefix :: Text
, RateLimitPolicy -> Double
policyMax :: Double
, RateLimitPolicy -> Double
policyRefill :: Double
, RateLimitPolicy -> NominalDiffTime
policyInterval :: NominalDiffTime
}
deriving stock (RateLimitPolicy -> RateLimitPolicy -> Bool
(RateLimitPolicy -> RateLimitPolicy -> Bool)
-> (RateLimitPolicy -> RateLimitPolicy -> Bool)
-> Eq RateLimitPolicy
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RateLimitPolicy -> RateLimitPolicy -> Bool
== :: RateLimitPolicy -> RateLimitPolicy -> Bool
$c/= :: RateLimitPolicy -> RateLimitPolicy -> Bool
/= :: RateLimitPolicy -> RateLimitPolicy -> Bool
Eq, Eq RateLimitPolicy
Eq RateLimitPolicy =>
(RateLimitPolicy -> RateLimitPolicy -> Ordering)
-> (RateLimitPolicy -> RateLimitPolicy -> Bool)
-> (RateLimitPolicy -> RateLimitPolicy -> Bool)
-> (RateLimitPolicy -> RateLimitPolicy -> Bool)
-> (RateLimitPolicy -> RateLimitPolicy -> Bool)
-> (RateLimitPolicy -> RateLimitPolicy -> RateLimitPolicy)
-> (RateLimitPolicy -> RateLimitPolicy -> RateLimitPolicy)
-> Ord RateLimitPolicy
RateLimitPolicy -> RateLimitPolicy -> Bool
RateLimitPolicy -> RateLimitPolicy -> Ordering
RateLimitPolicy -> RateLimitPolicy -> RateLimitPolicy
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: RateLimitPolicy -> RateLimitPolicy -> Ordering
compare :: RateLimitPolicy -> RateLimitPolicy -> Ordering
$c< :: RateLimitPolicy -> RateLimitPolicy -> Bool
< :: RateLimitPolicy -> RateLimitPolicy -> Bool
$c<= :: RateLimitPolicy -> RateLimitPolicy -> Bool
<= :: RateLimitPolicy -> RateLimitPolicy -> Bool
$c> :: RateLimitPolicy -> RateLimitPolicy -> Bool
> :: RateLimitPolicy -> RateLimitPolicy -> Bool
$c>= :: RateLimitPolicy -> RateLimitPolicy -> Bool
>= :: RateLimitPolicy -> RateLimitPolicy -> Bool
$cmax :: RateLimitPolicy -> RateLimitPolicy -> RateLimitPolicy
max :: RateLimitPolicy -> RateLimitPolicy -> RateLimitPolicy
$cmin :: RateLimitPolicy -> RateLimitPolicy -> RateLimitPolicy
min :: RateLimitPolicy -> RateLimitPolicy -> RateLimitPolicy
Ord, Int -> RateLimitPolicy -> ShowS
[RateLimitPolicy] -> ShowS
RateLimitPolicy -> String
(Int -> RateLimitPolicy -> ShowS)
-> (RateLimitPolicy -> String)
-> ([RateLimitPolicy] -> ShowS)
-> Show RateLimitPolicy
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RateLimitPolicy -> ShowS
showsPrec :: Int -> RateLimitPolicy -> ShowS
$cshow :: RateLimitPolicy -> String
show :: RateLimitPolicy -> String
$cshowList :: [RateLimitPolicy] -> ShowS
showList :: [RateLimitPolicy] -> ShowS
Show)
instance AdmissionPolicy RateLimitPolicy where
policyPrefixOf :: RateLimitPolicy -> Text
policyPrefixOf = RateLimitPolicy -> Text
policyPrefix
tokenBucket :: Text -> Double -> NominalDiffTime -> RateLimitPolicy
tokenBucket :: Text -> Double -> NominalDiffTime -> RateLimitPolicy
tokenBucket Text
prefix Double
count NominalDiffTime
period =
RateLimitPolicy
{ policyPrefix :: Text
policyPrefix = Text
prefix
, policyMax :: Double
policyMax = Double
count
, policyRefill :: Double
policyRefill = Double
count
, policyInterval :: NominalDiffTime
policyInterval = NominalDiffTime -> NominalDiffTime -> NominalDiffTime
forall a. Ord a => a -> a -> a
max NominalDiffTime
minRefillInterval NominalDiffTime
period
}
minRefillInterval :: NominalDiffTime
minRefillInterval :: NominalDiffTime
minRefillInterval = NominalDiffTime
1e-6
type RateLimitFor payload = Selector RateLimitPolicy payload (Maybe RateLimitKey)
noLimit :: RateLimitFor payload
noLimit :: forall payload. RateLimitFor payload
noLimit = Selector RateLimitPolicy payload (Maybe RateLimitKey)
forall p payload key. Selector p payload (Maybe key)
selectNone
limitBy :: RateLimitPolicy -> (payload -> Text) -> RateLimitFor payload
limitBy :: forall payload.
RateLimitPolicy -> (payload -> Text) -> RateLimitFor payload
limitBy = (Text -> Text -> RateLimitKey)
-> RateLimitPolicy
-> (payload -> Text)
-> Selector RateLimitPolicy payload (Maybe RateLimitKey)
forall p key payload.
AdmissionPolicy p =>
(Text -> Text -> key)
-> p -> (payload -> Text) -> Selector p payload (Maybe key)
selectBy Text -> Text -> RateLimitKey
toRateLimitKey
globalLimit :: RateLimitPolicy -> Text -> RateLimitFor payload
globalLimit :: forall payload. RateLimitPolicy -> Text -> RateLimitFor payload
globalLimit RateLimitPolicy
pol Text
suffix = RateLimitPolicy -> (payload -> Text) -> RateLimitFor payload
forall payload.
RateLimitPolicy -> (payload -> Text) -> RateLimitFor payload
limitBy RateLimitPolicy
pol (Text -> payload -> Text
forall a b. a -> b -> a
const Text
suffix)
limitByCase :: (Bounded k, Enum k, Eq k) => (payload -> k) -> (k -> RateLimitFor payload) -> RateLimitFor payload
limitByCase :: forall k payload.
(Bounded k, Enum k, Eq k) =>
(payload -> k)
-> (k -> RateLimitFor payload) -> RateLimitFor payload
limitByCase = (payload -> k)
-> (k -> Selector RateLimitPolicy payload (Maybe RateLimitKey))
-> Selector RateLimitPolicy payload (Maybe RateLimitKey)
forall k payload policy a.
(Bounded k, Enum k, Eq k) =>
(payload -> k)
-> (k -> Selector policy payload a) -> Selector policy payload a
selectByCase
class HasRateLimit payload where
rateLimitFor :: RateLimitFor payload
rateLimitFor = RateLimitFor payload
forall payload. RateLimitFor payload
noLimit
rateLimitCost :: payload -> Double
rateLimitCost payload
_ = Double
defaultRateLimitCost
instance {-# OVERLAPPABLE #-} HasRateLimit payload
defaultRateLimitCost :: Double
defaultRateLimitCost :: Double
defaultRateLimitCost = Double
1
instance (HasRateLimit payload) => CollectFor payload RateLimitPolicy where
collectFor :: Set RateLimitPolicy
collectFor = Selector RateLimitPolicy payload (Maybe RateLimitKey)
-> Set RateLimitPolicy
forall policy payload a.
Ord policy =>
Selector policy payload a -> Set policy
collectPolicies (forall payload. HasRateLimit payload => RateLimitFor payload
rateLimitFor @payload)
type RegistryRateLimitPolicies registry = RegistryPolicies registry RateLimitPolicy
registryRateLimitPolicies :: forall registry. (RegistryRateLimitPolicies registry) => Set RateLimitPolicy
registryRateLimitPolicies :: forall (registry :: JobPayloadRegistry).
RegistryRateLimitPolicies registry =>
Set RateLimitPolicy
registryRateLimitPolicies = forall (registry :: JobPayloadRegistry) p.
(Ord p, RegistryPolicies registry p) =>
Set p
registryPolicies @registry @RateLimitPolicy
registryRateLimitTables :: forall registry. (RegistryRateLimitPolicies registry) => [(Text, Bool)]
registryRateLimitTables :: forall (registry :: JobPayloadRegistry).
RegistryRateLimitPolicies registry =>
[(Text, Bool)]
registryRateLimitTables = forall (registry :: JobPayloadRegistry) p.
RegistryPolicies registry p =>
[(Text, Bool)]
registryPolicyTables @registry @RateLimitPolicy