Promote dev to main: inline AMA operations drain, sparser crons - #300
Merged
Conversation
The */5 AMA work cron kept the Neon endpoint awake around the clock: each run issues an unconditional hold-release UPDATE plus a claimDue query, resetting the 5-minute autosuspend timer every cycle (~183 CU-hrs/month of always-on compute). Mutating endpoints now kick a background drain of the durable operations queue via waitUntil in the same invocation that enqueued the work, so booking emails, Finalizing Booking recovery, refunds, and admin-triggered retries start immediately instead of waiting for the next sweep. The lease-based runner already tolerates concurrent drains, so the kick and the scheduled sweep cannot double-execute. With request-triggered work handled inline, the cron becomes a pure clock fallback (reminders, retry backoff, expired Slot Hold bookkeeping) and drops to */30, with media reconcile hourly and aligned so wakeups consolidate. Reminders and retries may now land up to 30 minutes later; everything guest-facing gets faster, and the database can suspend between wakeups.
Address review feedback on the inline operations drain: - The Stripe webhook handler now surfaces the processed outcome via an onOutcome callback, and the route kicks the drain only for booking_created. Duplicate, ignored, orphaned, booking-exists, and hold-release deliveries return 200 without enqueueing work, so they no longer start a runner pass. - A single runner pass caps at its batch size, so older due work could crowd out the operation the triggering mutation just enqueued. The kick now re-runs the drain while full batches come back, bounded by a 30-second inline budget; leftovers stay with the scheduled sweep.
A single slow first pass (ten due operations with provider calls) could exhaust the 30-second outer budget before the drain reached the operation the triggering mutation enqueued, deferring it to the scheduled sweep. Raise the mutating routes to the platform-default 300s maxDuration (the explicit 60 had actually lowered it) and extend the drain budget to 240s, so 240s of passes plus one worst-case 45s pass still finish inside the ceiling. Passes are claim-ordered by nextAttemptAt, so each one moves the queue strictly toward the newest operation.
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.
Release
Promotes #299 to production.
Neon compute fix: the
*/5AMA work cron kept the database endpoint awake 24/7 (~183 CU-hrs/month). Durable operations (booking emails, Finalizing Booking recovery, refunds, artifact updates) now drain inline viawaitUntilin the same invocation that enqueues them, so guest-facing work starts immediately. The cron drops to*/30(media reconcile to hourly) as a pure clock fallback for reminders, retry backoff, and expired Slot Hold bookkeeping — letting Neon autosuspend between wakeups (~85% compute reduction expected).Review hardening included: webhook kick gated on
booking_created, drain loops past full batches under a 240s budget, mutating routes at the platform-default 300s maxDuration.Note: the new cron schedules take effect with this production deployment.
Greptile Summary
The PR starts due AMA durable operations within the mutation invocation that enqueues them, while retaining less-frequent cron sweeps for time-based and recovery work.
waitUntil-backed, multi-batch operation draining with a 240-second start budget.Confidence Score: 5/5
The PR appears safe to merge, with inline processing covering mutation-triggered AMA work and existing cron paths retaining scheduled recovery duties.
Durable-operation leasing protects concurrent drains, all changed enqueueing mutation paths trigger the runner, and the reduced schedules do not establish a broken correctness contract.
Important Files Changed
waitUntildrain that repeatedly runs full operation batches while relying on existing lease-based concurrency controls.Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart LR M[AMA mutation] --> E[Enqueue durable operation] E --> K[kickAmaOperations] K --> W[waitUntil inline drain] W --> R[Runner: batches of 10] R --> P[Calendar / Meeting / Email / Stripe] C[30-minute AMA cron] --> R C --> H[Expired hold cleanup] C --> T[Reminders and retry backoff] MC[Hourly media cron] --> MR[Media reconciliation]Reviews (1): Last reviewed commit: "perf(ama): drain durable operations inli..." | Re-trigger Greptile
Context used (4)