import TokenBucket from 'tokenbucket' ; import { TooManyRequestsError } from '../../../../../errors' ; import { ServiceContext } from '../../typings' ; import { createTokenBucket } from '../../utils/tokenBucket' ; const responseMessageConcurrent = 'Rate Exceeded: Too many requests in execution' ; const responseMessagePerMinute = 'Rate Exceeded: Too many requests per minute' ; function noopMiddleware ( _ , next ) { return next ( ) ; } export function perMinuteRateLimiter ( rateLimit ? , globalLimiter ? ) { if ( ! rateLimit && ! globalLimiter ) { return noopMiddleware ; } const tokenBucket = createTokenBucket ( rateLimit , globalLimiter ) ; return function perMinuteRateMiddleware ( ctx , next ) { if ( ! tokenBucket . removeTokensSync ( 1 ) ) { throw new TooManyRequestsError ( responseMessagePerMinute ) ; } return next ( ) ; } ; } export function concurrentRateLimiter ( rateLimit ? ) { if ( ! rateLimit ) { return noopMiddleware ; } let reqsInExecution = 0 ; const maxRequests = rateLimit ; return async function concurrentRateMiddleware ( ctx , next ) { if ( reqsInExecution >= maxRequests ) { throw new TooManyRequestsError ( responseMessageConcurrent ) ; } reqsInExecution ++ ; try { await next ( ) ; } finally { reqsInExecution -- ; } } ; }