`shutdown()` set `accepting = false` and `start()` refused for ever after, so a queue was single-use. Any process that boots more than one app broke: a test suite closing one harness and opening the next, a hot reload, a multi-tenant host. The failure landed far from its cause -- the SECOND app to boot threw WRN-QUEUE-CLOSED out of the dev server because an unrelated one had shut down earlier in the same process. That is what turned six example-app security tests red only when run alongside the rest of the suite. Starting is an explicit intent to run, so it reopens the queue. `add()` keeps its guard, so work offered to a queue that is shutting down is still refused. Also migrates the example app's welcome-email queue to `defineQueue`, which the new loader requires. It still used `defineJob`, so the loader refused it and took the whole example app down -- 14 failures from one unmigrated file. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
29 lines
881 B
TypeScript
29 lines
881 B
TypeScript
import { defineQueue } from "@wrnexus/queue";
|
|
|
|
export interface WelcomeEmailPayload {
|
|
userId: number;
|
|
email: string;
|
|
}
|
|
|
|
/*
|
|
* A file under app/queues must default-export defineQueue(...) -- the loader
|
|
* refuses anything else rather than registering a queue that would never run.
|
|
* This example used the older defineJob() shape and so failed to load, which
|
|
* took the whole example app down with it.
|
|
*/
|
|
export default defineQueue({
|
|
name: "welcome-email",
|
|
jobs: {
|
|
send: {
|
|
validate: (data: unknown): data is WelcomeEmailPayload =>
|
|
typeof data === "object" &&
|
|
data !== null &&
|
|
Number.isInteger((data as { userId?: unknown }).userId) &&
|
|
typeof (data as { email?: unknown }).email === "string",
|
|
run: async ({ email }: WelcomeEmailPayload) => {
|
|
console.log(`Welcome email queued for ${email}`);
|
|
},
|
|
},
|
|
},
|
|
});
|