Release: develop -> main#4360
Merged
Merged
Conversation
…ose instead of error (#4293) * fix(accounting): log designed-transient BankTxConsumer states at verbose instead of error Two designed-transient states in the ledger BankTxConsumer spammed the error logs on every scan cycle: - a fresh BUY_CRYPTO / BUY_CRYPTO_RETURN bank_tx scanned before the async pricing job has set amountInChf on the linked buy_crypto row — now thrown as LedgerGateBlockedException, logged verbose by the forward loop and the content-change scan (which already handles it since #4262) - a bank_tx whose type is still null (not yet classified) hitting the default switch branch — now logged verbose; a NON-null unhandled type stays at error (genuine enum gap, fail-loud) Retry and watermark semantics are unchanged: the gate-block still breaks the forward loop head-of-line (pricing does not bump bank_tx.updated, so that retry is the only booking path), and the null-type skip still advances the watermark (classification bumps updated, the content-change scan re-books). Extends the quiet-retry pattern established in #4262 for the sibling consumers. * fix(accounting): gate-block only provably transient unpriced states, keep fail-loud defaults Narrow the previous commit to the states that provably self-heal: - BUY_CRYPTO: gate-block only while the linked buy_crypto has no amlCheck result yet (doAmlCheck prices amlCheck==null rows). A linked row WITH an amlCheck result and no amountInChf (FAIL via chargebackFillUp or resetAmlCheck) is never re-priced — that stays a fail-loud Error. - BUY_CRYPTO_RETURN: gate-block only the unlinked link race (the chargebackFillUp cron links the return bank_tx). A LINKED chargeback with no amountInChf is permanently unpriced — fail-loud Error. - Revert the type-null default-branch downgrade: reconcileBooking no-ops on never-booked rows, so a skipped null-type row is never booked later — the gap must stay visible at error level for all unhandled types. The forward-loop catch keeps logging LedgerGateBlockedException at verbose; retry and watermark semantics are unchanged throughout. A two-run test pins the head-of-line-retry recovery the gate-block relies on. * fix(accounting): correct gate-block comments and use CheckStatus enum in spec - forward-loop catch comment now names both gate-block feeders (AML pricing pending, chargeback link pending) instead of only the unpriced linked row - drop the resetAmlCheck attribution from the fail-loud comments: it nulls amlCheck and amountInChf together, so it produces the gate-block state, never the fail-loud state - spec uses CheckStatus.FAIL instead of a string literal * fix(accounting): correct remaining gate-block comments - the exception doc now names both forward-path feeders precisely (BUY_CRYPTO linked but not yet AML-priced; BUY_CRYPTO_RETURN not yet linked to its chargeback) instead of 'linked row' - the type-null test comment no longer attributes reconcileBooking to the forward loop: the watermark passed the row and the content-change scan's reconcileBooking no-ops on never-booked rows * fix(accounting): tighten gate-block comment claims and wrap to 120 cols - 'is never re-priced' overgeneralized: a manual FAIL→PENDING re-trigger (allowed while the buy_crypto is not complete) re-prices via doAmlCheck's PENDING selector — the comments now say 'not re-priced by the cron' - wrap the forward-catch and exception doc comments to the 120-column convention * fix(accounting): align chargeback gate comment with the corrected re-pricing claim The RETURN-side guard comment still carried the categorical 'FAIL rows are never re-priced' phrase that the previous commit corrected on the BUY_CRYPTO side. It now names the actual freezing mechanism: the linking cron completes the row, freezing amlCheck — so a linked chargeback with no CHF is not re-priced by the cron. The mirrored spec comment is aligned the same way. * fix(accounting): narrow the gate-block to doAmlCheck-eligible rows, revert the RETURN-leg downgrade BUY_CRYPTO: amlCheck == null alone does not prove the pricing race - doAmlCheck only prices rows that also have amlReason null, input amount/asset set, no user chargeback date and isComplete false. An ineligible unpriced row would wedge the forward watermark at verbose. The gate now uses BuyCrypto.isAmlPricingPending, a mirror of the doAmlCheck selection, with reciprocal keep-in-sync comments. BUY_CRYPTO_RETURN: buyCryptoChargeback == null does not prove the fillUp link race - a bank_tx can be classified BUY_CRYPTO_RETURN without any chargeback ever linking, and chargebackFillUp only links FAIL/incomplete orders with an executed chargebackOutput. No cheap provable invariant exists on the consumer side, so the downgrade is reverted: the leg fails loud again for both sub-cases.
github-actions
Bot
requested review from
TaprootFreak and
davidleomay
as code owners
July 24, 2026 12:02
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.
Automatic Release PR
This PR was automatically created after changes were pushed to develop.
Commits: 1 new commit(s)
Checklist