allegro / allegro/bigcache

TestCacheLen is flaky: a 1s LifeWindow expires entries at the next Unix second, not 1s after insertion

未关闭
#433 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
主要语言
Go
星标
8.2k
派生
614
平均合并
5 天 12 小时
30 天内合并 PR
1

描述

`TestCacheLen` fails intermittently on CI with counts well below 1337:

```
expected: 1337, actual: 933
```

It isn't a slow-machine problem. The loop doesn't need to take a second, it only needs to cross a second boundary.

`clock.Epoch()` returns `time.Now().Unix()`, so timestamps have whole-second resolution. `isExpired` is

```go
return currentTimestamp-oldestTimestamp >= s.lifeWindow
```

and the test sets `LifeWindow: time.Second`. An entry written at Unix second T counts as expired as soon as the clock reads T+1, which can be a millisecond later. `set` calls `onEvict` on the oldest entry, so every `Set` after the crossing evicts one. Crossing at iteration k leaves roughly k entries, and 933 is consistent with that. `t.Parallel()` means the loop starts at an arbitrary phase within the second, which is why it usually passes.

I couldn't get it to fail by just running the suite (master passed 3 times plain, and 3 more under CPU load). Phase-aligning it reproduces it every time. On master `ae1c781`, sleeping until ~5ms before the next second and then running the identical loop:

```
attempt 0: expected 1337, got 1204
attempt 1: expected 1337, got 957
attempt 2: expected 1337, got 1058
```

Happy to send a PR if you have a preference on the fix. I can pin the test to a mock clock, or raise `LifeWindow` so a boundary crossing stops mattering. There's arguably a separate question about whether a 1s `LifeWindow` should mean "until the next second" rather than "for one second", but that's a behaviour change and I didn't want to assume.

I used a coding agent to help pin down the repro.

贡献指南

这个仓库没有索引到贡献指南

评估

这个 Issue 还没有评估数据。

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。