Я хочу отобразить в приложении внешнего интерфейса (angular) все задачи, принадлежащие проекту и когда они были закрыты на графике. Я использую postgres в качестве БД с таблицей Todo
, которая имеет внешний ключ (fk_project_id) для таблицы Project
.
С помощью этой средней статьи я смог настроить postgres триггер уведомлений, который прослушивает мой бэкэнд js (см. Скрипт ниже). После каждого INSERT
или UPDATE
мой бэкэнд будет проверять, какой проект t todo изменился, и уведомлять об этом в канале socket.io для этого указанного c проекта.
Моя проблема теперь заключается в действии , что пользователь может удалить задачу из проекта. Текущий триггер выдаст удаленную задачу без fk_project_id
, и я не могу выполнить sh обновление канала проекта, из которого была удалена задача.
Единственное решение, которое я могу придумать, - это добавьте второй триггер для задач с BEFORE UPDATE
, который я считаю дорогим с единственной целью получить предыдущий fk_project_id
.
Есть ли другие подходы, которые я могу использовать?
import { Pool } from 'pg';
interface NotificationTriggerConfig {
trigger: string;
channel: string;
table: string;
connectionString: string;
}
const getNotificationTrigger = (config: NotificationTriggerConfig) => `
CREATE OR REPLACE FUNCTION ${config.trigger}()
RETURNS trigger AS
$BODY$
BEGIN
PERFORM pg_notify('${config.channel}', row_to_json(NEW)::text);
RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
DROP TRIGGER IF EXISTS ${config.trigger} on "public"."${config.table}";
CREATE TRIGGER ${config.trigger}
AFTER INSERT OR UPDATE
ON "${config.table}"
FOR EACH ROW
EXECUTE PROCEDURE ${config.trigger}();
`;
export function createNotificationTrigger<T = any>(
cb: (payload: T) => any,
config: NotificationTriggerConfig
) {
const { connectionString, channel } = config;
return new Promise(async (resolve, reject) => {
const pool = new Pool({ connectionString, max: 10 });
await pool.query(getNotificationTrigger(config));
pool.connect((err, client) => {
if (err) {
console.log(err);
return reject(err);
}
client.on('notification', (msg) => {
if (msg.channel === channel) {
cb(JSON.parse(msg.payload));
}
});
client.query(`LISTEN ${channel}`);
});
resolve(pool.end);
});
}