Перейти к основному содержимому
Нормативная версия документации - английская

Эта страница переведена с английского языковой моделью. При любом расхождении верен английский оригинал.

Пробуждение

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

Цикл захвата подписки и то, что заканчивает его ожидание раньше интервала опросаЗахватстроки на воркераили пакетаЗаполнил ли захватсвой лимит?Ожиданиеинтервал опросаили до пробужденияПубликация этогоброкера в таблицуи группуСлушающеесоединение вернулось:будит всехУведомление в каналетаблицы,на PostgreSQLДругой процесс,триггер: pg_notify(channel, group)Интервал опроса действует при любых пробуждениях:одна секунда, если брокер или подписка не задают свой
Схема текстом
  1. Захват строки на воркера или пакета → Заполнил ли захват свой лимит?
  2. Заполнил ли захват свой лимит? → Захват строки на воркера или пакета: полон
  3. Заполнил ли захват свой лимит? → Ожидание интервал опроса или до пробуждения: меньше строк
  4. Ожидание интервал опроса или до пробуждения → Захват строки на воркера или пакета
  5. Публикация этого брокера в таблицу и группу → Ожидание интервал опроса или до пробуждения
  6. Слушающее соединение вернулось: будит всех → Ожидание интервал опроса или до пробуждения
  7. Уведомление в канале таблицы, на PostgreSQL → Ожидание интервал опроса или до пробуждения
  8. Другой процесс, триггер: pg_notify (channel, group) → Уведомление в канале таблицы, на PostgreSQL: при фиксации
  9. Интервал опроса действует при любых пробуждениях: одна секунда, если брокер или подписка не задают свой

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

Публикация через брокер будит подписки своей таблицы на том же брокере: так работают Repository, маршрут, ответ и сообщение, которое тест публикует через обвязку. В таблице с группами публикация будит только подписки своей группы. Подписка, занятая захватом, сохраняет пробуждение для следующего ожидания, и это ожидание заканчивается сразу. Пробуждение стоит публикации одну атомарную операцию на каждую разбуженную подписку, а подписке не стоит ничего на сообщение. Строка, которую сервис пишет сам, своим SQL или через Tx обработчика, никого не будит: она ждёт интервала опроса или уведомления.

LISTEN/NOTIFY​

На PostgreSQL listen_notify будит и подписки в других процессах. Брокер берёт одно соединение пула при подключении и держит его до завершения работы, слушая на нём. Каждая подписка начинает слушать канал своей таблицы до первого захвата. Канал называется именем таблицы, дополненным схемой, если она есть, как в app.jobs. Каждая публикация брокера выполняет SELECT pg_notify(channel, group) на соединении, которое записало строку, сразу после записи; уведомление с пустой полезной нагрузкой будит каждую подписку таблицы. Уведомление, вернувшее ошибку, попадает в журнал, а публикация всё равно проходит успешно: до строки доберётся опрос по интервалу.

PostgreSQL доставляет уведомление при фиксации его транзакции, поэтому разбуженная подписка видит строку. Уведомление, отправленное, пока слушающее соединение было потеряно, пропадает: брокер подключается снова и один раз будит каждую подписку. Имена каналов ограничены 63 байтами, поэтому подписка на таблицу с более длинным полным именем останавливается при старте. Переключатель стоит одно соединение на всё время жизни брокера и ещё один оператор на публикацию. Транзакция, которая отправляет уведомление, к тому же берёт при фиксации блокировку, глобальную для сервера, поэтому фиксации с уведомлениями выполняются одна за другой, и это ограничивает множество одновременных писателей. На другой базе данных listen_notify не компилируется.

Сервер описывает механизм на странице NOTIFY: доставка при фиксации, полезная нагрузка короче 8000 байт и предел в 63 байта для идентификаторов. Блокировку при фиксации разработчики PostgreSQL описывают в списке рассылки.