infoalloggi-monorepo/apps/infoalloggi/src/server/controllers/event_queue.controller.ts

96 lines
2.2 KiB
TypeScript
Raw Normal View History

2025-08-04 17:45:44 +02:00
import type { Override } from "TypeHelpers.type";
2025-08-28 18:27:07 +02:00
import { TRPCError } from "@trpc/server";
import { add, set } from "date-fns";
import type { NewEventQueue } from "~/schemas/public/EventQueue";
2025-08-04 17:45:44 +02:00
import {
2025-08-28 18:27:07 +02:00
type MinimalSMSData,
SendMessage,
2025-08-04 17:45:44 +02:00
} from "~/server/controllers/skebby.controller";
2025-08-28 18:27:07 +02:00
import { db } from "~/server/db";
import { NewMail, type NewMailProps } from "~/server/services/mailer";
2025-08-04 17:45:44 +02:00
type Email_EventData = {
2025-08-28 18:27:07 +02:00
tipo: "email";
data: NewMailProps;
2025-08-04 17:45:44 +02:00
};
type SMS_EventData = {
2025-08-28 18:27:07 +02:00
tipo: "sms";
data: MinimalSMSData;
2025-08-04 17:45:44 +02:00
};
export const canSendNotification = () => {
2025-08-28 18:27:07 +02:00
const d = new Date();
const hour = d.getHours();
return hour >= 9 && hour <= 20;
2025-08-04 17:45:44 +02:00
};
export const nextTimeForNotification = () => {
2025-08-28 18:27:07 +02:00
const d = new Date();
const targetDay = d.getHours() < 9 ? d : add(d, { days: 1 });
const lock_expires = set(targetDay, {
hours: 9,
minutes: 0,
});
return lock_expires;
2025-08-04 17:45:44 +02:00
};
export type EventDataTypes = Email_EventData | SMS_EventData;
type NewEventQueueProps = Override<NewEventQueue, { data: EventDataTypes }>;
export const addEventToQueue = async (data: NewEventQueueProps) => {
2025-08-28 18:27:07 +02:00
try {
await db.insertInto("event_queue").values(data).execute();
} catch (e) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: `Error while adding event to queue, ${(e as Error).message}`,
});
}
2025-08-04 17:45:44 +02:00
};
const getEventsFromQueue = async () => {
2025-08-28 18:27:07 +02:00
try {
const events = await db
.selectFrom("event_queue")
.selectAll()
.where("status", "=", "pending")
.where("event_queue.lock_expires", "<=", new Date())
.execute();
return events;
} catch (e) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: `Error while getting events from queue, ${(e as Error).message}`,
});
}
2025-08-04 17:45:44 +02:00
};
export const processEvents = async () => {
2025-08-28 18:27:07 +02:00
const events = await getEventsFromQueue();
if (events.length === 0) {
return;
}
for (const e of events) {
const data = e.data as EventDataTypes;
2025-08-04 17:45:44 +02:00
2025-08-28 18:27:07 +02:00
switch (data.tipo) {
case "email":
await NewMail({
...data.data,
});
break;
2025-08-04 17:45:44 +02:00
2025-08-28 18:27:07 +02:00
case "sms":
await SendMessage(data.data);
break;
}
// Mark event as processed
await db
.deleteFrom("event_queue")
.where("event_id", "=", e.event_id)
.execute();
}
2025-08-04 17:45:44 +02:00
};