In case when ctx that passed to Effector canceled by timeout before refill ticker fires - possible lost token. Here is example:
func TestRefill(t *testing.T) {
const max uint = 1
const refillDuration = time.Second
callsCounter := 0
effector := callsCountFunction(&callsCounter)
// Any context with cancellation (WithTimeout, etc)
ctx, cancel := context.WithCancel(context.Background())
throttle := Throttle(effector, max, max, refillDuration)
_, err := throttle(ctx)
if err != nil {
t.Fatal("unexpected error: ", err)
}
if callsCounter != 1 {
t.Fatal("unexpected callsCounter value: ", callsCounter)
}
// Request cancelled by timeout before refillDuration. (If comment this line โ test will be success)
cancel()
// Waiting token refill . x2 for ensure that token refiled
time.Sleep(refillDuration * 2)
ctx, cancel = context.WithCancel(context.Background())
defer cancel()
_, err = throttle(ctx)
if err != nil {
t.Fatal("unexpected error: ", err)
}
if callsCounter != 2 {
t.Fatal("unexpected callsCounter value: ", callsCounter)
}
}