# Надёжные исходящие события Модуль `reliable_events` отправляет webhook без сетевого запроса внутри сохранения документа. ## Для чего он нужен Это не аудит действий администратора и не журнал cron. Модуль связывает AVE.cms с внешними сервисами: CRM, Telegram-ботом, учётной системой, сервисом аналитики или собственным обработчиком. Движок или установленный модуль создаёт именованное событие. `reliable_events` сохраняет его в очереди, подбирает активные подписки и отправляет каждой из них подписанный JSON. Поэтому временно недоступный внешний сервис не блокирует сохранение документа и не приводит к потере события. ## Как это работает 1. AVE.cms записывает документ и событие в одной транзакции. 2. После успешного коммита событие остаётся в очереди. 3. Планировщик забирает небольшую пачку. 4. Получатель получает подписанный HTTP POST. 5. Результат записывается в журнал. 6. Временная ошибка повторяется с увеличивающейся задержкой. Недоступная интеграция не мешает редактору сохранить документ. ## Связь с планировщиком Модуль автоматически регистрирует в [Планировщике](scheduler.md) две задачи: - `reliable_events.deliver` — каждую минуту забирает до 20 готовых событий, отправляет webhook и назначает повтор для временных ошибок; - `reliable_events.cleanup` — ежедневно в 03:40 удаляет успешно доставленные события старше 30 дней. Кнопка **Обработать очередь** на странице модуля запускает одну такую пачку немедленно. Она полезна для проверки подписки, но не заменяет автоматический запуск Планировщика на сервере. Историю выполнения самих фоновых задач смотрите в Планировщике, а HTTP-ответы конкретных получателей — на вкладке **Попытки доставки** этого модуля. ## Подписка В разделе **Модули → Исходящие события** укажите название, код события, HTTPS URL, число попыток, таймаут и секрет. Код может быть точным `content.document.published` или групповым `content.document.*`. События документов: - `content.document.created`; - `content.document.updated`; - `content.document.published`; - `content.document.unpublished`. Собственное событие модуля: ```php use App\Modules\ReliableEvents\Dispatcher; Dispatcher::emit('my_module.completed', array( 'operation_id' => 15, 'result' => 'success', ), array( 'aggregate_type' => 'operation', 'aggregate_id' => 15, )); ``` Событие записывается в очередь только тогда, когда на момент вызова есть хотя бы одна активная подписка с подходящим кодом. Подписка, созданная позже, не получит уже прошедшие события: outbox является очередью доставки, а не полным журналом действий. ## Запрос и подпись JSON содержит `id`, `event`, `occurred_at` и `data`. Заголовки: - `X-AVE-Event`; - `X-AVE-Event-Id`; - `X-AVE-Timestamp`; - `X-AVE-Signature: sha256=<подпись>`. Подпись — HMAC SHA-256 строки `.`. Получатель должен проверять подпись, возраст timestamp и уникальность Event ID. Успешная доставка конкретной подписке не повторяется. После исчерпания попыток событие останавливается, но администратор может вернуть его в очередь. Если процесс доставки аварийно завершится, просроченная блокировка автоматически освободится при следующем запуске обработчика. Для автоматической обработки должен быть настроен серверный запуск [Планировщика](scheduler.md).