shad-go/ratelimit/README.md

33 lines
2.1 KiB
Markdown
Raw Permalink Normal View History

2021-03-02 18:05:37 +00:00
# ratelimit
Напишите примитив синхронизации, ограничивающий число вызовов на интервале времени.
2021-03-11 17:22:50 +00:00
2021-03-02 18:05:37 +00:00
```go
func NewLimiter(maxCount int, interval time.Duration) *Limiter
func (l *Limiter) Acquire(ctx context.Context) error
2021-03-05 11:06:01 +00:00
func (l *Limiter) Stop()
2021-03-02 18:05:37 +00:00
```
2021-03-11 17:22:50 +00:00
Пользователь создаёт `*Limiter`, указывая параметры `maxCount` и `interval`.
После этого, пользователь вызывает `Acquire` из многих горутин. Некоторые из вызовов `Acquire` могут завершиться сразу,
а некоторые могут заблокироваться.
2022-03-06 02:06:00 +00:00
`Limiter` должен гарантировать, что на любом интервале времени `interval` не больше `maxCount` вызовов
2021-03-11 17:22:50 +00:00
`Acquire` могут завершиться без ошибки. Например, если `interval` равен `1s`, `maxCount` равен 100,
и 200 горутин сделали вызов `Acquire` одновременно, то 100 горутин должны выйти из `Acquire` сразу, а 100 других должны
заблокироваться на секунду.
2021-03-02 18:05:37 +00:00
Каждый вызов `Acquire` должен либо завершаться успешно, либо завершаться с ошибкой в случае если `ctx` отменили
2021-03-05 11:20:55 +00:00
во время ожидания. Об отмене `ctx` нужно узнавать по закрытию канала `ctx.Done()`. Если `ctx` отменён,
2021-03-05 11:06:01 +00:00
нужно возвращать ошибку `ctx.Err()`.
2022-03-06 02:06:00 +00:00
Вызовы `Acquire()` после `Stop()` должны сразу завершаться с ошибкой ErrStopped.
Эту задачу можно решить многими способами, но мы хотим решение где
`Limiter` работает используя одну управляющую горутину. Эта горутина
должна запускаться в `NewLimiter` и останавливаться в `Stop`.