События на стороне сервера / EventSource / PostgreSQL Notify - только при транзакции в БД

Я пытаюсь сообщить клиенту (браузеру), когда в базе данных есть транзакция.
Я использую EventSource в JS для подключения к PHP, где я «слушаю» базу данных PostgreSQL.
Что происходит? EventSource прослушивает или считывает данные каждые 3-4 секунды, хотя я ничего об этом не устанавливал.
Я намерен получать уведомления только при наличии транзакции в БД и только тогда, когда БД стреляет «уведомить».

ПРОБЛЕМА: EventSource прослушивает каждые 3-4 секунды, как и опрос, и уведомляет меня несколько раз, хотя было одно уведомление от БД.
ПРОБЛЕМА: я подключение БД каждый раз, когда она работает через PHP, и этот SSE похож на опрос.

JavaScript

if(typeof(EventSource) !== "undefined") {
    var source = new EventSource("sse.php");
    source.onmessage = function(event) {
        console.log(event.data);
    };
} else {
    console.log("SSE NOT SUPPORTED");
}

PHP

header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

$conn = pg_pconnect("DB INFO HERE") or die('DB CONNECT ERROR');
pg_query($conn, 'LISTEN event_insert;');
$notify = pg_get_notify($conn);

if (!$notify) {
    echo "data: .\n\n";
} else {
    $msg = json_encode($notify);
    echo "data: {$msg}\n\n";
}

flush();

PostgreSQL

CREATE OR REPLACE FUNCTION notify_event_insert() RETURNS trigger AS $$
DECLARE
BEGIN
  NOTIFY event_insert;
  RETURN new;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_event_insert AFTER INSERT ON events
FOR EACH ROW EXECUTE PROCEDURE notify_event_insert();

JS-КОНСОЛЬ

Я получил '.' когда нет транзакции, и я получаю JSON, когда есть транзакция, и БД «уведомляет» меня.

Скриншот


person David YK Han    schedule 23.09.2020    source источник


Ответы (1)


Опрос — это то, что задокументировано:

В противном случае, если NOTIFY не ожидает, возвращается FALSE.

Возможно, вместо этого вы захотите использовать pgsqlGetNotify PDO.

person jjanes    schedule 23.09.2020
comment
Я не совсем понимаю. Итак, вы имеете в виду, что NOTIFY нужно слушать в бесконечном цикле, чтобы продолжать слушать? Я не хочу, чтобы это был опрос. Я не хочу помещать его в постоянный цикл while, как в последнем примере в этом ссылка в самом низу. - person David YK Han; 24.09.2020
comment
pg_get_notify выполнит опрос и немедленно вернет false, если ничего не ожидается. pgsqlGetNotify будет блокироваться до тех пор, пока не получит сообщение (или не истечет время ожидания, если вы используете время ожидания). Если вы хотите продолжить прослушивание после первого сообщения/не сообщения, вам нужно зациклиться. Какой еще вариант может быть? - person jjanes; 24.09.2020
comment
Хорошо. Итак, pg_get_notify опрашивает. Это хорошо знать. Я искал метод типа обработчика событий. Мне pgsqlgetnotify кажется тем, что я ищу. Могу ли я, не зацикливаясь, получать уведомления почти в режиме реального времени, когда есть новая транзакция (уведомление БД)? Я хочу получать уведомления всякий раз, когда БД уведомляет, но я не хочу опроса. - person David YK Han; 25.09.2020