уведомления postgres из хранимых процедур / триггеров, не сразу полученные клиентом слушателя node.js - PullRequest
0 голосов
/ 23 апреля 2019

Мы используем хранимые процедуры postgres 11 для циклического обновления строк в пакетах. После обновления пакета таблица «Ход выполнения» обновляется с указанием процента выполнения и статуса, ТО затем отправляется уведомление (с использованием pg_notify). Клиент nodejs прослушивает уведомление и обрабатывает его.

Для тестирования мы добавили PERFORM pg_sleep(5) сразу после вызова pg_notify, чтобы мы могли видеть, как медленно увеличивается процент выполнения.

Проблема в том, что уведомления не сразу отправляются слушателям при вызове PERFORM pg_notify, а вместо этого ВСЕ уведомления отправляются ПОСЛЕ завершения хранимой процедуры.

Кто-нибудь сталкивался с этой проблемой и нашел какое-либо решение (кроме dblink)?

Мы попробовали следующее внутри хранимой процедуры: - перемещено pg_sleep в верхней части цикла - добавление коммита; после pg_notify - используйте notify channel, 'payload вместо pg_notify

Затем мы попытались использовать триггеры + pg_notify. Когда это не помогло, мы также попытались использовать execute format('notify channel, ''%s''', payload). Тот же результат.

Некоторые примеры кодов:

Node.js

const pg = require('pg');
let client = new pg.Client({user: '', database: '', host: '', password: '', port: 5432});
client.connect();
client.query('LISTEN progress_updates');
client.on('notification', function(data) {
   console.log('notification: ', data);
});

Backend:

-- table
drop table if exists operations;
create table progress ( id serial primary key, percent int default 0 );

-- stored procedure
CREATE OR REPLACE PROCEDURE my_stored_proc() language plpgsql
AS $$
DECLARE
progress_id int;
BEGIN
insert into progress (percent) values (0) returning id into progress_id;
commit;

update progress set percent= 10 where id = progress_id ;
commit;
perform pg_notify('progress_updates', '{"percent": 10}');
-- notify progress_updates, '{"percent": 10}'
perform pg_sleep(5);

update progress set percent= 30 where id = progress_id ;
commit;
perform pg_notify('progress_updates', '{"percent": 30}');
perform pg_sleep(5);

update progress set percent= 70 where id = progress_id ;
commit;
perform pg_notify('progress_updates', '{"percent": 70}');
perform pg_sleep(5);

update progress set percent= 100 where id = progress_id ;
commit;
perform pg_notify('progress_updates', '{"percent": 100}');
END;
$$;

-- trigger
create or replace function notify_progress_trigger() returns trigger
  language plpgsql
as
$$
DECLARE
  payload TEXT;
BEGIN
  raise notice 'TRIGGERED ON %', NOW();
  payload := '{"percent": ' || NEW.percent || '}';
  perform pg_notify('progress_updates', payload);
  -- execute format('notify progress_updates, ''%s''', payload);
  return NEW;
END;
$$;
alter function notify_progress_trigger() owner to postgres;

create trigger watched_progress_trigger
  after insert or update
  on operations
execute procedure notify_progress_trigger();

-- Call stored proc manually
call my_stored_proc();

Мы ожидали, что уведомления будут приниматься слушателем одно за другим после обновления каждого пакета во время выполнения хранимой процедуры, но вместо этого мы получаем все уведомления в быстрой последовательности после завершения хранимой процедуры.

...