.. | ||
ratelimit.go | ||
ratelimit_test.go | ||
README.md |
ratelimit
Напишите примитив синхронизации, ограничивающий число вызовов на интервале времени.
func NewLimiter(maxCount int, interval time.Duration) *Limiter
func (l *Limiter) Acquire(ctx context.Context) error
func (l *Limiter) Stop()
Пользователь создаёт *Limiter
, указывая параметры maxCount
и interval
.
После этого, пользователь вызывает Acquire
из многих горутин. Некоторые из вызовов Acquire
могут завершиться сразу,
а некоторые могут заблокироваться.
Limiter
должен гарантировать, что на любом интервале времени interval
не больше maxCount
вызовов
Acquire
могут завершиться без ошибки. Например, если interval
равен 1s
, maxCount
равен 100,
и 200 горутин сделали вызов Acquire
одновременно, то 100 горутин должны выйти из Acquire
сразу, а 100 других должны
заблокироваться на секунду.
Каждый вызов Acquire
должен либо завершаться успешно, либо завершаться с ошибкой в случае если ctx
отменили
во время ожидания. Об отмене ctx
нужно узнавать по закрытию канала ctx.Done()
. Если ctx
отменён,
нужно возвращать ошибку ctx.Err()
.
Вызовы Acquire()
после Stop()
должны сразу завершаться с ошибкой ErrStopped.
Эту задачу можно решить многими способами, но мы хотим решение где
Limiter
работает используя одну управляющую горутину. Эта горутина
должна запускаться в NewLimiter
и останавливаться в Stop
.