Safe Haskell | None |
---|---|
Language | Haskell98 |
This module implements rate-limiting functionality for Haskell programs. Rate-limiting is useful when trying to control / limit access to a particular resource over time. For example, you might want to limit the rate at which you make requests to a server, as an administrator may block your access if you make too many requests too quickly. Similarly, one may wish to rate-limit certain communication actions, in order to avoid accidentally performing a denial-of-service attack on a critical resource.
The fundamental idea of this library is that given some basic information about the requests you wante rate limited, it will return you a function that hides all the rate-limiting detail. In short, you make a call to one of the function generators in this file, and you will be returned a function to use. For example:
do f <- generateRateLimitedFunction ... ... res1 <- f a ... res2 <- f b ...
The calls to the generated function (f) will be rate limited based on the
parameters given to generateRateLimitedFunction
.
generateRateLimitedFunction
is the most general version of the rate
limiting functionality, but specialized versions of it are also exported
for convenience.
- generateRateLimitedFunction :: forall req resp t. TimeUnit t => RateLimit t -> (req -> IO resp) -> ResultsCombiner req resp -> IO (req -> IO resp)
- data RateLimit a
- = PerInvocation a
- | PerExecution a
- type ResultsCombiner req resp = req -> req -> Maybe (req, resp -> (resp, resp))
- dontCombine :: ResultsCombiner a b
- rateLimitInvocation :: TimeUnit t => t -> (req -> IO resp) -> IO (req -> IO resp)
- rateLimitExecution :: TimeUnit t => t -> (req -> IO resp) -> IO (req -> IO resp)
Documentation
generateRateLimitedFunction Source #
:: TimeUnit t | |
=> RateLimit t | What is the rate limit for this action |
-> (req -> IO resp) | What is the action you want to rate limit, given as an a MonadIO function from requests to responses? |
-> ResultsCombiner req resp | A function that can combine requests if
rate limiting happens. If you cannot combine
two requests into one request, we suggest
using |
-> IO (req -> IO resp) |
The most generic way to rate limit an invocation.
The rate at which to limit an action.
PerInvocation a | Rate limit the action to invocation once per time unit. With this option, the time it takes for the action to take place is not taken into consideration when computing the rate, only the time between invocations of the action. This may cause the action to execute concurrently, as an invocation may occur while an action is still running. |
PerExecution a | Rate limit the action to execution once per time unit. With this option, the time it takes for the action to take plase is taken into account, and all actions will necessarily occur sequentially. However, if your action takes longer than the time unit given, then the rate of execution will be slower than the given unit of time. |
type ResultsCombiner req resp = req -> req -> Maybe (req, resp -> (resp, resp)) Source #
In some cases, if two requests are waiting to be run, it may be possible to combine them into a single request and thus increase the overall bandwidth. The rate limit system supports this, but requires a little additional information to make everything work out right. You may also need to do something a bit wonky with your types to make this work ... sorry.
The basic idea is this: Given two requests, you can either return Nothing (signalling that the two requests can be combined), or a Just with a new request representing the combination of the two requests. In addition, you will need to provide a function that can turn the response to this single request into two responses, one for each of the original requests.
I hope this description helps you work through the type, which I'll admit is a bit opaque.
dontCombine :: ResultsCombiner a b Source #
rateLimitInvocation :: TimeUnit t => t -> (req -> IO resp) -> IO (req -> IO resp) Source #
Rate limit the invocation of a given action. This is equivalent to calling
generateRateLimitedFunction
with a PerInvocation
rate limit and the
dontCombine
combining function.
rateLimitExecution :: TimeUnit t => t -> (req -> IO resp) -> IO (req -> IO resp) Source #
Rate limit the execution of a given action. This is equivalent to calling
generateRateLimitedFunction
with a PerExecution
rate limit and the
dontCombine
combining function.