100 lines
2.2 KiB
TypeScript
100 lines
2.2 KiB
TypeScript
import { sql } from "drizzle-orm";
|
|
import { db } from "../db/db.controller.js";
|
|
import { createLogger } from "../logger/logger.controller.js";
|
|
|
|
const log = createLogger({
|
|
module: "db",
|
|
subModule: "notifications",
|
|
});
|
|
|
|
/**
|
|
* Creates/updates Postgres notification functions + triggers.
|
|
*
|
|
* Safe to run on every app startup.
|
|
* CREATE OR REPLACE updates the function.
|
|
* DROP TRIGGER IF EXISTS prevents duplicate triggers.
|
|
*/
|
|
export async function setupDbNotifications() {
|
|
log.info({}, "Setting up DB notifications");
|
|
|
|
await setupLogsNotifications();
|
|
await setupDockScansNotifications();
|
|
|
|
log.info({}, "DB notifications setup complete");
|
|
}
|
|
|
|
/**
|
|
* Logs notification setup.
|
|
*
|
|
* Flow:
|
|
* 1. app inserts into logs table
|
|
* 2. trigger runs after insert
|
|
* 3. Postgres sends NOTIFY logs_inserted with the new log id
|
|
* 4. Node listener receives id and fetches/emits full row
|
|
*/
|
|
async function setupLogsNotifications() {
|
|
await db.execute(sql`
|
|
CREATE OR REPLACE FUNCTION notify_logs_inserted()
|
|
RETURNS trigger AS $$
|
|
BEGIN
|
|
PERFORM pg_notify(
|
|
'logs_inserted',
|
|
json_build_object(
|
|
'table', TG_TABLE_NAME,
|
|
'action', TG_OP,
|
|
'id', NEW.id
|
|
)::text
|
|
);
|
|
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
`);
|
|
|
|
await db.execute(sql`
|
|
DROP TRIGGER IF EXISTS logs_inserted_notify_trigger ON logs;
|
|
`);
|
|
|
|
await db.execute(sql`
|
|
CREATE TRIGGER logs_inserted_notify_trigger
|
|
AFTER INSERT ON logs
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION notify_logs_inserted();
|
|
`);
|
|
|
|
log.info({}, "Logs DB notification trigger ready");
|
|
}
|
|
|
|
async function setupDockScansNotifications() {
|
|
await db.execute(sql`
|
|
CREATE OR REPLACE FUNCTION notify_dock_scan_inserted()
|
|
RETURNS trigger AS $$
|
|
BEGIN
|
|
PERFORM pg_notify(
|
|
'dock_scan_inserted',
|
|
json_build_object(
|
|
'table', TG_TABLE_NAME,
|
|
'action', TG_OP,
|
|
'id', NEW.id
|
|
)::text
|
|
);
|
|
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
`);
|
|
|
|
await db.execute(sql`
|
|
DROP TRIGGER IF EXISTS dock_scan_inserted_notify_trigger ON dock_door_scans;
|
|
`);
|
|
|
|
await db.execute(sql`
|
|
CREATE TRIGGER dock_scan_inserted_notify_trigger
|
|
AFTER INSERT ON dock_door_scans
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION notify_dock_scan_inserted();
|
|
`);
|
|
|
|
log.info({}, "Dock scan DB notification trigger ready");
|
|
}
|