Skip to content

test(scheduler): make the LambdaGuard control catch a non-blocking harness (#971 follow-ups) - #988

Merged
cristim merged 1 commit into
LeanerCloud:mainfrom
IAmJSD:fix/971-followups
Oct 16, 2026
Merged

cristim merged 1 commit into
LeanerCloud:mainfrom
IAmJSD:fix/971-followups

Conversation

@IAmJSD

@IAmJSD IAmJSD commented Oct 16, 2026

Copy link
Copy Markdown
Collaborator

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

  1. Control subtest (background_collection_test.go):
    • The store stub now signals started and then blocks on an unbuffered release channel. It's a small blockingRefreshStore helper, and cleanup closes done, so nothing leaks.
    • The non-Lambda control waits for started and asserts collecting is held while the store call is blocked. It then sends on release with a 2s timeout, and asserts collecting is released.
    • If the stub stops blocking, nothing receives on release, so the control fails every time instead of depending on timing.
  2. Lambda subtest: the 200ms wait is gone. The guard returns before the synchronous claim of the flag, so the test asserts straight after the call: collecting is false, a non-blocking receive on started gets nothing, and GetGlobalConfig was never called. It now runs in about 0.00s.
  3. Guard comments: each test has a one-line comment naming the guard it pins.
Guard Pinned by
ListRecommendations mayCollect && !s.isLambda (scheduler.go:1183) LambdaSkipsBackgroundRefresh (also caught by ColdStart_Lambda_NeverMarksOrCollects)
kickColdStartCollection isLambda (:1452) ColdStart_Lambda_NeverMarksOrCollects only
maybeKickBackgroundRefresh isLambda (:1502) TestMaybeKickBackgroundRefresh_LambdaGuard/lambda_never_kicks only

Mutation probes

Each mutation was applied, run, and reverted.

Mutation Result
Guard at 1183 removed LambdaSkipsBackgroundRefresh and ColdStart_Lambda_NeverMarksOrCollects fail
Guard at 1452 removed Only ColdStart_Lambda_NeverMarksOrCollects fails
Guard at 1502 removed Only LambdaGuard/lambda_never_kicks fails; the control still passes
Stub no longer blocks (the wait on release deleted; the reviewer's mutant) The control fails with "the refresh's store call did not wait for release; the harness no longer blocks it", in 100 of 100 runs with -count=100

Verification

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, and go vet and gofmt are clean.
  • golangci-lint v2.10.1 reports 0 issues.
  • git-secrets (--register-aws plus .gitallowed) is clean on both changed files.
  • git merge-tree against current origin/main is 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

…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>
@coderabbitai

coderabbitai Bot commented Oct 16, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

  • Run on-demand review

This review includes 2 billable files and costs up to $0.50.

Or wait 3 minutes for your next included review.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository: LeanerCloud/cloud-commitments-platform/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 4823c931-b33e-45e5-b311-911860bcc202
📥 Commits

Reviewing files that changed from the base of the PR and between adcd80c and 3f2dafa.

📒 Files selected for processing: 2
  • internal/scheduler/background_collection_test.go
  • internal/scheduler/scheduler_test.go
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@cristim cristim left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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: started is buffered (1), so a wrongly kicked goroutine cannot block on send; t.Cleanup closes done, 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.

@cristim

cristim commented Oct 16, 2026

Copy link
Copy Markdown
Member

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).

@IAmJSD IAmJSD added impact/internal Team-internal only triaged Item has been triaged priority/p3 Polish / idea / may never ship severity/low Minor harm urgency/this-quarter Within the quarter effort/xs Trivial / one-liner type/bug Defect labels Oct 16, 2026
@cristim

cristim commented Oct 16, 2026

Copy link
Copy Markdown
Member

Gate record for 3f2dafa (origin/main CLAUDE.md "Review gate"):

Merging at 3f2dafa with --match-head-commit.

@cristim
cristim merged commit 8aae08d into LeanerCloud:main Oct 16, 2026
25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/xs Trivial / one-liner impact/internal Team-internal only priority/p3 Polish / idea / may never ship severity/low Minor harm triaged Item has been triaged type/bug Defect urgency/this-quarter Within the quarter

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Follow-ups from #971 review: make the LambdaGuard control catch a non-blocking harness

2 participants