Многие современные СУБД представляют возможности для обмена сообщениями между процессами. Чаще всего это уведомления о каких-то событиях в базе данных. Например, об изменении данных или об окончании выполнения процедуры. Принцип реализации этого механизма у всех СУБД одинаковый: один процесс (приложение) подписывается на событие от базы данных и ожидает его, а второй процесс отправляет уведомление об этом событии. В Oracle это позволяют делать процедуры пакетов DBMS_ALERT и DBMS_PIPE, в PostgreSQL команды NOTIFY и LISTEN, в InterBase/Firebird команды POST_EVENT и EVENT INIT/WAIT...
Рассмотрим отправку сообщений из базы данных PostgreSQL и их получение в программе. Как я писал выше, PostgreSQL для обмена сообщениями использует две команды: NOTIFY и LISTEN. Команда NOTIFY отправляет текстовое сообщение с указанием имени канала всем клиентским процессам (приложениям), которые до этого выполнили в текущей базе данных команду LISTEN для этого канала. Создадим тестовую таблицу:
У объекта UniAlerter обязательно необходимо заполнить свойство Events. В этом свойстве хранится перечень событий, на которые подписывается объект (наименования событий разделяются символом "точка с запятой"). Присвоим Events наименование нашего канала "test_notify". Теперь добавим обработчик OnEvent, который срабатывает, когда вызывается какое-либо из зарегистрированных событий:
Заставить объект UniAlerter принимать сообщения можно двумя способами. Первый - это установить свойство AutoRegister=TRUE. Тогда подписка на события осуществится автоматически при открытии подключения к базе данных. Второй способ для тех, кто привык контролировать все сам - воспользоваться методами Start и Stop:
Сообщения "INSERT" появляются только, если объект UniAlerter находится в состоянии Active=TRUE. Необходимо учитывать, что подобный механизм обмена сообщениями связан с транзакциями. Это означает, что ожидающий процесс не получит извещение о событии, пока транзакция, в рамках которой была инициировано событие, не завершится.
Кроме получения сообщений класс TUniAlerter умеет их и отправлять. Это делается с помощью метода SendEvent(const EventName: string; const Message: string):
Таким образом в наших руках есть инструментарий позволяющий легко организовать обмен сообщениями между различными процессами, подключенными к одной базе данных.
Рассмотрим отправку сообщений из базы данных PostgreSQL и их получение в программе. Как я писал выше, PostgreSQL для обмена сообщениями использует две команды: NOTIFY и LISTEN. Команда NOTIFY отправляет текстовое сообщение с указанием имени канала всем клиентским процессам (приложениям), которые до этого выполнили в текущей базе данных команду LISTEN для этого канала. Создадим тестовую таблицу:
и правило (можно триггер), которое при вставке строки в созданную нами таблицу будет посылать в канал "test_notify" сообщение "INSERT":CREATE TABLE public.test ( id SERIAL NOT NULL, name VARCHAR(100) NOT NULL, CONSTRAINT PK_Test PRIMARY KEY(id) );
Для обработки событий, публикуемых сервером базы данных в программе, воспользуемся компонентой TUniAlerter из библиотеки Universal Data Access Components (UniDAC). На форму помещаем компоненты для подключения к базе данных (TUniConnection и TPostgreSQLUniProvider) и TUniAlerter:CREATE OR REPLACE RULE rule_test_notify AS ON INSERT TO public.test DO NOTIFY test_notify, 'INSERT';
У объекта UniAlerter обязательно необходимо заполнить свойство Events. В этом свойстве хранится перечень событий, на которые подписывается объект (наименования событий разделяются символом "точка с запятой"). Присвоим Events наименование нашего канала "test_notify". Теперь добавим обработчик OnEvent, который срабатывает, когда вызывается какое-либо из зарегистрированных событий:
В событии OnEvent нас интересуют два параметра: EventName - наименование события и Message - текст сообщения.procedure TForm1.UniAlerterEvent(Sender: TDAAlerter; const EventName, Message: string); begin mLog.Lines.Add(DateTimeToStr(Now) + ': ' + Message); end;
Заставить объект UniAlerter принимать сообщения можно двумя способами. Первый - это установить свойство AutoRegister=TRUE. Тогда подписка на события осуществится автоматически при открытии подключения к базе данных. Второй способ для тех, кто привык контролировать все сам - воспользоваться методами Start и Stop:
Теперь запустим полученную программу и попробуем вставлять данные в тестовую таблицу запуская и останавливая UniAlerter нажатием на кнопку "Start/Stop":procedure TForm1.btnStartStopClick(Sender: TObject); begin if UniAlerter.Active then begin UniAlerter.Stop; mLog.Lines.Add(DateTimeToStr(Now) + ': Stop'); end else begin UniAlerter.Start; mLog.Lines.Add(DateTimeToStr(Now) + ': Start'); end; end;
Сообщения "INSERT" появляются только, если объект UniAlerter находится в состоянии Active=TRUE. Необходимо учитывать, что подобный механизм обмена сообщениями связан с транзакциями. Это означает, что ожидающий процесс не получит извещение о событии, пока транзакция, в рамках которой была инициировано событие, не завершится.
Кроме получения сообщений класс TUniAlerter умеет их и отправлять. Это делается с помощью метода SendEvent(const EventName: string; const Message: string):
Вызов этого метода отправляет в канал "test_notify" сообщение "Hello PostgreSQL" и его получат все процессы, которые подписались на этот канал.procedure TForm1.btnSendEventClick(Sender: TObject); begin UniAlerter.SendEvent('test_notify', 'Hello PostgreSQL'); end;
Таким образом в наших руках есть инструментарий позволяющий легко организовать обмен сообщениями между различными процессами, подключенными к одной базе данных.
Комментариев нет:
Отправить комментарий