Cherry-pick #46659: Fix VPP API retry recursion causing server OOM - #46684
Conversation
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #46656 `server/mdm/apple/vpp.do` retried transient Apple errors by **calling itself recursively**, with the rate-limit branch nesting `retry.Do` inside `retry.Do`. This change replaces the recursion with a single retry loop (respecting the prior 1 initial attempt + 3 retries), closes each response before retrying, honors Apple's `Retry-After` capped at 30s so that a multi-minute value can't block a synchronous request, and threads `context` through the VPP calls so the backoff is cancellable. The retry timings are otherwise unchanged from before. Following @sgress454 suggestion, I considered routing this through the shared `retry.Do` helper (a single attempt wrapped in `retry.Do` + an error filter) but figured out that: - retry.Do` owns its own wait schedule and its error filter returns an outcome enum rather than a duration, so it can't honor Apple's per-response `Retry-After` value. - also, I'd have to change the `retry` package to receive an extra `ctx` param so that the backoff is context-aware (which IMHO is more blast radius than this incident fix should carry). # Checklist for submitter - [x] Changes file added for user-visible changes in `changes/`. - [x] Timeouts are implemented and retries are limited to avoid infinite loops ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually **What was verified.** The new automated test cannot run against `main` (the fix changes the VPP function signatures and adds the retry knobs), so to confirm the actual failure mode I checked out `main` and ran a small repro that drives the VPP client against an Apple endpoint that always returns the rate-limit error. On `main`, the call **never returns** — `do()` recurses without bound — and the repro times out: ``` --- FAIL: TestReproUnboundedRecursionOnMain (10.00s) zz_repro_main_test.go:30: AssociateAssets did NOT return within 10s — unbounded retry recursion in do() on main FAIL FAIL github.com/fleetdm/fleet/v4/server/mdm/apple/vpp 10.642s ``` On this branch the same scenario returns a bounded error promptly. That behavior is covered by the new `TestDoRetryIsBoundedAndNonRecursive` (bounded rate-limit retries, `Retry-After` honored-but-capped, and context cancellation), and the full `server/mdm/apple/vpp` package passes. **I did not perform an end-to-end QA against a live Apple endpoint**. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed a server out-of-memory crash that occurred when Apple VPP API repeatedly returned transient errors during VPP operations, including app installs, user registration, and license seat releases. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.
Tip: disable this comment in your organization's Code Review settings.
CI Feedback 🧐A test triggered by this PR failed. Here is an AI-generated analysis of the failure:
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## rc-patch-fleet-v4.86.1 #46684 +/- ##
=========================================================
Coverage ? 66.76%
=========================================================
Files ? 2749
Lines ? 219926
Branches ? 10771
=========================================================
Hits ? 146833
Misses ? 59799
Partials ? 13294
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Cherry-pick of #46659 into the RC branch.