You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(plans): a ramp step counts as complete when one of N accounts buys, and both silent-under-buy paths are log-only #1861
Split out of #1669 (fix in flight on fix/1669-ramp-step-idempotent), which deliberately kept its scope to "one ramp step must not be counted twice". Two problems remain, and they are the same problem seen from two sides: a plan can quietly buy less commitment than the customer intended, and nothing durable says so.
1. A ramp step counts as complete when ONE account's execution runs clean
CompletePlanStep advances the ramp when any execution for that step finishes successfully. A multi-account plan fans one ramp step out into one execution per cloud account, each of which succeeds or fails independently, so an operator who repairs and retries a single failed account moves the plan to "step N done" while the other accounts have bought nothing for step N.
This predates #1669 and is unchanged by it: the pre-#1669 blind CurrentStep++ had the same granularity, plus the double-count that #1669 removes. It is visible directly in that fix's own regression test (internal/purchase/ramp_step_progress_integration_test.go): a 3-account plan whose step-3 fan-out committed only account A reaches CurrentStep = 3 as soon as account B's retry succeeds, while account C is still failed.
The original issue asked for this decision to be settled explicitly:
a ramp step is only complete when every account's row for that step has succeeded, not when any one of them has. Worth settling that explicitly in this issue before implementing.
It was not settled, and #1669 does not settle it. Settling it is this issue.
Gate the advance on sibling completeness: keep the counter, but only advance when no per-account row for that step is outstanding. Cheaper, but needs care that a permanently-failed account cannot freeze the ramp forever, which is the failure mode option 1 avoids by construction.
Whichever is chosen, "the plan's target accounts at the time the step ran" has to be pinned down, since a plan's account set can change between steps.
2. Two reachable money-path decisions are recorded only in a log line
Both of these silently under-buy and neither leaves durable evidence. purchase.executeAndFinalize calls updatePlanProgress for side effect only and swallows any error into logging.Errorf, so once the Lambda log ages out there is nothing to find.
A refused advance.CompletePlanStep refuses to advance when the completing step is more than one beyond CurrentStep, because the steps in between never completed and jumping would overstate what the plan bought. Reachable whenever a step fails terminally and a later step then succeeds. The plan silently stops advancing, next_execution_date stops moving, and plan_health can only infer "behind schedule" from wall-clock drift, which it reports identically for a plan that is merely late.
Stamp the outcome on the execution row (an audit note alongside error) so a refused or no-op advance surfaces in History rather than only in CloudWatch.
Give plan_health a distinct stalled-ramp factor, keyed on the recorded refusal instead of letting behind_schedule proxy for it.
Why this is P1 rather than P2
The failure direction is the same silent under-buy that #1669 was filed for: commitment the customer intended to buy that never gets bought, with nothing erroring and the plan reporting itself further along than it is. Multi-account plans are the normal shape for the customers who ramp, and per-account retry became the canonical recovery flow in #1655, so item 1 is reachable on the routine path rather than an edge case.
Split out of #1669 (fix in flight on
fix/1669-ramp-step-idempotent), which deliberately kept its scope to "one ramp step must not be counted twice". Two problems remain, and they are the same problem seen from two sides: a plan can quietly buy less commitment than the customer intended, and nothing durable says so.1. A ramp step counts as complete when ONE account's execution runs clean
CompletePlanStepadvances the ramp when any execution for that step finishes successfully. A multi-account plan fans one ramp step out into one execution per cloud account, each of which succeeds or fails independently, so an operator who repairs and retries a single failed account moves the plan to "step N done" while the other accounts have bought nothing for step N.This predates #1669 and is unchanged by it: the pre-#1669 blind
CurrentStep++had the same granularity, plus the double-count that #1669 removes. It is visible directly in that fix's own regression test (internal/purchase/ramp_step_progress_integration_test.go): a 3-account plan whose step-3 fan-out committed only account A reachesCurrentStep = 3as soon as account B's retry succeeds, while account C is still failed.The original issue asked for this decision to be settled explicitly:
It was not settled, and #1669 does not settle it. Settling it is this issue.
Options, roughly in order of preference:
CurrentStepfrom the executions table as the highest step whose per-account rows are all terminal-and-successful, rather than storing an incrementally-mutated counter. This also removes the migration/backfill class of problem entirely, because there is no stored convention left to get wrong.Whichever is chosen, "the plan's target accounts at the time the step ran" has to be pinned down, since a plan's account set can change between steps.
2. Two reachable money-path decisions are recorded only in a log line
Both of these silently under-buy and neither leaves durable evidence.
purchase.executeAndFinalizecallsupdatePlanProgressfor side effect only and swallows any error intologging.Errorf, so once the Lambda log ages out there is nothing to find.CompletePlanSteprefuses to advance when the completing step is more than one beyondCurrentStep, because the steps in between never completed and jumping would overstate what the plan bought. Reachable whenever a step fails terminally and a later step then succeeds. The plan silently stops advancing,next_execution_datestops moving, andplan_healthcan only infer "behind schedule" from wall-clock drift, which it reports identically for a plan that is merely late.purchase_executionsrow whosestep_numberpredates fix(plans): retrying two failed accounts of one ramp step advances CurrentStep twice, so a later step silently never purchases #1669's convention correction, or that was written during the deploy overlap, completes a step the plan has already counted. The advance is a correct no-op, and equally invisible.Wanted:
error) so a refused or no-op advance surfaces in History rather than only in CloudWatch.plan_healtha distinct stalled-ramp factor, keyed on the recorded refusal instead of lettingbehind_scheduleproxy for it.Why this is P1 rather than P2
The failure direction is the same silent under-buy that #1669 was filed for: commitment the customer intended to buy that never gets bought, with nothing erroring and the plan reporting itself further along than it is. Multi-account plans are the normal shape for the customers who ramp, and per-account retry became the canonical recovery flow in #1655, so item 1 is reachable on the routine path rather than an edge case.
Related