Repository navigation
fix(purchase): shorten execution budget to 3m30s so the failure alert fits the Lambda timeout - #1578
Conversation
… fits the Lambda timeout The detached purchase phases run back to back: execution (4m), terminal save (30s) and, for a failed or partial row, the failure alert (30s, its own detached deadline). That is 300s, exactly lambda_timeout, leaving no margin for the request work before the detach or the response, so Lambda could end the invocation in the middle of the failure email. Per the acting owner's decision, shorten purchaseExecutionTimeout to 3m30s (no lambda_timeout change): 3m30s + 30s + 30s = 270s, plus the 30s margin fits 300s. TestLambdaTimeoutCoversPurchaseBudget now counts all three phases against every shipped Lambda timeout, and the comments and Terraform validation messages state the real sum. Closes LeanerCloud#1434 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 59 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Independent review (IAmJSD's agent, fresh context, given only the diff, the issue and the PR text): VERDICT: APPROVE Blocking:
Non-blocking:
Attacked:
Body-stale:
Reviewer: rM1. Bar while the maintainers are away (set by IAmJSD as acting owner): one approving independent review on the head, two for money, auth and security paths. |
|
Independent review (IAmJSD's agent, fresh context, given only the diff, the issue and the PR text): VERDICT: APPROVE Blocking:
Non-blocking:
Attacked:
Body-stale:
Reviewer: rM2. Bar while the maintainers are away (set by IAmJSD as acting owner): one approving independent review on the head, two for money, auth and security paths. |
|
Local verification at |
|
Merged by IAmJSD's agent at IAmJSD's request (IAmJSD is acting owner while the maintainers are away), under the bar IAmJSD set: 2 approving independent review(s) on |
Root cause
executeAndFinalizeruns three detached phases back to back, each with its own deadline:purchaseExecutionTimeout= 4m (internal/purchase/manager.go);terminalSaveTimeout= 30s;notifyRootFailure->sendFailureNotice), which detaches again withfailureNotifyTimeout= 30s (internal/purchase/failure_notify.go, added by fix(ops): alert on failed purchases and scheduled tasks; wire monitoring per environment #1094/fix(purchase): alert on failed fan-out roots and every terminal-failure writer #1245).That adds up to 300s, which is exactly
lambda_timeoutin every shipped config. Nothing is left for the request work before the detach or for the response, so Lambda could end the invocation in the middle of the failure email.TestLambdaTimeoutCoversPurchaseBudgetonly counted phases 1 and 2, so it missed this.Fix (owner decision D28, issue option 2)
purchaseExecutionTimeout: 4m -> 3m30s. Worst case is now 3m30s + 30s + 30s = 270s. With the 30slambdatimeout.Marginthat fits the 300s Lambda timeout.lambda_timeoutis unchanged and no deploy change is needed.TestLambdaTimeoutCoversPurchaseBudgetnow passespurchaseExecutionTimeout + terminalSaveTimeout + failureNotifyTimeouttolambdatimeout.AssertCovers. That helper reads every shipped Lambda timeout: the Terraform module and root variable defaults and validation floors, every committedlambda_timeouttfvars value and example,docs/DEPLOYMENT.md, and the CloudFormationTimeout. So raising any of the three phase budgets, or lowering any shipped timeout, fails the test.TestExecuteAndFinalize_SlowRunGetsFreshTerminalSaveBudgetwas 4m. It is now 3m30s, so the new value is pinned directly and not only through the constant.manager.go,failure_notify.go,internal/server/scheduled_tasks.go, the comment on thetimeoutvariable interraform/modules/compute/aws/lambda/variables.tf, and theerror_messageof both Lambda timeout validations (module andterraform/environments/aws/variables.tf). Only text changed. The>= 300floors, the defaults and the tfvars values are untouched.Fan-out note: per-account rows send their own failure alert (a fresh 30s detach) from inside the execution phase. The root row of a fan-out logs only the marker and sends no email. So the worst case is still one 30s alert after the execution deadline, then the save: 270s total. Accounts are skipped once the run context is done, and the per-account alerts that run concurrently overlap in time instead of adding up.
Closes #1434
Verification
All of this is unit, fixture and mock evidence. Nothing ran against a real AWS account and no deploy was made.
Environment:
AWS_CONFIG_FILE=/dev/null AWS_SHARED_CREDENTIALS_FILE=/dev/null AWS_EC2_METADATA_DISABLED=true, Go 1.26.9.Fail-before: the new test with
manager.gofromorigin/main(4m budget), restored viagit show origin/main:internal/purchase/manager.go:Pass-after (this branch):
Mutation probes on this branch, each reverted afterwards:
failureNotifyTimeout30s -> 31s: the test fails with 11 "shorter than" errors.terraform/environments/aws/github-prod.tfvarslambda_timeout300 -> 299: the test fails withgithub-prod.tfvars lambda_timeout: Lambda timeout 4m59s is shorter than the 4m30s detached budget plus 30s margin (want >= 5m0s).Other checks:
go build ./...,go vet ./...,go vet -tags integration ./...: OKgo test -count=1on./internal/purchase/,./internal/server/and./internal/mocks/: okgolangci-lint run --allow-parallel-runners ./internal/purchase/ ./internal/server/(v2.10.1): 0 issuesgocyclo -over 10 -ignore "_test\.go"on the changed non-test Go files: cleanterraform fmt -checkon both changedvariables.tf: clean.terraform validateonmodules/compute/aws/lambdaandenvironments/aws(in a temp copy,init -backend=false): valid.terraform test -filter=tests/timeout.tftest.hclin the Lambda module (mock provider, plan only): 5 passed.No integration test was added. The bug is a static budget mismatch with no DB or concurrency path involved.
Combined-tree verification. Tested on a local, never-pushed tree:
queue/platform@40dbbdaf= origin/main6e2033cdplus:Linux, Go 1.26.9,
AWS_CONFIG_FILE=/dev/null AWS_SHARED_CREDENTIALS_FILE=/dev/null AWS_EC2_METADATA_DISABLED=true; Docker Postgres via testcontainers.go build ./...,go vet ./...,go vet -tags integration ./...and the fullgo test -race -short -count=1 ./....--build-tags integration.gocyclo -over 10is silent on the changed non-test files.-tags integration -count=1, one package at a time):internal/api,internal/database/postgres/migrations,internal/purchaseandinternal/serverpass.internal/confighad one failure, which comes from the fix(marketplace): close RI Marketplace poller gaps (pending rows with a listing id, superseded listings, deployment coverage) #1494 branch (a mid-claim listing gets settled); that branch is being fixed and isn't opened yet.scripts/test-git-secrets-allowlist.shpasses.Out of scope
lambda_timeoutitself (issue option 1) was left at 300 on purpose, per the owner decision.internal/api/ri_exchange_detached.go) still uses 4m + 30s = 270s and sends no separate detached alert, so it also fits 300s. It is unchanged.perRecPurchaseTimeout).Labels
Maintainer: please mirror the issue's triage labels onto this PR:
priority/p3,severity/low,urgency/this-quarter,impact/few,effort/xs,type/bug.🤖 Generated with Claude Code