Merge remote-tracking branch 'origin/master' into v2

This commit is contained in:
2026-09-25 11:08:24 -07:00
3 changed files with 38 additions and 5 deletions
@@ -32,10 +32,10 @@ func TestParallelAndQueue(t *testing.T) {
go func() { go func() {
rel, waited, err := l.Acquire(ctx, "alpha", "m") rel, waited, err := l.Acquire(ctx, "alpha", "m")
if err == nil { if err == nil {
defer rel()
if waited < 40*time.Millisecond { if waited < 40*time.Millisecond {
err = errors.New("third acquire did not wait") err = errors.New("third acquire did not wait")
} }
rel() // release before reporting, so the final count check cannot race it
} }
got3 <- err got3 <- err
}() }()
@@ -85,6 +85,19 @@ func TestDifferentConversationsSpreadByFreeSlots(t *testing.T) {
} }
} }
// waitUntil polls cond every 5 ms for up to two seconds and fails the test if it never holds.
func waitUntil(t *testing.T, cond func() bool) {
t.Helper()
deadline := time.Now().Add(2 * time.Second)
for time.Now().Before(deadline) {
if cond() {
return
}
time.Sleep(5 * time.Millisecond)
}
t.Fatal("condition not reached within two seconds")
}
func TestQueueFullIs503(t *testing.T) { func TestQueueFullIs503(t *testing.T) {
alpha := newUpstream(t, "alpha") alpha := newUpstream(t, "alpha")
alpha.delay = 400 * time.Millisecond alpha.delay = 400 * time.Millisecond
@@ -99,14 +112,20 @@ hosts = ["alpha"]
default_model = "shared" default_model = "shared"
`, alpha) `, alpha)
codes := make(chan int, 3) codes := make(chan int, 3)
for i := 1; i <= 3; i++ { fire := func(i int) {
go func(i int) { go func() {
resp := r.post("/r/v1/chat/completions", conversation(i, 1)) resp := r.post("/r/v1/chat/completions", conversation(i, 1))
drain(resp) drain(resp)
codes <- resp.StatusCode codes <- resp.StatusCode
}(i) }()
time.Sleep(30 * time.Millisecond) // arrival order: 1 runs, 2 queues, 3 finds the queue full
} }
// Arrival order is enforced by watching the limiter, not by sleeping: 1 runs, 2 queues,
// 3 finds the queue full.
fire(1)
waitUntil(t, func() bool { return r.lim.InFlight("alpha", "shared") == 1 })
fire(2)
waitUntil(t, func() bool { return r.lim.Queued("alpha", "shared") == 1 })
fire(3)
got := map[int]int{} got := map[int]int{}
for i := 0; i < 3; i++ { for i := 0; i < 3; i++ {
got[<-codes]++ got[<-codes]++
+14
View File
@@ -82,3 +82,17 @@ reason.
per argv element, so check 3 could never pass. Test fault (mine): the body now goes through a per argv element, so check 3 could never pass. Test fault (mine): the body now goes through a
file (`-d @file`). Ornith diagnosed it correctly. Resumed from the working tree with the file (`-d @file`). Ornith diagnosed it correctly. Resumed from the working tree with the
corrected script. corrected script.
- 2026-09-25, task 05, third session: `TestParallelAndQueue` (v1 given `limiter_test.go`) failed
once under full-suite `-race` load with `after releases: inflight 1 queued 0`. Test fault
(mine): the third acquirer sent its result before its deferred release ran, so the final
count check could observe one slot still held. The given file now releases before reporting.
Ornith found it and measured the flake rate rather than editing the protected file.
- 2026-09-25, task 05, third session: also saw `TestQueueFullIs503` fail with
`Requests:3 Errors:2`. Two causes. (1) Test fault (mine): arrival order rested on 30 ms
sleeps; the given test now waits on the limiter's in-flight and queued counts. (2) A real v1
defect, verified by the owner with a diagnostic build (5 of 8 runs): after a forward completes,
`forward.go` checks `r.Context().Err()` and, when the client has already closed its connection,
records a served 200 as a 499 "client cancelled" error. Cancellation must be what the reverse
proxy itself observed, never a post-hoc context check. Scheduled as v2.1 task 01; not fixed in
task 05, which is wiring only. The session then ended on a refused read of `/proc/loadavg` —
the seventh refusal-ending. Model fault.