Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
11e5065
Add retry mechanism for failed requests
devkiran Dec 10, 2025
465d23d
Update queue-failed-request-for-retry.ts
devkiran Dec 10, 2025
40bd5df
Update queue-failed-request-for-retry.ts
devkiran Dec 10, 2025
2b1aaf6
Refactor error handling to consistently wrap errors in an object for …
devkiran Dec 10, 2025
39e6383
Merge branch 'main' into retry-endpoints
devkiran Dec 15, 2025
f68b1a6
Format
devkiran Dec 15, 2025
666a623
add handleCronErrorResponse
devkiran Dec 15, 2025
f229700
Format
devkiran Dec 15, 2025
c3cfd79
use handleCronErrorResponse for cron jobs
devkiran Dec 15, 2025
a26177b
Update route.ts
devkiran Dec 15, 2025
f328dbb
Update route.ts
devkiran Dec 15, 2025
468b9c6
Delete index.test.ts
devkiran Dec 15, 2025
28bd5b4
Update queue-failed-request-for-retry.ts
devkiran Dec 15, 2025
ccfaa43
Delete encrypt-token.ts
devkiran Dec 15, 2025
5cbd2a5
cleanup
devkiran Dec 15, 2025
6711ecb
Update workspace.ts
devkiran Dec 15, 2025
690b960
CodeRabbit Feedbacks
devkiran Dec 15, 2025
cfbc02f
Merge branch 'main' into retry-endpoints
devkiran Dec 23, 2025
741c88b
Merge branch 'main' into retry-endpoints
steven-tey Dec 26, 2025
c487abe
Merge branch 'main' into retry-endpoints
steven-tey Dec 29, 2025
32af6ff
Merge branch 'main' into retry-endpoints
steven-tey Dec 29, 2025
db84b48
add jitter to retries
steven-tey Dec 30, 2025
91b62b9
Merge branch 'main' into retry-endpoints
devkiran Jan 8, 2026
c0eeb32
use default export for zod
devkiran Jan 8, 2026
e96ea92
fix build
devkiran Jan 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions apps/web/app/(ee)/api/cron/aggregate-clicks/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { createId } from "@/lib/api/create-id";
import { handleAndReturnErrorResponse } from "@/lib/api/errors";
import { syncTotalCommissions } from "@/lib/api/partners/sync-total-commissions";
import { qstash } from "@/lib/cron";
import { verifyQstashSignature } from "@/lib/cron/verify-qstash";
Expand All @@ -14,7 +13,7 @@ import {
nFormatter,
} from "@dub/utils";
import * as z from "zod/v4";
import { logAndRespond } from "../utils";
import { handleCronErrorResponse, logAndRespond } from "../utils";
import { resolveClickRewardAmount } from "./resolve-click-reward-amount";

export const dynamic = "force-dynamic";
Expand Down Expand Up @@ -239,7 +238,7 @@ async function handler(req: Request) {

return logAndRespond(endMessage);
} catch (error) {
return handleAndReturnErrorResponse(error);
return handleCronErrorResponse({ error });
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { createId } from "@/lib/api/create-id";
import { handleAndReturnErrorResponse } from "@/lib/api/errors";
import { evaluateWorkflowCondition } from "@/lib/api/workflows/execute-workflows";
import { qstash } from "@/lib/cron";
import { verifyQstashSignature } from "@/lib/cron/verify-qstash";
Expand All @@ -10,7 +9,7 @@ import { Prisma } from "@dub/prisma/client";
import { APP_DOMAIN_WITH_NGROK, log } from "@dub/utils";
import { differenceInMinutes } from "date-fns";
import * as z from "zod/v4";
import { logAndRespond } from "../../utils";
import { handleCronErrorResponse, logAndRespond } from "../../utils";

export const dynamic = "force-dynamic";

Expand Down Expand Up @@ -209,6 +208,6 @@ export async function POST(req: Request) {
type: "errors",
});

return handleAndReturnErrorResponse(error);
return handleCronErrorResponse({ error });
}
}
5 changes: 2 additions & 3 deletions apps/web/app/(ee)/api/cron/bounties/notify-partners/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { createId } from "@/lib/api/create-id";
import { handleAndReturnErrorResponse } from "@/lib/api/errors";
import { qstash } from "@/lib/cron";
import { verifyQstashSignature } from "@/lib/cron/verify-qstash";
import { ACTIVE_ENROLLMENT_STATUSES } from "@/lib/zod/schemas/partners";
Expand All @@ -10,7 +9,7 @@ import { NotificationEmailType } from "@dub/prisma/client";
import { APP_DOMAIN_WITH_NGROK, log } from "@dub/utils";
import { differenceInMinutes } from "date-fns";
import * as z from "zod/v4";
import { logAndRespond } from "../../utils";
import { handleCronErrorResponse, logAndRespond } from "../../utils";

export const dynamic = "force-dynamic";

Expand Down Expand Up @@ -217,6 +216,6 @@ export async function POST(req: Request) {
type: "errors",
});

return handleAndReturnErrorResponse(error);
return handleCronErrorResponse({ error });
}
}
5 changes: 2 additions & 3 deletions apps/web/app/(ee)/api/cron/campaigns/broadcast/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { validateCampaignFromAddress } from "@/lib/api/campaigns/validate-campaign";
import { createId } from "@/lib/api/create-id";
import { handleAndReturnErrorResponse } from "@/lib/api/errors";
import { renderCampaignEmailHTML } from "@/lib/api/workflows/render-campaign-email-html";
import { qstash } from "@/lib/cron";
import { verifyQstashSignature } from "@/lib/cron/verify-qstash";
Expand All @@ -14,7 +13,7 @@ import { APP_DOMAIN_WITH_NGROK, chunk, log } from "@dub/utils";
import { differenceInMinutes } from "date-fns";
import { headers } from "next/headers";
import * as z from "zod/v4";
import { logAndRespond } from "../../utils";
import { handleCronErrorResponse, logAndRespond } from "../../utils";

export const dynamic = "force-dynamic";

Expand Down Expand Up @@ -331,6 +330,6 @@ export async function POST(req: Request) {
type: "errors",
});

return handleAndReturnErrorResponse(error);
return handleCronErrorResponse({ error });
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { handleAndReturnErrorResponse } from "@/lib/api/errors";
import { bulkDeletePartners } from "@/lib/api/partners/bulk-delete-partners";
import { verifyQstashSignature } from "@/lib/cron/verify-qstash";
import { prisma } from "@dub/prisma";
import { ACME_PROGRAM_ID, log } from "@dub/utils";
import { subHours } from "date-fns";
import { logAndRespond } from "../../utils";
import { handleCronErrorResponse, logAndRespond } from "../../utils";

export const dynamic = "force-dynamic";

Expand Down Expand Up @@ -81,6 +80,6 @@ export async function POST(req: Request) {
type: "errors",
});

return handleAndReturnErrorResponse(error);
return handleCronErrorResponse({ error });
}
}
4 changes: 2 additions & 2 deletions apps/web/app/(ee)/api/cron/cleanup/e2e-tests/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { markDomainAsDeleted } from "@/lib/api/domains/mark-domain-deleted";
import { handleAndReturnErrorResponse } from "@/lib/api/errors";
import { bulkDeleteLinks } from "@/lib/api/links/bulk-delete-links";
import { includeProgramEnrollment } from "@/lib/api/links/include-program-enrollment";
import { includeTags } from "@/lib/api/links/include-tags";
Expand All @@ -8,6 +7,7 @@ import { verifyQstashSignature } from "@/lib/cron/verify-qstash";
import { prisma } from "@dub/prisma";
import { log } from "@dub/utils";
import { NextResponse } from "next/server";
import { handleCronErrorResponse } from "../../utils";

export const dynamic = "force-dynamic";

Expand Down Expand Up @@ -165,6 +165,6 @@ export async function POST(req: Request) {
type: "errors",
});

return handleAndReturnErrorResponse(error);
return handleCronErrorResponse({ error });
}
}
4 changes: 2 additions & 2 deletions apps/web/app/(ee)/api/cron/cleanup/expired-tokens/route.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { handleAndReturnErrorResponse } from "@/lib/api/errors";
import { verifyQstashSignature } from "@/lib/cron/verify-qstash";
import { prisma } from "@dub/prisma";
import { log } from "@dub/utils";
import { NextResponse } from "next/server";
import { handleCronErrorResponse } from "../../utils";

export const dynamic = "force-dynamic";

Expand Down Expand Up @@ -64,6 +64,6 @@ export async function POST(req: Request) {
type: "errors",
});

return handleAndReturnErrorResponse(error);
return handleCronErrorResponse({ error });
}
}
4 changes: 2 additions & 2 deletions apps/web/app/(ee)/api/cron/cleanup/link-retention/route.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { handleAndReturnErrorResponse } from "@/lib/api/errors";
import { qstash } from "@/lib/cron";
import { verifyQstashSignature } from "@/lib/cron/verify-qstash";
import { recordLink } from "@/lib/tinybird";
Expand All @@ -7,6 +6,7 @@ import { Domain } from "@dub/prisma/client";
import { APP_DOMAIN_WITH_NGROK } from "@dub/utils";
import { NextResponse } from "next/server";
import * as z from "zod/v4";
import { handleCronErrorResponse } from "../../utils";

export const dynamic = "force-dynamic";

Expand Down Expand Up @@ -49,7 +49,7 @@ export async function POST(req: Request) {

return NextResponse.json("OK");
} catch (error) {
return handleAndReturnErrorResponse(error);
return handleCronErrorResponse({ error });
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { handleAndReturnErrorResponse } from "@/lib/api/errors";
import { verifyQstashSignature } from "@/lib/cron/verify-qstash";
import { prisma } from "@dub/prisma";
import { log } from "@dub/utils";
import { subDays } from "date-fns";
import { NextResponse } from "next/server";
import { handleCronErrorResponse } from "../../utils";

export const dynamic = "force-dynamic";

Expand Down Expand Up @@ -66,6 +66,6 @@ export async function POST(req: Request) {
type: "errors",
});

return handleAndReturnErrorResponse(error);
return handleCronErrorResponse({ error });
}
}
5 changes: 2 additions & 3 deletions apps/web/app/(ee)/api/cron/commissions/export/route.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { convertToCSV } from "@/lib/analytics/utils/convert-to-csv";
import { formatCommissionsForExport } from "@/lib/api/commissions/format-commissions-for-export";
import { createDownloadableExport } from "@/lib/api/create-downloadable-export";
import { handleAndReturnErrorResponse } from "@/lib/api/errors";
import { generateExportFilename } from "@/lib/api/utils/generate-export-filename";
import { generateRandomString } from "@/lib/api/utils/generate-random-string";
import { verifyQstashSignature } from "@/lib/cron/verify-qstash";
Expand All @@ -11,7 +10,7 @@ import ExportReady from "@dub/email/templates/export-ready";
import { prisma } from "@dub/prisma";
import { log } from "@dub/utils";
import * as z from "zod/v4";
import { logAndRespond } from "../../utils";
import { handleCronErrorResponse, logAndRespond } from "../../utils";
import { fetchCommissionsBatch } from "./fetch-commissions-batch";

const payloadSchema = commissionsExportQuerySchema.extend({
Expand Down Expand Up @@ -109,6 +108,6 @@ export async function POST(req: Request) {
type: "cron",
});

return handleAndReturnErrorResponse(error);
return handleCronErrorResponse({ error });
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { handleAndReturnErrorResponse } from "@/lib/api/errors";
import { verifyQstashSignature } from "@/lib/cron/verify-qstash";
import { disableStripeDiscountCode } from "@/lib/stripe/disable-stripe-discount-code";
import { prisma } from "@dub/prisma";
import { logAndRespond } from "../../../utils";
import { handleCronErrorResponse, logAndRespond } from "../../../utils";

export const dynamic = "force-dynamic";

Expand Down Expand Up @@ -57,6 +56,6 @@ export async function POST(
`Discount code ${discountCode.code} disabled from Stripe for ${workspace.stripeConnectId}.`,
);
} catch (error) {
return handleAndReturnErrorResponse(error);
return handleCronErrorResponse({ error });
}
}
4 changes: 2 additions & 2 deletions apps/web/app/(ee)/api/cron/disposable-emails/route.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { handleAndReturnErrorResponse } from "@/lib/api/errors";
import { verifyQstashSignature } from "@/lib/cron/verify-qstash";
import { redis } from "@/lib/upstash";
import { log } from "@dub/utils";
import { NextResponse } from "next/server";
import { handleCronErrorResponse } from "../utils";

export const dynamic = "force-dynamic";

Expand Down Expand Up @@ -39,6 +39,6 @@ export async function POST(req: Request) {
type: "cron",
});

return handleAndReturnErrorResponse(error);
return handleCronErrorResponse({ error });
}
}
4 changes: 2 additions & 2 deletions apps/web/app/(ee)/api/cron/domains/delete/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { queueDomainDeletion } from "@/lib/api/domains/queue-domain-update";
import { handleAndReturnErrorResponse } from "@/lib/api/errors";
import { linkCache } from "@/lib/api/links/cache";
import { includeProgramEnrollment } from "@/lib/api/links/include-program-enrollment";
import { includeTags } from "@/lib/api/links/include-tags";
Expand All @@ -10,6 +9,7 @@ import { recordLink } from "@/lib/tinybird/record-link";
import { prisma } from "@dub/prisma";
import { R2_URL } from "@dub/utils";
import * as z from "zod/v4";
import { handleCronErrorResponse } from "../../utils";

export const dynamic = "force-dynamic";

Expand Down Expand Up @@ -134,6 +134,6 @@ export async function POST(req: Request) {
`Deleted ${links.length} links, no more links remaining. Domain deleted.`,
);
} catch (error) {
return handleAndReturnErrorResponse(error);
return handleCronErrorResponse({ error });
}
}
4 changes: 2 additions & 2 deletions apps/web/app/(ee)/api/cron/domains/renewal-payments/route.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { createId } from "@/lib/api/create-id";
import { handleAndReturnErrorResponse } from "@/lib/api/errors";
import { verifyVercelSignature } from "@/lib/cron/verify-vercel";
import { createPaymentIntent } from "@/lib/stripe/create-payment-intent";
import { prisma } from "@dub/prisma";
import { Invoice, Project, RegisteredDomain } from "@dub/prisma/client";
import { log } from "@dub/utils";
import { addDays, endOfDay, startOfDay } from "date-fns";
import { NextResponse } from "next/server";
import { handleCronErrorResponse } from "../../utils";

/**
* Daily cron job to create payment intents for `.link` domain renewals.
Expand Down Expand Up @@ -155,6 +155,6 @@ export async function GET(req: Request) {
type: "errors",
});

return handleAndReturnErrorResponse(error);
return handleCronErrorResponse({ error });
}
}
4 changes: 2 additions & 2 deletions apps/web/app/(ee)/api/cron/domains/renewal-reminders/route.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { handleAndReturnErrorResponse } from "@/lib/api/errors";
import { verifyVercelSignature } from "@/lib/cron/verify-vercel";
import { sendBatchEmail } from "@dub/email";
import DomainRenewalReminder from "@dub/email/templates/domain-renewal-reminder";
Expand All @@ -12,6 +11,7 @@ import {
subDays,
} from "date-fns";
import { NextResponse } from "next/server";
import { handleCronErrorResponse } from "../../utils";

/**
* Daily cron job to send `.link` domain renewal reminders.
Expand Down Expand Up @@ -130,6 +130,6 @@ export async function GET(req: Request) {
type: "errors",
});

return handleAndReturnErrorResponse(error);
return handleCronErrorResponse({ error });
}
}
4 changes: 2 additions & 2 deletions apps/web/app/(ee)/api/cron/domains/transfer/route.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { handleAndReturnErrorResponse } from "@/lib/api/errors";
import { linkCache } from "@/lib/api/links/cache";
import { qstash } from "@/lib/cron";
import { verifyQstashSignature } from "@/lib/cron/verify-qstash";
Expand All @@ -7,6 +6,7 @@ import { prisma } from "@dub/prisma";
import { APP_DOMAIN_WITH_NGROK, log } from "@dub/utils";
import { NextResponse } from "next/server";
import * as z from "zod/v4";
import { handleCronErrorResponse } from "../../utils";
import { sendDomainTransferredEmail } from "./utils";

const schema = z.object({
Expand Down Expand Up @@ -124,6 +124,6 @@ export async function POST(req: Request) {
type: "cron",
});

return handleAndReturnErrorResponse(error);
return handleCronErrorResponse({ error });
}
}
5 changes: 2 additions & 3 deletions apps/web/app/(ee)/api/cron/domains/update/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {
linkDomainUpdateSchema,
queueDomainUpdate,
} from "@/lib/api/domains/queue-domain-update";
import { handleAndReturnErrorResponse } from "@/lib/api/errors";
import { linkCache } from "@/lib/api/links/cache";
import { includeProgramEnrollment } from "@/lib/api/links/include-program-enrollment";
import { includeTags } from "@/lib/api/links/include-tags";
Expand All @@ -11,7 +10,7 @@ import { recordLink } from "@/lib/tinybird";
import { prisma } from "@dub/prisma";
import { Link } from "@dub/prisma/client";
import { linkConstructorSimple } from "@dub/utils";
import { logAndRespond } from "../../utils";
import { handleCronErrorResponse, logAndRespond } from "../../utils";

export const dynamic = "force-dynamic";

Expand Down Expand Up @@ -113,7 +112,7 @@ export async function POST(req: Request) {
return logAndRespond("Error scheduling next batch.");
}
} catch (error) {
return handleAndReturnErrorResponse(error);
return handleCronErrorResponse({ error });
}
}

Expand Down
4 changes: 2 additions & 2 deletions apps/web/app/(ee)/api/cron/domains/verify/route.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { getConfigResponse } from "@/lib/api/domains/get-config-response";
import { getDomainResponse } from "@/lib/api/domains/get-domain-response";
import { verifyDomain } from "@/lib/api/domains/verify-domain";
import { handleAndReturnErrorResponse } from "@/lib/api/errors";
import { verifyVercelSignature } from "@/lib/cron/verify-vercel";
import { prisma } from "@dub/prisma";
import { log } from "@dub/utils";
import { NextResponse } from "next/server";
import { handleCronErrorResponse } from "../../utils";
import { handleDomainUpdates } from "./utils";

/**
Expand Down Expand Up @@ -112,6 +112,6 @@ export async function GET(req: Request) {
message: "Domains cron failed. Error: " + error.message,
type: "errors",
});
return handleAndReturnErrorResponse(error);
return handleCronErrorResponse({ error });
}
}
Loading