Я пытаюсь создать клиент -> система уведомлений/обновления базы данных. Клиент написан на Java/Hibernate. Чтобы уведомить клиента, я использую триггер:
CREATE OR REPLACE FUNCTION notifyUsers() RETURNS TRIGGER AS $$
DECLARE
data integer;
notification json;
BEGIN
IF (TG_OP = 'DELETE') THEN
data = OLD.id;
ELSE
data = NEW.id;
END IF;
-- Contruct the notification
notification = json_build_object(
'table',TG_TABLE_NAME,
'action', TG_OP,
'id', data);
-- Execute pg_notify(channel, notification)
PERFORM pg_notify('events',notification::text);
-- Result is ignored since this is an AFTER trigger
RETURN NULL;
END;
$$ LANGUAGE 'plpgsql';
CREATE TRIGGER notifyUsersAccountData AFTER INSERT OR UPDATE OR DELETE ON document FOR EACH ROW EXECUTE PROCEDURE notifyUsers();
но когда уведомление получено клиентом, я не могу определить, кто его запускает. Могу ли я отправить какой-либо дополнительный параметр, который будет определять, кто его запускает (session_id? В моем приложении есть настраиваемые пользователи, но я хотел бы избежать отправки User.id, поскольку вход в систему для одного и того же пользователя на 2 ПК нарушит мою систему уведомлений / обновлений)
После получения уведомления клиент обновляет значение, «идентификатор сеанса» необходим, чтобы определить, внес ли изменение «ЭТОТ клиент» (конечно, в этом случае клиент не должен обновляться) или кто-то другой (в этом случае обновление должно применяться)
РЕДАКТИРОВАТЬ - - -
Я хотел бы обновить эту тему, так как она не решена. Решение с вызовом pg_backend_pid иногда ломается, в результате чего «PID вызывающей стороны, выполняющей SQL-запрос», не совпадает с PGNotification.getPid. Код:
public int getSessionPid() {
int lResult = -1;
try
{
connect();
Session session = _sessionFactory.getCurrentSession();
Transaction lTransaction = session.beginTransaction();
SQLQuery lQuery = session.createSQLQuery("SELECT pg_backend_pid()");
List lResultQuery = lQuery.list();
lResult = Integer.parseInt(lResultQuery.get(0).toString());
lTransaction.commit();
}catch(org.hibernate.SessionException e)
{
e.printStackTrace();
}
return lResult;
}
и код, где появляется сравнение:
int lPid = Facade.databaseConnector.warehouse.getSessionPid();
for(int i = 0; i < notifications.length; ++i)
{
if(lPid == notifications[i].getPID())
...
Кроме того, я вижу, что в таблице, где видны текущие бэкэнд-соединения select * from pg_stat_activity, есть 3 соединения на один экземпляр моей программы.
SELECT 1- просто для обновления с уведомлениями, т.к. без "прикосновения" к базе данных уведомления не сработают- одно соединение связано со спящим режимом
- одно соединение связано с SQL-запросами в базе данных (например, вставка/обновление/удаление строк и т. д.)
Все внутренние соединения имеют разные порты и PID в файле pg_stat_activity.
Любые идеи?