31.9. Асинхронное уведомление#

31.9. Асинхронное уведомление

31.9. Асинхронное уведомление #

Tantor BE предлагает асинхронное уведомление с помощью команд LISTEN и NOTIFY. Клиентская сессия регистрирует свой интерес к определенному каналу уведомлений с помощью команды LISTEN (и может прекратить прослушивание с помощью команды UNLISTEN). Все сессии, прослушивающие определенный канал, будут уведомлены асинхронно, когда команда NOTIFY с указанным именем канала будет выполнена любой сессией. Строка payload может быть передана для передачи дополнительных данных слушателям.

libpq приложения отправляют команды LISTEN, UNLISTEN и NOTIFY как обычные SQL команды. Поступление сообщений NOTIFY может быть обнаружено впоследствии вызовом PQnotifies.

Функция PQnotifies возвращает следующее уведомление из списка необработанных уведомлений, полученных от сервера. Если нет ожидающих уведомлений, функция возвращает нулевой указатель. После возврата уведомления из PQnotifies оно считается обработанным и будет удалено из списка уведомлений.

PGnotify *PQnotifies(PGconn *conn);

typedef struct pgNotify
{
    char *relname;              /* notification channel name */
    int  be_pid;                /* process ID of notifying server process */
    char *extra;                /* notification payload string */
} PGnotify;

После обработки объекта PGnotify, возвращаемого функцией PQnotifies, обязательно освободите его с помощью PQfreemem. Достаточно освободить указатель PGnotify; поля relname и extra не представляют отдельных выделений памяти. (Названия этих полей исторические; в частности, имена каналов не обязательно должны иметь отношение к именам отношений).

Пример 31.2 предоставляет пример программы, иллюстрирующей использование асинхронного уведомления.

PQnotifies на самом деле не считывает данные с сервера; он просто возвращает сообщения, ранее полученные другой функцией libpq. В древних версиях libpq единственным способом гарантировать своевременное получение сообщений NOTIFY было постоянно отправлять команды, даже пустые, а затем проверять PQnotifies после каждого PQexec. Хотя это все еще работает, это устарело как пустая трата вычислительной мощности.

Лучший способ проверить сообщения NOTIFY, когда у вас нет полезных команд для выполнения, - вызвать PQconsumeInput , а затем проверить PQnotifies. Вы можете использовать select(), чтобы ожидать поступления данных от сервера, тем самым не используя CPU до тех пор, пока не будет что-то делать. (См. PQsocket, чтобы получить номер файлового дескриптора для использования с select()). Обратите внимание, что это будет работать нормально, независимо от того, отправляете ли вы команды с помощью PQsendQuery/PQgetResult или просто используете PQexec. Однако, после каждого PQgetResult или PQexec, вы должны проверить PQnotifies, чтобы увидеть, поступили ли какие-либо уведомления во время обработки команды.