Есть приложение A , которое крутится где-то там, и к которому у меня нет доступа. Это приложение использует API реализованное с помощью хранимых процедур. Есть приложение B, которое настраивает данные для приложения А, а также строит отчёты по работе приложения А. К приложению B и хранимым процедурам у меня доступ есть. Со временем приложение B обрасло телеграм-ботом. Получать оповещения в режиме реального времени всем понравилось, и тут поступила хотелка: когда в приложении А происходит событие X, оповещать пользователей приложения B через телеграм-бота. Задача была бы несложной, если можно было бы договориться о том, чтобы приложение A уведомляло приложение B о наступлении события X. Но договориться не удалось. Анализ системы показал, что при наступлении события X, приложение A вызывает хранимую процедуру Y. Немного подумав, я решил запустить задание (Job) в приложении B, банально вставив строчку в таблицу jobs. А уж это задание отправит оповещение через телеграм-бота. Драйвер очереди должен быть выбран, как database. Должны быть настроены и запущены воркеры. Лучше один раз увидеть и пощупать, чем сто раз прочитать теорию, поэтому реализацию описываю в виде туториала для тестового приложения. Кто считает это излишним, переходите сразу к этому разделу. Вернуться к началу никогда не поздно. К сожалению, элегантного решения для общего случая я не нашёл, задача решается «в лоб» и для каждого задания решение будет уникальным. Но общую идею я опишу. Наше тестовое приложение будет отправлять письмо и эта отправка будет инициирована хранимой процедурой. Настройте соединение с базой данных. Если базы нет, можно запустить После этого обращаться к базе. Настройки в .env  В качестве драйвера очереди укажите database (QUEUE_CONNECTION=database).  Опыты будем ставить на отправке писем. Чтобы не настраивать соединение, поставьте MAIL_MAILER=log. Пусть письма падают в логи. Заходим в app/Notifications/TestNotify.php и изменяем конструктор и метод toMail()  Давайте проверим, работает ли наше уведомление. Заходим в tinker После появления приглашения вводим код  Отлично! Всё на месте. И тема письма, и ID и почтовый адрес. Лог можно удалить, чтобы не искать факт повторной отправки письма. Заходим в app/Jobs/TestJob.php и изменяем конструктор и метод handle()  Временно настроим драйвер очереди на sync (QUEUE_CONNECTION=sync) и проверим работу нашего задания в tinker. Если вы ещё из него не вышли — выйдите. Запущенный tinker ничего не знает о нашем новом задании. Заходим в tinker и после появления приглашения вводим Почему так странно отправили задание? Ответ находится здесь.  Опять всё на месте. Удаляем лог, меняем драйвер очереди на database. На этом этапе у нас есть уведомление и задание, которое это уведомление отправляет. Настала пора «засунуть» отправку задания в хранимую функцию. Но для начала поймём, как должна выглядеть запись о постановке задания в очередь. Драйвер очереди переключили? Выйдите и войдите в тинкер. Иначе тинкер ничего не будет знать об этом переключении. Давайте ещё раз с помощью тинкер отправим задание в очередь. В таблице jobs должна появиться запись. Поля available_at и created_at равны результату выполнения функции time() на момент вставки записи в таблицу. Это количество секунд, прошедших с начала эпохи Unix (1 января 1970 00:00:00 GMT) до текущего времени. Поле payload содержит в себе json, с которым мы сейчас разберёмся. Заходим в тинкер, выполняем Результат выполнения Собственно, создать такой json в PostgreSQL почти не проблема. Единственное затруднение — это содержимое data->command, в котором хранится сериализованный объект App\Jobs\TestJob Подаём команду в tinker Получаем Проблема в том, что PostgreSQL ничего не знает про объекты PHP и об алгоритме сериализации. Поэтому я принял решение, работать с этим значением, как со строкой.  Теперь можно приступать к работе с PostgreSQL Чтобы вставить запись о задании в таблицу jobs нам нужно: сгенерировать uuid сосчитать количество секунд, прошедших с начала эпохи Unix (1 января 1970 00:00:00 GMT) до текущего времени сформировать json, в который следует вставить необходимые для выполнения задания данные PostgreSQL версии 13 и выше умеет генерировать uuid v 4 из коробки. Чтобы сгенерировать uuid в PostgreSQL ниже 13-й версии, нужны функции, содержащиеся в модуле uuid-ossp. Зачастую этот модуль отключён и его нужно включить. Я покажу, как проверить, подключены ли нужные функции на примере докер-контейнера, описанного выше. Подключаюсь к запущенному контейнеру В контейнере подключаюсь к терминальному клиенту для работы с PostgreSQL — psql Проверяю, какие функции подключены Видно, что функций для работы с uuid нет. Пробуем их добавить. Нам нужна функция uuid_generate_v4. Пробуем ею воспользоваться.  Отлично, работает! Если в вашем случае функции не добавились, обратитесь к документации по PostgreSQL. В прошлом этот модуль зависел от библиотеки OSSP UUID, что отразилось в его имени. Хотя библиотеку OSSP UUID всё ещё можно найти по адресу http://www.ossp.org/pkg/lib/uuid/, она плохо поддерживается и её становится всё сложнее портировать на новые платформы. Поэтому модуль uuid-ossp теперь на некоторых платформах можно собирать без библиотеки OSSP. Во FreeBSD и некоторых других ОС на базе BSD подходящие функции формирования UUID включены в системную библиотеку libc. В Linux, macOS и некоторых других платформах подходящие функции предоставляются библиотекой libuuid, которая изначально пришла из проекта e2fsprogs (хотя в современных дистрибутивах Linux она является частью пакета util-linux-ng). Вызывая configure, передайте ключ --with-uuid=bsd, чтобы использовать функции BSD, либо --with-uuid=e2fs, чтобы использовать libuuid из e2fsprogs, либо ключ --with-uuid=ossp, чтобы использовать библиотеку OSSP UUID. В конкретной системе может быть установлено сразу несколько библиотек, поэтому configure не выбирает библиотеку автоматически.   В PostgreSQL отсутствует функция, аналогичная функции time() в PHP. Поэтому получить нужное количество секунд можно с помощью такой конструкции Самое простое, взять за основу уже готовую запись валидного задания. Берём за основу результат поданной в тинкер команды: json_decode(\DB::table('jobs')->first()->payload) и на основе полученного результата собираем json. Обратите внимание, что вместо передачи известного uuid генерируется новый. Данный запрос возвращает валидный payload для задачи, но нам нужно не просто поставить в очередь задачу, а передать ей данные.  Разберём поле command. Я передаю этот параметр строкой. В сериализованной строке передаётся тип данных и их размерность, если это требуется. Мы передаём в задачу три параметра: два строковых — email и subject и один целочисленный. Который отображается в теле письма. Найдём эти параметры в строке. email: s:12:"tset@liam.ur". s — строка, 12 — длина строки, "tset@liam.ur" — содержимое строки, экранированное двойными кавычками. Аналогично для subject.  В случае id: i:654321 i — целое число, 654321 — его значение. Таким образом, надо подменить следующие параметры: размерность и содержимое. Следует помнить, что в PostgreSQL с вычислением длины строк, закодированных в utf-8,  ровно такая же беда, как и в PHP. Поэтому длину строковых переменных следует вычислять с помощью функции octet_length(); Часть функции, подменяющей параметры Создаём миграцию  Выполняем миграцию Переходим в терминал контейнера и пробуем вызвать эту функцию В терминале запускаем воркер  Всё на месте. Вот таким нехитрым способом можно заставить Laravel реагировать на события, происходящие в базе данных: хранимых функциях и триггерах.