Skip to content

Commit

Permalink
Retry on Svix rate limits
Browse files Browse the repository at this point in the history
  • Loading branch information
N2D4 committed Dec 12, 2024
1 parent b0db0a5 commit 4944537
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 9 deletions.
29 changes: 21 additions & 8 deletions apps/backend/src/lib/webhooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { teamCreatedWebhookEvent, teamDeletedWebhookEvent, teamUpdatedWebhookEve
import { userCreatedWebhookEvent, userDeletedWebhookEvent, userUpdatedWebhookEvent } from "@stackframe/stack-shared/dist/interface/crud/users";
import { WebhookEvent } from "@stackframe/stack-shared/dist/interface/webhooks";
import { getEnvVariable } from "@stackframe/stack-shared/dist/utils/env";
import { StackAssertionError, captureError } from "@stackframe/stack-shared/dist/utils/errors";
import { Result } from "@stackframe/stack-shared/dist/utils/results";
import { Svix } from "svix";
import * as yup from "yup";

Expand All @@ -20,10 +22,11 @@ async function sendWebhooks(options: {
} catch (e: any) {
if (e.message.includes("409")) {
// This is a Svix bug; they are working on fixing it
// TODO next-release: remove this
console.warn("[no action required] Svix bug: 409 error when creating application. Remove this warning when Svix fixes this.");
// TODO next-release: remove this once it no longer appears on Sentry
captureError("svix-409-hack", "Svix bug: 409 error when creating application. Remove this warning once Svix fixes this.");
} else {
throw e;
}
console.warn("Error creating application in Svix", e);
}
await svix.message.create(options.projectId, {
eventType: options.type,
Expand All @@ -36,11 +39,21 @@ async function sendWebhooks(options: {

function createWebhookSender<T extends yup.Schema>(event: WebhookEvent<T>) {
return async (options: { projectId: string, data: yup.InferType<typeof event.schema> }) => {
await sendWebhooks({
type: event.type,
projectId: options.projectId,
data: options.data,
});
await Result.retry(async () => {
try {
return Result.ok(await sendWebhooks({
type: event.type,
projectId: options.projectId,
data: options.data,
}));
} catch (e) {
if (typeof e === "object" && e !== null && "code" in e && e.code === "429") {
// Rate limit. Let's retry later
return Result.error(e);
}
throw new StackAssertionError("Error sending Svix webhook!", { event: event.type, data: options.data, cause: e });
}
}, 5);
};
}

Expand Down
2 changes: 1 addition & 1 deletion packages/stack-shared/src/utils/results.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ RetryError.prototype.name = "RetryError";
async function retry<T>(
fn: (attempt: number) => Result<T> | Promise<Result<T>>,
retries: number,
{ exponentialDelayBase = 2000 },
{ exponentialDelayBase = 1000 } = {},
): Promise<Result<T, RetryError>> {
const errors: unknown[] = [];
for (let i = 0; i < retries; i++) {
Expand Down

0 comments on commit 4944537

Please sign in to comment.