fix(testing): bound the waits in the new-enemy e2e test - #3347
Draft
vroldanbet wants to merge 1 commit into
Draft
vroldanbet wants to merge 1 commit into
vroldanbet wants to merge 1 commit into
Conversation
vroldanbet
force-pushed
the
perf/datastore-pool-prepopulation
branch
from
September 21, 2026 20:07
3f66c1a to
5f7f944
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
vroldanbet
force-pushed
the
perf/datastore-pool-prepopulation
branch
from
September 21, 2026 20:30
5f7f944 to
ffd1af1
Compare
vroldanbet
force-pushed
the
fix/newenemy-e2e-unbounded-waits
branch
from
September 21, 2026 20:31
ad93a78 to
229805f
Compare
vroldanbet
force-pushed
the
perf/datastore-pool-prepopulation
branch
from
September 22, 2026 08:24
ffd1af1 to
242cdd3
Compare
vroldanbet
force-pushed
the
fix/newenemy-e2e-unbounded-waits
branch
from
September 22, 2026 09:25
229805f to
8be0de6
Compare
vroldanbet
force-pushed
the
perf/datastore-pool-prepopulation
branch
from
September 22, 2026 10:16
242cdd3 to
ec17b8a
Compare
vroldanbet
force-pushed
the
fix/newenemy-e2e-unbounded-waits
branch
from
September 22, 2026 10:16
8be0de6 to
73d045d
Compare
vroldanbet
force-pushed
the
perf/datastore-pool-prepopulation
branch
from
September 22, 2026 10:18
ec17b8a to
8fe51ed
Compare
vroldanbet
force-pushed
the
fix/newenemy-e2e-unbounded-waits
branch
2 times, most recently
from
September 22, 2026 10:18
c8a521b to
449af85
Compare
vroldanbet
force-pushed
the
perf/datastore-pool-prepopulation
branch
from
September 22, 2026 14:13
8fe51ed to
3ead613
Compare
TestNoNewEnemy issues its setup writes with no deadline of their own: fillSchema and namespacesForNode passed context.Background() outright, and fill passed the suite context, whose only deadline is the go test timeout. namespacesForNode's search loop is likewise unbounded. So when a single write stops making progress, the test does not fail -- it sits there in silence until the 30-minute timeout, then reports one line. This has happened three times in recent CI history: twice on main (runs 30120682812 and 28831661566) and once on the pool-prepopulation branch, each burning 29 minutes on a large runner. A re-run of the same commit passed in 50s, so this is a stall, not a regression. What the stall looks like, from the node logs of the last one: the test configures 64KiB single-replica ranges with a 10s GC TTL, fills 4000 namespaces, and then WriteSchema's full read of namespace_config -- 17ms up to that point -- steps to 12.48s and stays there. A read span that wide cannot be refreshed, so every commit fails RETRY_SERIALIZABLE and SpiceDB retries with backoff indefinitely. The test cannot prevent that, but it should not wait 29 minutes to notice it. Each setup write now gets a 90s budget of its own and names itself when it expires; the namespace search gets 5 minutes, against a worst passing run of about two. leaderFromRangeRow no longer calls log.Fatal, which exited the binary outright and skipped the cleanup that stops three CockroachDB nodes and nine SpiceDB processes -- unacceptable now that its callers hold contexts that can expire. Claude-Session: https://claude.ai/code/session_017DF2mdm5e2RGbjPWtmYetd
vroldanbet
force-pushed
the
fix/newenemy-e2e-unbounded-waits
branch
from
September 22, 2026 14:14
449af85 to
3eb6148
Compare
vroldanbet
marked this pull request as ready for review
September 29, 2026 17:18
vroldanbet
marked this pull request as draft
September 29, 2026 18:17
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Gives every setup write in
TestNoNewEnemya deadline of its own, bounds thenamespacesForNodesearch loop, and stopsleaderFromRangeRowcallinglog.Fatal.Test-only.
Skip-Changelog.Why
E2E (22.1.5)on #3339 failed after 29m53s. It is not a regression fromthat PR: a re-run of the identical commit (
3f66c1ac) passed in 49.9s, andthe same 29-minute failure has already happened twice on
main(run 30120682812,
run 28831661566),
with the identical signature:
--- FAIL: TestNoNewEnemy (1740.0s).1740s is exactly the budget the test gives itself — the 30-minute
go testtimeout minus the one-minute cleanup margin it subtracts in
TestNoNewEnemy.The test does not fail because something went wrong; it fails because it ran
out of clock while waiting, in silence, on a single gRPC call.
From the node logs of the failing run, where the time actually went:
fillSchema, 4000 namespacesnamespacesForNode, 57 attemptsWriteSchemaThe stall itself is a property of the cluster this test deliberately builds.
setSmallRangesconfigures 64KiB ranges,num_replicas = 1and a 10s GC TTL;after 4000 namespaces,
namespace_config's full read inside SpiceDB'sWriteSchematransaction — 17ms on every one of the preceding 75 calls —steps to 12.48s and stays pinned there:
A read span that wide cannot be refreshed, so every commit comes back
RETRY_SERIALIZABLE - failed preemptive refreshand SpiceDB retries withexponential backoff — 20 attempts, spacing out to six minutes apart — until
the client's gRPC connection hits
MaxConnectionAgeand the RPC dies withreceived prior goaway: ... "max_age".The test cannot prevent that. What it should not do is take 29 minutes of a
large runner to notice, and then report a single confusing line about a gRPC
GOAWAY rather than "this write never completed".
How
fillWriteTimeout(90s) bounds eachWriteSchema/WriteRelationshipsbatch. On a healthy cluster these take tens of milliseconds and the slowest
ever recorded in a passing run is under a second, so the budget is ~100x
headroom; the point is that it is finite.
fillSchemapreviously usedcontext.Background(), honouring neither the suite deadline nor any boundof its own.
namespaceSearchTimeout(5m) boundsnamespacesForNode. The loop isguess-and-check against random range placement; passing runs have needed
between 48 and 646 attempts, the latter taking a bit over two minutes.
It now also fails the test when it gives up, instead of returning a zero
NamespaceNamesthat the caller would happily fill relationships into.leaderFromRangeRowtakestesting.TBand usesrequire.NoErrorinsteadof
log.Fatal.log.Fatalexits the binary: no test output, not.Cleanup, and so noStop()for the three CockroachDB nodes and nineSpiceDB processes the suite started. Harmless while the only route here was
a genuinely broken cluster; not harmless now that callers hold contexts that
can expire.
Net effect: this failure mode becomes a ~2 minute job that says which write
stalled, instead of a 30 minute job that says nothing.
References
Two findings worth recording separately, neither addressed here:
TestNoNewEnemyis flaky onmain, independent of this stack. Three1740s timeouts in recent history.
WriteSchemareads all ofnamespace_configinside itsread-write transaction. Once that table is large enough for the read span
to exceed CockroachDB's refresh-span budget, a pushed transaction can never
refresh, so
WriteSchemaretries forever rather than failing. This testreaches that state artificially, but a large real schema on a contended
cluster is the same shape.