fix(transactions): prevent TTL reaper from deleting confirmed transactions (#94) - #97
Conversation
…tions (Deen-Bridge#94) - Scope TTL index to pending transactions using partialFilterExpression - Set conditional default for expiresAt so confirmed/terminal records omit expiry - Explicitly clear expiresAt on all terminal states (confirmed, failed, refunded, expired, disputed) - Add idempotent fixTtlTransactionExpiry migration to unset legacy expiresAt and update index - Document status -> expiresAt lifecycle invariants - Add comprehensive test suite in test/ttlTransactionExpiry.test.js
|
Important Review available on request
Reviews should be triggered manually for repositories with fewer than 10 stars. Select Trigger review above or comment ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Strict review blocker: this branch conflicts with the base branch. Please rebase and resolve conflicts before requesting merge. |
2 similar comments
|
Strict review blocker: this branch conflicts with the base branch. Please rebase and resolve conflicts before requesting merge. |
|
Strict review blocker: this branch conflicts with the base branch. Please rebase and resolve conflicts before requesting merge. |
|
@ghzhost this PR has merge conflicts with the |
|
Hi @zeemscript , my PR that addresses this issue has been merged, however this PR was also created addressing the issue, and apparently wasn't merged by you. I am not the author of the PR, hence I can't be able to work or resolve the conflicts. I would advise you close it withh the proper label for it since my pr already addressed it and it has been merged. Thank you. |
Summary
Fixes #94
This PR resolves a critical bug where confirmed transactions (and other terminal state transactions) were being deleted ~30 minutes after creation by MongoDB's background TTL thread.
Root Cause
Transaction.jsschema defined a blanket TTL index{ expiresAt: 1 }with{ expireAfterSeconds: 0 }matching all documents.Date.now() + 30mforexpiresAt.confirmed,failed,refunded,expired,disputed) did not unsetexpiresAt, leaving confirmed purchases and donations vulnerable to permanent automatic purging.Changes Made
transactionSchemato usepartialFilterExpression: { status: "pending" }so MongoDB's TTL reaper only matches pending records.expiresAtdefault function to return a 30-minute timestamp ONLY whenthis.status === "pending"(or unset), returningundefinedfor records created directly in terminal states.src/controllers/stellar/paymentController.js: ClearsexpiresAt = undefinedon purchase confirmation & validation/network failures, and unsets on cancellation.src/controllers/stellar/donationController.js: ClearsexpiresAt = undefinedon donation confirmation & failures.src/services/stellar/reconciliationService.js: ClearsexpiresAt = undefinedinpromoteTransaction.src/controllers/stellar/refundController.js: UnsetsexpiresAtduring refund confirmation and dispute escalation.src/jobs/handlers.js: ClearsexpiresAt = undefinedon background on-chain verification confirmation or failure.src/migrations/fixTtlTransactionExpiry.jsto$unsetexpiresAton existing non-pending records and rebuild the partial index.docs/transaction-lifecycle.mddocumenting the status-to-expiry invariants and architecture safeguards.test/ttlTransactionExpiry.test.jsvalidating schema defaults, non-pending creations, legacy data backfilling, and partial index construction (100% test suite passing: 30 test suites, 296 passed).Closes #94