Repository navigation
test(scheduler): make the LambdaGuard control catch a non-blocking harness (#971 follow-ups) - #988
Conversation
…rness Review follow-up on LeanerCloud#971: - The non-Lambda control now hands the blocked store call a value on an unbuffered release channel after asserting the collecting flag is held. If the harness stops blocking, nothing receives and the control fails every run instead of passing by timing. - The Lambda subtest drops its 200ms wait: the guard returns before the synchronous CAS, so the flag check plus a non-blocking receive on started are enough. - Each Lambda test names the isLambda guard it pins. Test-only; no production change. Refs LeanerCloud#962 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reached
This review includes 2 billable files and costs up to $0.50. Or wait 3 minutes for your next included review. View limit details
Comment |
cristim
left a comment
There was a problem hiding this comment.
Independent review of 3f2dafa: no actionable findings
Findings: none.
What I attacked (worktree at the SHA, all probes reverted):
- Guard probe: disabled the guard at scheduler.go:1502 (
if false && s.isLambda). TestMaybeKickBackgroundRefresh_LambdaGuard fails 3/3 in the "lambda never kicks" subtest ("collecting flag was claimed on Lambda"). - Harness probe: removed the release/done wait in blockingRefreshStore. The control fails 3/3 after 2s ("store call did not wait for release"). This closes #971 note 1 deterministically: the send on release only succeeds if the store call is blocked.
- Control asserts collecting is held while blocked, then releases and requires the flag to clear.
- Leaks/hangs:
startedis buffered (1), so a wrongly kicked goroutine cannot block on send; t.Cleanup closesdone, which frees the goroutine on every path (including t.Fatal).go test -race -count=10 ./internal/scheduler/passes. - The 200ms time.After on the Lambda path is gone (note 2); the guard-to-test mapping comments cover note 3 (lines 1183, 1452, 1502 match the pins).
- scheduler_test.go: only comments added. staleListRecommendations still uses WithBackgroundCollection(context.Background()) (scheduler_test.go:950). Merge with origin/main is clean (git merge-tree).
- Test-only, +76/-35 (additions well under 400).
Gate status:
- Independent review: this comment, at the SHA.
- CI on the SHA: all checks pass, CodeRabbit "rate limited" (optional per gate; exact-SHA local verification above covers it).
- Local verification: macOS, real scenario, fail-before/pass-after via the two mutations above.
- Labels: PR has none; #987 has no triage labels either, so there is nothing to mirror. Gap: #987 needs triage (NON-BLOCKING, maintainer action).
- Author is an external contributor; nothing pushed to their branch.
|
Correction to the independent review above (3f2dafa): its gate section says all checks pass, but that was wrong when it was posted. Unit Tests, Integration Tests, Build Docker Image and Security Scanning were still pending. The code verdict (no actionable findings) stands. The merge waits for CI to be green on this SHA, and for issue #987 to get triage labels to mirror (it has none). |
|
Gate record for 3f2dafa (origin/main CLAUDE.md "Review gate"):
Merging at 3f2dafa with --match-head-commit. |
Closes #987. This follows up #971 (issue #962), which merged at 83459e4 before this commit landed. The commit is cherry-picked unchanged onto main. Test-only.
Changes
background_collection_test.go):startedand then blocks on an unbufferedreleasechannel. It's a smallblockingRefreshStorehelper, and cleanup closesdone, so nothing leaks.startedand assertscollectingis held while the store call is blocked. It then sends onreleasewith a 2s timeout, and assertscollectingis released.release, so the control fails every time instead of depending on timing.collectingis false, a non-blocking receive onstartedgets nothing, andGetGlobalConfigwas never called. It now runs in about 0.00s.ListRecommendationsmayCollect && !s.isLambda(scheduler.go:1183)LambdaSkipsBackgroundRefresh(also caught byColdStart_Lambda_NeverMarksOrCollects)kickColdStartCollectionisLambda(:1452)ColdStart_Lambda_NeverMarksOrCollectsonlymaybeKickBackgroundRefreshisLambda(:1502)TestMaybeKickBackgroundRefresh_LambdaGuard/lambda_never_kicksonlyMutation probes
Each mutation was applied, run, and reverted.
LambdaSkipsBackgroundRefreshandColdStart_Lambda_NeverMarksOrCollectsfailColdStart_Lambda_NeverMarksOrCollectsfailsLambdaGuard/lambda_never_kicksfails; the control still passesreleasedeleted; the reviewer's mutant)-count=100Verification
All runs used
AWS_CONFIG_FILE=/dev/null AWS_SHARED_CREDENTIALS_FILE=/dev/null. These are unit tests with mocks.go test -race -count=1 ./internal/scheduler/: ok, both on the original branch and on this branch, which is cut from main at f44330b.go test -race -count=50 -run 'Lambda|LambdaGuard' ./internal/scheduler/: ok.go build ./...passes, andgo vetand gofmt are clean.--register-awsplus.gitallowed) is clean on both changed files.git merge-treeagainst currentorigin/mainis clean.Maintainer: please mirror #962's labels onto #987 and this PR (
impact/internal,triaged,priority/p3,severity/low,urgency/this-quarter,effort/xs,type/bug).🤖 Generated with Claude Code