feat(email): route all email sends through Cloudflare Queue

Introduces a CF Queue binding (kk-email-queue) to decouple email
delivery from request handlers, preventing slow responses and
providing automatic retries. All send*Email calls now go through
the queue when the binding is available, with direct-send fallbacks
for local dev. Reminder fan-outs mark DB rows optimistically before
enqueueing to prevent re-enqueue on subsequent cron ticks.
This commit is contained in:
2026-03-11 17:13:35 +01:00
parent 7f431c0091
commit e5d2b13b21
12 changed files with 524 additions and 106 deletions

View File

@@ -1,3 +1,4 @@
import type { EmailMessage } from "@kk/api/email-queue";
import { QueryClientProvider } from "@tanstack/react-query";
import { createRouter as createTanStackRouter } from "@tanstack/react-router";
@@ -6,6 +7,18 @@ import Loader from "./components/loader";
import { routeTree } from "./routeTree.gen";
import { orpc, queryClient } from "./utils/orpc";
// Minimal CF Queue binding shape needed for type inference
type Queue = {
send(
message: EmailMessage,
options?: { contentType?: string },
): Promise<void>;
sendBatch(
messages: Array<{ body: EmailMessage }>,
options?: { contentType?: string },
): Promise<void>;
};
export const getRouter = () => {
const router = createTanStackRouter({
routeTree,
@@ -26,3 +39,9 @@ declare module "@tanstack/react-router" {
router: ReturnType<typeof getRouter>;
}
}
declare module "@tanstack/router-core" {
interface Register {
server: { requestContext: { emailQueue?: Queue } };
}
}