feat(queue): add typed application queue lifecycle
Quality / quality (ubuntu-latest) (push) Failing after 10m55s
Quality / quality (windows-latest) (push) Canceled after 0s

This commit is contained in:
2026-08-23 09:22:05 +05:30
parent 9332522614
commit 9377a69d88
17 changed files with 667 additions and 13 deletions
+22
View File
@@ -63,6 +63,8 @@ export interface Router {
authz: ComponentRef[];
/** Service implementations (`app/services/<name>.ts`) mounted for inter-app calls. */
services: ComponentRef[];
/** Background queues (`app/queues/<name>.ts`) loaded and started with the server. */
queues?: ComponentRef[];
matchPage(pathname: string): RouteMatch | null;
matchApi(pathname: string): RouteMatch | null;
matchRealtime(pathname: string): RouteMatch | null;
@@ -329,6 +331,25 @@ export function buildRouter(appDir: string, opts: RouterOptions = {}): Router {
services.push({ name, file: f.file });
}
const queues: ComponentRef[] = [];
const queueFilesByName = new Map<string, string>();
for (const f of scanDir(join(appDir, "queues"), [".js"])) {
if (!/\.(ts|js)$/.test(f.file) || /[.]gen[.](ts|js)$/.test(f.file)) continue;
const name = f.rel.replace(/\.(ts|js)$/, "").replace(/\//g, ":");
if (!/^[A-Za-z][A-Za-z0-9_:-]*$/.test(name)) {
console.warn(`[wrnexus] skipping queue with unsafe name: ${name}`);
continue;
}
const existing = queueFilesByName.get(name);
if (existing) {
throw new Error(
`WRN-QUEUE-COLLISION: two queues are named "${name}": ${existing} and ${f.file}`,
);
}
queueFilesByName.set(name, f.file);
queues.push({ name, file: f.file });
}
return {
pages,
api,
@@ -340,6 +361,7 @@ export function buildRouter(appDir: string, opts: RouterOptions = {}): Router {
schemas,
authz,
services,
queues,
matchPage: (p) => matchRoute(pages, p),
matchApi: (p) => matchRoute(api, p),
matchRealtime: (p) => matchRoute(realtime, p),