import { model } from "@medusajs/framework/utils" /** * Durable record of every verified webhook delivery. `event_id` and * `transmission_id` drive deduplication; `status` / `attempt_count` / * `next_retry_at` drive the async subscriber and the retry cron * (`pending` → `processing` → `processed` | `failed` | `dead_letter` | * `ignored`). */ const PayPalWebhookEvent = model .define("paypal_webhook_event", { id: model.id().primaryKey(), event_id: model.text().unique(), event_type: model.text(), event_version: model.text().nullable(), transmission_id: model.text().nullable(), transmission_time: model.dateTime().nullable(), status: model.text().default("pending"), attempt_count: model.number().default(0), next_retry_at: model.dateTime().nullable(), processed_at: model.dateTime().nullable(), last_error: model.text().nullable(), resource_id: model.text().nullable(), payload: model.json().default({}), }) .indexes([ // Declared on the model (with the migrations' exact names and predicates) // so a future `db:generate` diff doesn't try to drop or duplicate the // indexes the migrations created. // Dedup lookup on every incoming delivery. { name: "idx_paypal_webhook_event_transmission_id", on: ["transmission_id"], where: '"transmission_id" IS NOT NULL', }, // Retry sweep: failed events ordered by next_retry_at. { name: "idx_paypal_webhook_event_status_retry", on: ["status", "next_retry_at"], where: "status = 'failed'", }, { name: "idx_paypal_webhook_event_type", on: ["event_type"], }, ]) export default PayPalWebhookEvent