33.9. ÐÑÐ¸Ð½Ñ Ñонное Ñведомление
Postgres Pro пÑÐµÐ´Ð»Ð°Ð³Ð°ÐµÑ Ð°ÑинÑ
Ñонное Ñведомление поÑÑедÑÑвом команд LISTEN и NOTIFY. ÐлиенÑÑкий ÑÐµÐ°Ð½Ñ ÑабоÑÑ ÑегиÑÑÑиÑÑÐµÑ ÑÐ²Ð¾Ñ Ð·Ð°Ð¸Ð½ÑеÑеÑованноÑÑÑ Ð² конкÑеÑном канале Ñведомлений Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ LISTEN (и Ð¼Ð¾Ð¶ÐµÑ Ð¾ÑÑановиÑÑ Ð¿ÑоÑлÑÑивание Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ UNLISTEN). ÐÑе ÑеанÑÑ, пÑоÑлÑÑиваÑÑие конкÑеÑнÑй канал, бÑдÑÑ ÑведомлÑÑÑÑÑ Ð² аÑинÑ
Ñонном Ñежиме, когда в ÑамкаÑ
лÑбого ÑеанÑа команда NOTIFY вÑполнÑеÑÑÑ Ñ Ð¿Ð°ÑамеÑÑом, ÑказÑваÑÑим Ð¸Ð¼Ñ ÑÑого канала. ÐÐ»Ñ Ð¿ÐµÑедаÑи дополниÑелÑнÑÑ
даннÑÑ
пÑоÑлÑÑиваÑÑим ÑеанÑам Ð¼Ð¾Ð¶ÐµÑ Ð¸ÑполÑзоваÑÑÑÑ ÑÑÑока «payload».
ÐÑиложениÑ, иÑполÑзÑÑÑие libpq, оÑпÑавлÑÑÑ ÑеÑвеÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ LISTEN, UNLISTEN и NOTIFY как обÑÑнÑе SQL-командÑ. ÐоÑÑÑпление ÑообÑений Ð¾Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ NOTIFY можно впоÑледÑÑвии оÑÑледиÑÑ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ ÑÑнкÑии PQnotifies.
ФÑнкÑÐ¸Ñ PQnotifies возвÑаÑÐ°ÐµÑ ÑледÑÑÑее Ñведомление из ÑпиÑка необÑабоÑаннÑÑ
ÑведомиÑелÑнÑÑ
ÑообÑений, полÑÑеннÑÑ
Ð¾Ñ ÑеÑвеÑа. Ðна возвÑаÑÐ°ÐµÑ Ð½Ñлевой ÑказаÑелÑ, еÑли Ð½ÐµÑ Ñведомлений, ожидаÑÑиÑ
обÑабоÑки. Ðак ÑолÑко Ñведомление возвÑаÑено из ÑÑнкÑии PQnotifies, оно ÑÑиÑаеÑÑÑ Ð¾Ð±ÑабоÑаннÑм и бÑÐ´ÐµÑ Ñдалено из ÑпиÑка Ñведомлений.
PGnotify *PQnotifies(PGconn *conn);
typedef struct pgNotify
{
char *relname; /* Ð¸Ð¼Ñ ÐºÐ°Ð½Ð°Ð»Ð° Ñведомлений */
int be_pid; /* ID ÑеÑвеÑного пÑоÑеÑÑа, поÑÑлаÑÑего Ñведомление */
char *extra; /* ÑÑÑока ÑообÑÐµÐ½Ð¸Ñ Ð² Ñведомлении */
} PGnotify;
ÐоÑле обÑабоÑки обÑекÑа PGnotify, возвÑаÑÑнного ÑÑнкÑией PQnotifies, обÑзаÑелÑно оÑвободиÑе памÑÑÑ, занимаемÑÑ Ð¸Ð¼, Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ ÑÑнкÑии PQfreemem. ÐоÑÑаÑоÑно оÑвободиÑÑ ÑказаÑÐµÐ»Ñ Ð½Ð° PGnotify; Ð¿Ð¾Ð»Ñ relname и extra не пÑедÑÑавлÑÑÑ Ð¾ÑделÑнÑÑ
облаÑÑей памÑÑи. (Ðмена ÑÑиÑ
полей ÑвлÑÑÑÑÑ ÑаковÑми по иÑÑоÑиÑеÑким пÑиÑинам; в ÑаÑÑноÑÑи, имена каналов не обÑÐ·Ð°Ð½Ñ Ð¸Ð¼ÐµÑÑ Ð½Ð¸Ñего обÑего Ñ Ð¸Ð¼ÐµÐ½Ð°Ð¼Ð¸ ÑелÑÑионнÑÑ
оÑноÑений.)
ÐÑимеÑ 33.2 пÑедÑÑавлÑÐµÑ Ð¿ÑÐ¸Ð¼ÐµÑ Ð¿ÑогÑаммÑ, иллÑÑÑÑиÑÑÑÑей иÑполÑзование аÑÐ¸Ð½Ñ Ñонного ÑведомлениÑ.
ФÑнкÑÐ¸Ñ PQnotifies в дейÑÑвиÑелÑноÑÑи не ÑиÑÐ°ÐµÑ Ð´Ð°Ð½Ð½Ñе Ñ ÑеÑвеÑа; она пÑоÑÑо возвÑаÑÐ°ÐµÑ ÑообÑениÑ, пÑедваÑиÑелÑно ÑобÑаннÑе дÑÑгой ÑÑнкÑией библиоÑеки libpq. РоÑÐµÐ½Ñ ÑÑаÑÑÑ
вÑпÑÑкаÑ
libpq обеÑпеÑиÑÑ ÑвоевÑеменное полÑÑÐµÐ½Ð¸Ñ ÑообÑений Ð¾Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ NOTIFY можно бÑло ÑолÑко одним ÑпоÑобом â поÑÑоÑнно оÑпÑавлÑÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ, пÑÑÑÑ Ð´Ð°Ð¶Ðµ пÑÑÑÑе, а заÑем пÑовеÑÑÑÑ PQnotifies поÑле каждого вÑзова PQexec. ХоÑÑ ÑÑÐ¾Ñ Ð¼ÐµÑод вÑÑ ÐµÑÑ ÑабоÑаеÑ, он ÑÑиÑаеÑÑÑ ÑÑÑаÑевÑим Ð²Ð²Ð¸Ð´Ñ Ð½ÐµÑÑÑекÑивного иÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿ÑоÑеÑÑоÑа.
Ðолее ÑдаÑнÑм ÑпоÑобом пÑовеÑки налиÑÐ¸Ñ ÑообÑений Ð¾Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ NOTIFY, когда Ñ Ð²Ð°Ñ Ð½ÐµÑ Ð¿Ð¾Ð»ÐµÐ·Ð½ÑÑ
команд Ð´Ð»Ñ Ð²ÑполнениÑ, ÑвлÑеÑÑÑ Ð²Ñзов ÑÑнкÑии PQconsumeInput Ñ Ð¿Ð¾ÑледÑÑÑей пÑовеÑкой PQnotifies. ÐÑ Ð¼Ð¾Ð¶ÐµÑе иÑполÑзоваÑÑ select(), ÑÑÐ¾Ð±Ñ Ð¿Ð¾Ð´Ð¾Ð¶Ð´Ð°ÑÑ Ð¿ÑибÑÑÐ¸Ñ Ð´Ð°Ð½Ð½ÑÑ
Ñ ÑеÑвеÑа, не Ð·Ð°Ð½Ð¸Ð¼Ð°Ñ Ñем ÑамÑм ÑеÑÑÑÑÑ CPU в оÑÑÑÑÑÑвие Ð·Ð°Ð´Ð°Ñ Ð´Ð»Ñ Ð²ÑполнениÑ. (ÐолÑÑиÑÑ Ð½Ð¾Ð¼ÐµÑ Ð´ÐµÑкÑипÑоÑа Ð´Ð»Ñ Ð¸ÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ select() можно Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ ÑÑнкÑии PQsocket.) ÐамеÑÑÑе, ÑÑо ÑÑо бÑÐ´ÐµÑ ÑабоÑаÑÑ Ð½ÐµÐ·Ð°Ð²Ð¸Ñимо Ð¾Ñ Ñого, оÑпÑавлÑеÑе ли Ð²Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ, иÑполÑзÑÑ PQsendQuery/PQgetResult, или пÑоÑÑо вÑзÑваеÑе PQexec. Ðднако важно не забÑваÑÑ Ð¿ÑовеÑÑÑÑ PQnotifies поÑле каждого вÑзова PQgetResult или PQexec, ÑÑÐ¾Ð±Ñ ÑвидеÑÑ, не поÑÑÑпили ли какие-либо ÑÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð² пÑоÑеÑÑе обÑабоÑки командÑ.