feat: add nestjs replacement, remove nestjs (#285)
* feat: add nestjs replacement, remove nestjs * fix: format issues * fix: dependency issues * fix: dependency issues * fix: format issue * fix: wrong channel used for logging channel
This commit is contained in:
64
apps/tasks/src/lib/queue/client.ts
Normal file
64
apps/tasks/src/lib/queue/client.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { objectEntries, objectKeys } from "@homarr/common";
|
||||
import type { MaybePromise } from "@homarr/common/types";
|
||||
import { queueChannel } from "@homarr/redis";
|
||||
import type { z } from "@homarr/validation";
|
||||
|
||||
import type { createQueue } from "./creator";
|
||||
|
||||
interface Queue<TInput extends z.ZodType = z.ZodType> {
|
||||
name: string;
|
||||
callback: (input: z.infer<TInput>) => MaybePromise<void>;
|
||||
inputValidator: TInput;
|
||||
}
|
||||
|
||||
type Queues = Record<
|
||||
string,
|
||||
ReturnType<ReturnType<typeof createQueue>["withCallback"]>
|
||||
>;
|
||||
|
||||
export const createQueueClient = <TQueues extends Queues>(queues: TQueues) => {
|
||||
const queueRegistry = new Map<string, Queue>();
|
||||
for (const [name, queue] of objectEntries(queues)) {
|
||||
if (typeof name !== "string") continue;
|
||||
queueRegistry.set(name, {
|
||||
name,
|
||||
callback: queue._callback,
|
||||
inputValidator: queue._input,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
queueRegistry,
|
||||
client: objectKeys(queues).reduce(
|
||||
(acc, name) => {
|
||||
acc[name] = async (
|
||||
data: z.infer<TQueues[typeof name]["_input"]>,
|
||||
options,
|
||||
) => {
|
||||
if (typeof name !== "string") return;
|
||||
const queue = queueRegistry.get(name);
|
||||
if (!queue) return;
|
||||
|
||||
await queueChannel.add({
|
||||
name,
|
||||
data,
|
||||
executionDate:
|
||||
typeof options === "object" && options.executionDate
|
||||
? options.executionDate
|
||||
: new Date(),
|
||||
});
|
||||
};
|
||||
return acc;
|
||||
},
|
||||
{} as Record<
|
||||
keyof TQueues,
|
||||
(
|
||||
data: z.infer<TQueues[keyof TQueues]["_input"]>,
|
||||
props: {
|
||||
executionDate?: Date;
|
||||
} | void,
|
||||
) => Promise<void>
|
||||
>,
|
||||
),
|
||||
};
|
||||
};
|
||||
14
apps/tasks/src/lib/queue/creator.ts
Normal file
14
apps/tasks/src/lib/queue/creator.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import type { z } from "zod";
|
||||
|
||||
import type { MaybePromise } from "@homarr/common/types";
|
||||
|
||||
export const createQueue = <TInput extends z.ZodType>(input: TInput) => {
|
||||
return {
|
||||
withCallback: (callback: (data: z.infer<TInput>) => MaybePromise<void>) => {
|
||||
return {
|
||||
_input: input,
|
||||
_callback: callback,
|
||||
};
|
||||
},
|
||||
};
|
||||
};
|
||||
20
apps/tasks/src/lib/queue/worker.ts
Normal file
20
apps/tasks/src/lib/queue/worker.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { queueChannel } from "@homarr/redis";
|
||||
|
||||
import { queueRegistry } from "~/queues";
|
||||
|
||||
/**
|
||||
* This function reads all the queue executions that are due and processes them.
|
||||
* Those executions are stored in the redis queue channel.
|
||||
*/
|
||||
export const queueWorker = async () => {
|
||||
const now = new Date();
|
||||
const executions = await queueChannel.filter((item) => {
|
||||
return item.executionDate < now;
|
||||
});
|
||||
for (const execution of executions) {
|
||||
const queue = queueRegistry.get(execution.name);
|
||||
if (!queue) continue;
|
||||
await queue.callback(execution.data);
|
||||
await queueChannel.markAsDone(execution._id);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user