From 52b8b34827c6e135ec5852d691fe371fa0088160 Mon Sep 17 00:00:00 2001 From: CMGS Date: Wed, 7 Oct 2026 10:51:08 +0800 Subject: [PATCH] test(tenants/pg): the cached-tenant test stops the invalidation listener before the database goes The listener evicts the cache on its first connect and again on the Put's NOTIFY, both after Open returns and on their own schedule. The test read the cache as populated, closed the pool, and then one of those evictions landed, so Resolve went to the closed pool. The database-down case it proves has no live listener either, so the test stops it first; the old version failed 2 of 40 runs locally with the CI message. --- sandboxd/tenants/pg/pg_test.go | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/sandboxd/tenants/pg/pg_test.go b/sandboxd/tenants/pg/pg_test.go index 28ab7bcf6..d81a748f7 100644 --- a/sandboxd/tenants/pg/pg_test.go +++ b/sandboxd/tenants/pg/pg_test.go @@ -60,14 +60,10 @@ func TestACachedTenantOutlivesTheDatabase(t *testing.T) { if _, err := s.Put(ctx, tenantstest.Record("u-1", "warm", 0, "")); err != nil { t.Fatalf("put: %v", err) } - cached := func() bool { - _, err := s.Resolve(ctx, tenantstest.Sum("warm")) - s.mu.RLock() - defer s.mu.RUnlock() - return err == nil && s.byToken[tenantstest.Sum("warm")] == "u-1" - } - if !tenantstest.Eventually(t, cached) { - t.Fatal("u-1 never landed in the cache") + s.stop() + <-s.done + if r, err := s.Resolve(ctx, tenantstest.Sum("warm")); err != nil || r.Name != "u-1" { + t.Fatalf("resolve before the database goes: %+v %v", r, err) } s.pool.Close() if r, err := s.Resolve(ctx, tenantstest.Sum("warm")); err != nil || r.Name != "u-1" {