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:
Meier Lukas
2024-04-04 18:31:40 +02:00
committed by GitHub
parent c82915c6dc
commit 1936596c04
38 changed files with 599 additions and 2197 deletions

View 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>
>,
),
};
};

View 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,
};
},
};
};

View 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);
}
};