token-limiter-concurrent-0.1.0.0: A thread-safe concurrent token-bucket rate limiter that guarantees fairness
Safe HaskellSafe-Inferred
LanguageHaskell2010

Control.Concurrent.TokenLimiter.Concurrent

Synopsis

Create

type Count = Word64 Source #

An amount of tokens

data TokenLimitConfig Source #

A configuration for TokenLimiter

Constructors

TokenLimitConfig 

Fields

Instances

Instances details
Generic TokenLimitConfig Source # 
Instance details

Defined in Control.Concurrent.TokenLimiter.Concurrent

Associated Types

type Rep TokenLimitConfig :: Type -> Type #

Show TokenLimitConfig Source # 
Instance details

Defined in Control.Concurrent.TokenLimiter.Concurrent

Eq TokenLimitConfig Source # 
Instance details

Defined in Control.Concurrent.TokenLimiter.Concurrent

type Rep TokenLimitConfig Source # 
Instance details

Defined in Control.Concurrent.TokenLimiter.Concurrent

type Rep TokenLimitConfig = D1 ('MetaData "TokenLimitConfig" "Control.Concurrent.TokenLimiter.Concurrent" "token-limiter-concurrent-0.1.0.0-DcHrU4XMkb37dFhrj1OAuv" 'False) (C1 ('MetaCons "TokenLimitConfig" 'PrefixI 'True) (S1 ('MetaSel ('Just "tokenLimitConfigInitialTokens") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Count) :*: (S1 ('MetaSel ('Just "tokenLimitConfigMaxTokens") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Count) :*: S1 ('MetaSel ('Just "tokenLimitConfigTokensPerSecond") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Count))))

type MonotonicTime = Word64 Source #

A type synonym for a number of "monotonic time" nanoseconds.

This only exists because it is also a Word64 and would be too easy to confuse with a Count.

data TokenLimiter Source #

A token bucket-based rate limiter

This token limiter is thread-safe and guarantees that:

Constructors

TokenLimiter 

Fields

Instances

Instances details
Generic TokenLimiter Source # 
Instance details

Defined in Control.Concurrent.TokenLimiter.Concurrent

Associated Types

type Rep TokenLimiter :: Type -> Type #

Eq TokenLimiter Source # 
Instance details

Defined in Control.Concurrent.TokenLimiter.Concurrent

type Rep TokenLimiter Source # 
Instance details

Defined in Control.Concurrent.TokenLimiter.Concurrent

type Rep TokenLimiter = D1 ('MetaData "TokenLimiter" "Control.Concurrent.TokenLimiter.Concurrent" "token-limiter-concurrent-0.1.0.0-DcHrU4XMkb37dFhrj1OAuv" 'False) (C1 ('MetaCons "TokenLimiter" 'PrefixI 'True) (S1 ('MetaSel ('Just "tokenLimiterConfig") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 TokenLimitConfig) :*: S1 ('MetaSel ('Just "tokenLimiterLastServiced") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 (MVar (MonotonicTime, Count)))))

makeTokenLimiter :: TokenLimitConfig -> IO TokenLimiter Source #

Make a token limiter

The initial number of tokens will be the minimum of the tokenLimitConfigInitialTokens and the tokenLimitConfigMaxTokens,

Use

tryDebit :: TokenLimiter -> Word64 -> IO Bool Source #

Check if we can debit a number of tokens, and do it if possible.

The returned boolean represents whether the tokens were debited.

Note that there is a small race-condition in which tryDebit sometimes returns False eventhough it could (maybe) have debited because another thread was currently waitDebit-ing without actually waiting (because it didn't need to wait).

waitDebit :: TokenLimiter -> Word64 -> IO (Maybe MonotonicDiffNanos) Source #

Wait until the given number of tokens can be debited.

Returns the time waited, for stats recording purposes.

Note: only reports the time waited due to rate-limiting this specific action, not the wall-clock time waited (that might include waiting for previous actions limited by this rate limiter to finish).

Note: debitor threads are serviced in FIFO order, so a request for a small (and currently satisfiable) number of tokens can still be delayed by a debit request for a larger amount of tokens.

Note: the wait time reported can be inflated due to scheduling inaccuracy. See https://gitlab.haskell.org/ghc/ghc/-/issues/16601.

newtype MonotonicDiffNanos Source #

Instances

Instances details
Generic MonotonicDiffNanos Source # 
Instance details

Defined in Control.Concurrent.TokenLimiter.Concurrent

Associated Types

type Rep MonotonicDiffNanos :: Type -> Type #

Show MonotonicDiffNanos Source # 
Instance details

Defined in Control.Concurrent.TokenLimiter.Concurrent

Eq MonotonicDiffNanos Source # 
Instance details

Defined in Control.Concurrent.TokenLimiter.Concurrent

Ord MonotonicDiffNanos Source # 
Instance details

Defined in Control.Concurrent.TokenLimiter.Concurrent

type Rep MonotonicDiffNanos Source # 
Instance details

Defined in Control.Concurrent.TokenLimiter.Concurrent

type Rep MonotonicDiffNanos = D1 ('MetaData "MonotonicDiffNanos" "Control.Concurrent.TokenLimiter.Concurrent" "token-limiter-concurrent-0.1.0.0-DcHrU4XMkb37dFhrj1OAuv" 'True) (C1 ('MetaCons "MonotonicDiffNanos" 'PrefixI 'True) (S1 ('MetaSel ('Just "unMonotonicDiffNanos") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Word64)))

Helper functions

computeCurrentCount :: TokenLimitConfig -> MonotonicTime -> Count -> MonotonicTime -> Count Source #

Compute the current number of tokens in a bucket purely.

You should not need this function.