Repository navigation
fix: failed-build page states the payment outcome and only offers a Retry that will work - #574
Open
stevenfackley wants to merge 4 commits into
Open
stevenfackley wants to merge 4 commits into
stevenfackley wants to merge 4 commits into
Conversation
…ding it A paid row stranded in building, packing or uploading by a restart was failed, and since the refund rule landed, refunded. Every merge deploys prod, so a deploy during the compile stage cost the sale. The row still has the prompt and schema, so the reconciler now runs it again from the top, under the attempt budget and only while its payment is still completed. A late-stage row that went stale while this process was alive is still failed and refunded: the worker dropped it with an outcome the sweep cannot know.
…her Retry will work The failed-build page offered a Retry the server would refuse (after a refund, at the attempt limit), said nothing about a refund the customer had been given, and counted 'attempt N of 3' from a number that was usually 0. It now works from the payment behind the build, which is read with the owner's row: Retry is shown only when the web's attempt gate and the Engine's payment gate will both accept it, with the retries left; a paid build shows whether the payment is kept, a refund has started, or one is on its way. The page keeps polling a failed paid build for up to three minutes so a refund recorded a moment after the failure shows up. Retries are now counted: resetForRetry raises attempt_count in the same write and refuses the fourth. That makes the Engine's refund at the attempt limit reachable for a failure that keeps repeating. A test reads the Engine's retry rules and fails when they differ from the page's.
…e review gaps Review of #574 found: - A retry was counted even when no build started, so an Engine outage on the last retry ended in a refund instead of a build. The retry is now given back unless the Engine accepts the build. - Retries and the reconciler's restarts shared attempt_count, so every deploy that landed on a build spent one of the customer's retries, and the page then said they had used them. New column retry_count (migration 0004, additive) counts presses of Retry only; attempt_count stays the reconciler's restart budget. - The refund decision read the count once at the start of a run, and a failed read meant zero. It now reads the row at the failure, and refunds nothing if the row cannot be read. - The page promised a refund 'starts automatically' for failures where none was coming (old failures, a failed refund attempt). After 15 minutes it now says the refund has not gone out and to write to support. - After a refused retry the page kept saying the payment was in place. It now re-reads the row. - An unreadable paid row was failed as schema (Retry shown, never refunded). It is now failed as internal and refunded. - A build cut off by a deploy waited the 15-minute stale window before restarting. A boot pass restarts it at once. - The reconciler tests used a clock that never moved, so comparing against 'now' instead of process start would have passed.
… the count on its own Second review of #574: - A retry was given back after any non-acceptance, but on 503/429/unreachable the row stays pending and the reconciler builds it, so the customer got an uncounted build; a timeout after the Engine accepted did the same. Only 402 gives the retry back now. - A 400 (input refused) gave the retry back and returned success, so a Retry that can never work was offered forever. It now returns the error and the retry stays counted. - The refund decision read the whole row; a row whose JSON no longer parses read as 'unknown' and was never refunded. GetRetryCountAsync reads retry_count alone. - Stale comments about attempt_count and when the Engine reads the count.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What was wrong on the failed-build page
attempt_count, which was usually 0.What the page does now
It works from the payment behind the build (
payment_status, read with the owner's row) and from the customer's own retry count.How retries are counted
retry_count(migration 0004: one additive column with a default, safe while the old code runs; deploy-prod applies migrations before starting the new images). It counts presses of Retry only.attempt_countstays the reconciler's restart budget, so a deploy that restarts a build no longer spends one of the customer's retries.resetForRetryraisesretry_countin the same write and refuses the fourth.retry_counthas reached 3. The count is read at the failure, on its own (GetRetryCountAsync), so it does not depend on the row's JSON parsing. If the count can't be read, nothing is refunded on a guess.Engine changes
internaland refunded. Before it wasschema: Retry shown, a retry that could never work, never refunded.OffersRetryandRetryLimitand fails when they differ from the page's rules.Checked
Not covered
transactions.generation_idhas no index. The lookup runs on every status poll; the table is small today.security.ubuntu.com. Unrelated to this change; the prod deploy runs on our own runner.