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.
48 lines
1.3 KiB
TypeScript
48 lines
1.3 KiB
TypeScript
import type { EmailMessage } from "@kk/api/email-queue";
|
|
import { QueryClientProvider } from "@tanstack/react-query";
|
|
import { createRouter as createTanStackRouter } from "@tanstack/react-router";
|
|
|
|
import "./index.css";
|
|
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,
|
|
scrollRestoration: true,
|
|
defaultPreloadStaleTime: 0,
|
|
context: { orpc, queryClient },
|
|
defaultPendingComponent: () => <Loader />,
|
|
defaultNotFoundComponent: () => <div>Not Found</div>,
|
|
Wrap: ({ children }) => (
|
|
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
|
),
|
|
});
|
|
return router;
|
|
};
|
|
|
|
declare module "@tanstack/react-router" {
|
|
interface Register {
|
|
router: ReturnType<typeof getRouter>;
|
|
}
|
|
}
|
|
|
|
declare module "@tanstack/router-core" {
|
|
interface Register {
|
|
server: { requestContext: { emailQueue?: Queue } };
|
|
}
|
|
}
|