feat: expire stale pending booking-intents - #736
Open
islarmeeyah-cyber wants to merge 1 commit into
Open
Conversation
Adds a scheduled worker that sweeps booking intents stuck in `pending` beyond a 30-minute TTL, expires them, releases the reserved slot inventory, and emits a durable `booking_intent_expired` outbox event. - src/scheduler/expireBookingIntents.ts: new background worker with safety-brake threshold, re-verification guard against double-cancels, and env-configurable TTL/batch/interval - PgBookingIntentRepository.findStalePendingIntents: claims stale rows with FOR UPDATE SKIP LOCKED so concurrent worker instances never process the same intent twice - metrics: booking_intents_expired_total counter - index.ts: registers the worker with transactional-outbox event emission Closes Chronopay-Org#588
|
@islarmeeyah-cyber Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
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.
Overview
This PR adds a scheduled background worker that finds booking intents stuck in
pending(awaiting payment/confirmation) for longer than the configured TTL (default 30 minutes), cancels them, releases the reserved slot inventory back to the marketplace, and emits a durablebooking_intent_expiredevent.Related Issue
Closes #588
Changes
⏰ Expire Pending Booking-Intents Worker
[ADD]
src/scheduler/expireBookingIntents.tsScans for stale
pendingintents (oldest first) every 60s by default.Claims rows with
FOR UPDATE SKIP LOCKEDso multiple worker instances never double-process an intent.Re-verifies each intent is still
pendingimmediately before expiring, preventing double-cancels (e.g. buyer confirmed/completed in the meantime).Trips a safety brake and skips the sweep when candidate count exceeds the threshold (default 10,000).
Marks the intent
expired, releases the slot inventory, and emits thebooking_intent_expiredevent.Configurable via env vars:
EXPIRE_BOOKING_INTENTS_TTL_MS,_BATCH_SIZE,_SAFETY_THRESHOLD,_INTERVAL_MS; disable withEXPIRE_BOOKING_INTENTS_DISABLED=true.[ADD]
src/scheduler/__tests__/expireBookingIntents.test.ts24 tests covering edge cases: two workers running (no double-cancel), expiry exactly at the 30-minute boundary, slot already completed, safety brake, event-emission failures, async repositories, env config parsing, and graceful shutdown.
[MODIFY] Repository layer
booking-intent-repository.ts— addedfindStalePendingIntentsto the interface + in-memory implementation.pg-booking-intent-repository.ts— PostgreSQL implementation usingFOR UPDATE SKIP LOCKEDfor concurrent-safety.[MODIFY]
src/metrics.tsAdded
booking_intents_expired_totalPrometheus counter + safety-brake counter.[MODIFY]
src/index.tsRegisters the worker with transactional-outbox event emission (
booking_intent_expired) and a shutdown hook.[MODIFY]
src/modules/booking-intents/__tests__/pg-booking-intent-repository.test.tsCoverage for the new
findStalePendingIntentsquery.Verification Results
FOR UPDATE SKIP LOCKEDcreatedAt === cutoff)releaseSlotsets slot back to bookablebooking_intent_expiredeventbooking_intents_expired_totalNotes
src/workers/expireBookingIntents.tsandsrc/scheduler/registry.ts; this repo keeps all workers undersrc/scheduler/and registers them insrc/index.ts, so the worker follows the existing codebase conventions (same pattern asholdAutoRefundWorker).cancelled_expiredis theexpiredstatus in thebooking_intent_statusenum (migration 004).