De-flake wfengine transient cover-retry spec (bookshelf-di2zy) #1432
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "bd-bookshelf-di2zy"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
internal/wfengine:[PANICKED!] LibraryScanWorkflow — transient cover failure retried [JustBeforeEach] returns no error.MaxAttempts=3 backoff), driving more executor events/goroutines through
go-workflows' in-memory
WorkflowTesterthan a single-attempt spec. Thetester's default 10s idle timeout is a real wall-clock timer racing the
event loop (
tester.goExecute:time.NewTimer(TestTimeout)vs thecallback channel) — under CPU starvation on a loaded CI runner the gap
between events can exceed 10s even though nothing is actually deadlocked,
triggering the panic.
BulkMetadataWorkflow'sretry-heavy spec (bookshelf-19lt): pass
tester.WithTestTimeout(60*time.Second).This spec in
scan_workflow_test.gowas the one retry-driving cover specstill missing that option.
retry-the-CI-job workaround — it corrects a tester construction option the
spec should have had from the start, matching the sibling pattern already
used elsewhere in the same package.
Test plan
go build ./...,go vet ./...cleango test -tags integration -run TestWfengine ./internal/wfengine/— full2106-spec suite green
--ginkgo.focus="transient cover failure retried"run 15x in arow, clean
GOMAXPROCS=2+ 20-30 concurrentyesloads) to approximate a loaded CI runner — no regressionmake testfull suite greenDocs: N/A because test infra only, no user-facing change.
Closes bead bookshelf-di2zy on merge.
Security review (bookshelf-di2zy)
Reviewed the diff for PR #1432 — a test-only de-flake of the "LibraryScanWorkflow — transient cover failure retried" spec in
internal/wfengine/scan_workflow_test.go.Scope confirmed: the entire diff is a single hunk adding
tester.WithTestTimeout(60*time.Second)to the existingtester.NewWorkflowTester[error](wfengine.LibraryScanWorkflow, ...)call plus an explanatory comment and atimeimport. No production (non-_test.go) code is touched, no assertion is removed or weakened, and the change matches the existing sibling pattern already used inbulk_workflow_test.go/recalc_scores_workflow_test.go. No secrets, credentials, or PII are introduced.No findings.
REVIEW VERDICT: 0 blocker, 0 major, 0 minor
Code Review — PR #1432 (bookshelf-di2zy)
No blockers or majors. This is a legitimate root-cause fix, not a mask.
Verification of root cause (not a race, not a masked assertion):
"No new events generated during workflow execution and no pending timers, workflow blocked?"togo-workflows@v1.4.1/tester/tester.go:470, which fires from a hardcodedTestTimeout: 10sidle-wait (tester.go:197) inside the tester's own event loop (tester.go:458-470) — this is a wall-clock idle-detection heuristic inside the third-party test harness, not a data race inscan_workflow_test.go's own state.coverCallCount/coverSucceeded(scan_workflow_test.go:298-299, 325-330) are correctly atomic-incremented inside the activity stub and read only afterwt.Execute()returns synchronously inJustBeforeEach(scan_workflow_test.go:335-337) — i.e. after the tester has fully drained the event loop. No async-side-effect race here; this confirms the panic is the harness's idle timer, not a test-state race.tester.WithTestTimeout) was already established and accepted for the identical failure mode in bookshelf-19lt / PR #397 (BulkMetadataWorkflow, June 2026) — same tester.go:470 panic under CI runner CPU contention, same fix. This PR is consistent precedent, not a novel workaround.Describeblock (scan_workflow_test.go:315), not applied file-wide.Confirmed NOT masking:
It("returns no error", ...)(scan_workflow_test.go:340-342) still asserts the workflow SUCCEEDED (workflowErr).NotTo(HaveOccurred())), not merely "an error occurred" or "did not panic."sleepwas added to pad timing;WithTestTimeoutonly raises the harness's own idle-panic ceiling, it does not change when real events fire.package wfengine_test(scan_workflow_test.go:1). No new white-box/internal access introduced.Describeblock (scan_workflow_test.go:294-351); no unrelated changes.[MINOR] internal/wfengine/scan_workflow_test.go:315-320 — The 60s timeout is generous but matches the existing accepted precedent (bookshelf-19lt used the same 60s value for a similar retry-heavy spec), so consistency is good; no action needed. Worth a passing note only: if this class of flake recurs in additional retry-heavy specs, consider making
WithTestTimeout(60*time.Second)the default for any wfengine spec that exercisesMaxAttempts > 1fan-out, rather than fixing them one at a time as they flake (tracked informally, not blocking this PR).REVIEW VERDICT: 0 blocker, 0 major, 1 minor