PIPRES-796 Fix order status webhook leaving orders half-updated on database deadlock#1441
Open
TLabutis wants to merge 1 commit into
Open
PIPRES-796 Fix order status webhook leaving orders half-updated on database deadlock#1441TLabutis wants to merge 1 commit into
TLabutis wants to merge 1 commit into
Conversation
…tabase deadlock Wrap the order status transition in a database transaction and retry transient database errors (deadlock 1213, lock wait timeout 1205) so an interrupted transition rolls back cleanly instead of leaving the order with a paid current_state, no history entry and an invoice without lines. Detect and complete previously interrupted transitions on webhook retry: the current_state guard now checks the order history, relinks the orphan invoice (order lines, payments, invoice number and date) and applies the status instead of silently skipping. Send status emails after commit and fail the transition when the history entry cannot be added.
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.
Problem
When a MySQL deadlock or lock wait timeout interrupts the order status transition mid-way (e.g. the paid webhook colliding with a scheduled ERP sync), the order is left permanently half-updated:
current_stateis committed to paid but no history entry existscurrent_stateguard inOrderStatusServicetreats the half-applied state as already doneConfirmed on merchant production (8 affected orders, each matching a logged deadlock to the second) and reproduced deterministically on PS 8.2.3 by holding a row lock on the order's
order_detailrows while the paid webhook arrives. Related reports: #1025 (timeout variant), #387 (duplicate payments). Bank transfer is the most exposed flow (order exists before payment), but the code path is shared by all payment methods, including refund, chargeback and Klarna shipment transitions.Fix
changeIdOrderState+ history entry) inside a database transaction; roll back and retry up to 3 times on transient database errors (deadlock 1213, lock wait timeout 1205). A final failure rolls back cleanly so the next webhook retry finds an untouched order.current_stateguard now also checks the order history: a matchingcurrent_statewithout a history entry is an interrupted transition, which gets logged, repaired (relink invoice order lines, link payments to the invoice, set order invoice number and date) and completed instead of skipped.Validation
Tested against a reproduction harness on PS 8.2.3 with real Mollie test webhooks (bank transfer):
Release
Note for reviewers
Hooks fired by
changeIdOrderStatenow run inside the transaction: their database writes roll back together with the transition (consistent), but external side effects could fire once per retry attempt. Retries only happen on transient database errors, which previously produced a permanently broken order.