provider: a key that says it is out of its windows while they are being read has them read again once that reading is back (TestRestingKeyReadAgainInAnOrderedGroup red on macOS CI, runs 37467016755 and on main since 555f5706) — since 555f5706 the first planning of a lone key reads its windows behind the request. When that reading was still out as the key refused for quota, StaleKeyAllowance only zeroed the time it was read, and the reading, asked before the refusal, came back, set it to now and was trusted for a minute: the rest out of the key's windows wasn't lifted by the reading planned after it, though its limit had been raised. StaleKeyAllowance now marks a reading that is out (stale), and once it is back the key's windows are read again at once; forgetting every key's windows clears the mark. TestKeyAllowanceStaleMidRead (the first reading held until after StaleKeyAllowance, then answered; the second answered with the week half used) fails without the change (asked once) and passes -race -count=20 with the other TestKeyAllowance tests. The gateway test fails every time with its first reading delayed 300 ms ("still rests by window …, its windows read 2 times", as CI said) and passes with the change. go test -race ./internal/provider (8 of 9 runs pass; the first run's failure wasn't kept and didn't come back), go test -race -count=10 -run 'TestResting|Key|Lone|Allowance' ./internal/gateway, go vet, gofmt -l pass.
This commit is contained in:
1 parent
29f4909262
commit
ee2588c268
2 files changed
+40
-2
No files matched your search
@@ -31,6 +31,9 @@ type keyAllowance struct {
|
||||
a Allowance
|
||||
at time.Time // when read; zero to read again at the next ask
|
||||
loading bool
|
||||
// stale: made stale (StaleKeyAllowance) while a reading was out, which
|
||||
// was asked before the key said it was out and is followed by another
|
||||
stale bool
|
||||
}
|
||||
|
||||
// keyAllowanceAge is how long a key's windows as read go unasked again;
|
||||
@@ -124,6 +127,10 @@ func readKeyAllowance(p Provider, id string, gen int) {
|
||||
}
|
||||
e.loading, e.at = false, now
|
||||
renewed := err == nil && e.keep(allowanceOf(ws, now), SpentShareOf(p.Routing), now)
|
||||
if e.stale {
|
||||
e.stale, e.loading, e.at = false, true, time.Time{}
|
||||
go readKeyAllowance(p, id, gen)
|
||||
}
|
||||
c.Unlock()
|
||||
if renewed {
|
||||
tellRenewed("", id)
|
||||
@@ -215,7 +222,7 @@ func StaleKeyAllowance(p Provider) {
|
||||
c := &keyAllowances
|
||||
c.Lock()
|
||||
if e := c.m[keyAllowanceID(p)]; e != nil {
|
||||
e.at = time.Time{}
|
||||
e.at, e.stale = time.Time{}, e.loading
|
||||
}
|
||||
c.Unlock()
|
||||
}
|
||||
@@ -228,7 +235,7 @@ func forgetKeyAllowances() {
|
||||
c := &keyAllowances
|
||||
c.Lock()
|
||||
for _, e := range c.m {
|
||||
e.at, e.loading = time.Time{}, false
|
||||
e.at, e.loading, e.stale = time.Time{}, false, false
|
||||
}
|
||||
c.gen++
|
||||
c.Unlock()
|
||||
|
||||
@@ -348,6 +348,37 @@ func TestKeyAllowanceForgottenMidRead(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// A key that says it is out of its windows while a reading of them is
|
||||
// out has them read again once that reading is back, without being asked:
|
||||
// the reading was asked before, and the rest it would lift is planned on
|
||||
// the one after (an ordered group's member read as it is planned).
|
||||
func TestKeyAllowanceStaleMidRead(t *testing.T) {
|
||||
keyLimitsHome(t)
|
||||
week := time.Now().Add(72 * time.Hour).Truncate(time.Second)
|
||||
release := make(chan struct{})
|
||||
var first atomic.Bool
|
||||
srv, asked := sub2apiServer(t, func() ([]byte, int) {
|
||||
if first.CompareAndSwap(false, true) {
|
||||
<-release
|
||||
return weekUsed(t, "800", week), 200
|
||||
}
|
||||
return weekUsed(t, "400", week), 200
|
||||
})
|
||||
var once sync.Once
|
||||
t.Cleanup(func() { once.Do(func() { close(release) }) })
|
||||
p := sub2apiKey(srv)
|
||||
KeyAllowance(p)
|
||||
for asked.Load() < 1 {
|
||||
time.Sleep(5 * time.Millisecond)
|
||||
}
|
||||
StaleKeyAllowance(p) // out of its week, as the request found
|
||||
once.Do(func() { close(release) })
|
||||
waitAllowance(t, p, func(a Allowance) bool { u, _ := a.For("gpt-6-astra", time.Now()); return u > 0 && u < 100 })
|
||||
if n := asked.Load(); n != 2 {
|
||||
t.Fatalf("asked %d times", n)
|
||||
}
|
||||
}
|
||||
|
||||
// Until the key is first read (magpie just started), its windows are the
|
||||
// ones its card last showed, kept on disk; a window whose reset passed
|
||||
// since is empty again.
|
||||
|
||||
Reference in new issue
Block a user