Rebasely Beta: data may be purged

examples/storefront Public

TypeScript · 30 lines · 1.4 KiB · at c6a00ae

// Unpaid orders hold stock (checkout takes it), so they cannot wait forever. Every five minutes// the cron trigger cancels orders still pending_payment after PAYMENT_WINDOW_MS, cancelling the// PaymentIntent first so a late payment cannot land on a cancelled order.import type { OrderEvent } from "./events.ts";import { cancelOrder } from "./orders.ts";import type { Payments } from "./payments.ts";export const PAYMENT_WINDOW_MS = 30 * 60 * 1000;const BATCH = 50;export type ExpiryReport = { cancelled: string[]; left_to_webhook: string[] };export async function expireOrders(db: D1Database, events: Queue<OrderEvent>, payments: Payments, now: number): Promise<ExpiryReport> {  const { results } = await db    .prepare("SELECT id, payment_intent_id FROM orders WHERE status = 'pending_payment' AND created_at < ? ORDER BY created_at LIMIT ?")    .bind(now - PAYMENT_WINDOW_MS, BATCH)    .all<{ id: string; payment_intent_id: string | null }>();  const report: ExpiryReport = { cancelled: [], left_to_webhook: [] };  for (const o of results) {    // The intent succeeded or is processing: the payment won the race, and the webhook will mark    // the order paid. Leave it alone.    if (o.payment_intent_id && !(await payments.cancelIntent(o.payment_intent_id))) {      report.left_to_webhook.push(o.id);      continue;    }    if ((await cancelOrder(db, events, o.id, now)).changed) report.cancelled.push(o.id);  }  return report;}