Вернуться в блог
Журнал Adal Cloud

Можно ли получать вебхуки, пока компьютер выключен?

Adal принимает и сохраняет вебхуки в облаке, а после подключения доставляет их локальному приложению.

Опубликовано
Можно ли получать вебхуки, пока компьютер выключен?

Да — если вебхук сначала принимает постоянно доступный облачный сервис, а локальный компьютер подключается к нему позже.

Сам выключенный компьютер, конечно, не может принять HTTP-запрос. На нём не работает обработчик, нет активного сетевого соединения, а localhost недоступен внешнему сервису. Но это не означает, что событие должно потеряться или что webhook URL нужно менять перед каждым запуском разработки.

В Adal приём запроса и его доставка локальному приложению разделены:

Внешний сервис → публичный Сервер Adal → сохранённый Request → Adal CLI после подключения → локальный обработчик

Пока ноутбук выключен, Сервер Adal продолжает принимать вебхуки на постоянный публичный HTTPS URL. При включённом хранении Requests сохраняются в выбранном регионе в пределах retention-периода. Когда компьютер снова включается и Adal CLI восстанавливает соединение, ожидающие Requests могут быть доставлены локальному приложению.

Именно с этой задачи началась разработка Adal: принять вебхук независимо от состояния компьютера разработчика, не потерять его и передать обработчику после возвращения в онлайн. Позже вокруг этого сценария появились просмотр запросов, несколько Destinations, история попыток, retries, Replay и доставка в закрытые production-сети. Но исходная идея осталась прежней: доступность публичного webhook URL не должна зависеть от того, открыт ли сейчас ноутбук.

Почему обычная доставка на localhost не работает в офлайне

Webhook-провайдер отправляет HTTP-запрос в момент события. Например, платёжный сервис сообщает об успешной оплате, GitHub — о новом push, а CRM — об изменении сделки. Чтобы запрос дошёл, указанный webhook URL должен быть доступен из интернета именно в этот момент.

Локальный адрес вроде http://localhost:3000/webhooks существует только внутри вашего компьютера. Даже когда машина включена, внешний сервис не может обратиться к нему напрямую. Для разработки обычно используют публичный сервер, проброс порта или туннель, который пересылает трафик на локальный обработчик.

Но активный туннель тоже зависит от локального соединения. Если компьютер уснул, выключился, потерял сеть или CLI-процесс остановился, пересылать запрос больше некуда. Дальнейший результат зависит от поведения отправителя: один провайдер повторит доставку, другой быстро исчерпает попытки, а третий вообще не поддерживает удобную ручную отправку события заново.

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

Что происходит с вебхуком, пока компьютер выключен

Разберём путь одного запроса по шагам.

1. Внешний сервис отправляет вебхук на постоянный URL

У Сервера Adal есть собственный публичный HTTPS URL. Его один раз указывают в настройках провайдера, например:

https://a1b2c3d4e5f6g7h8.se1.adal.cloud/webhooks/payment

Этот адрес не меняется при остановке локального приложения, закрытии Adal CLI или перезагрузке компьютера. Провайдер продолжает отправлять события на тот же URL.

2. Adal принимает и сохраняет Request

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

Это и есть persistence: запрос существует независимо от процесса на локальном компьютере. Его можно увидеть и изучить, даже если обработчик в момент события не работал.

Хранение не бессрочное. У каждого Request есть дата удаления, которая определяется retention выбранного плана и настройками хранения. После окончания retention запрос нельзя восстановить, доставить или запустить через Replay. Поэтому максимальный период офлайна ограничен временем, в течение которого нужный Request остаётся сохранённым. Подробнее это описано в документации по хранению данных.

3. Delivery ждёт подключения CLI

Для доставки на локальный адрес используется Destination типа Adal CLI. Сам Adal CLI запускается на компьютере разработчика и устанавливает защищённое исходящее соединение с Adal. Публичный IP, входящий порт и изменение NAT для этого не нужны.

Пока CLI отключён, Adal не может начать HTTP-доставку в локальный сервис. Ожидание соединения не считается неудачной попыткой и не уменьшает настроенный лимит попыток: запрос ещё не был передан обработчику.

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

4. После подключения начинается доставка накопленных Requests

За этот сценарий отвечает настройка Сервера Deliver pending requests on connect. Если она включена, сохранённые ожидающие Requests могут быть переданы после подключения CLI. Если настройка выключена, CLI получает новые Requests, пришедшие после подключения, а накопленные во время офлайна не доставляются автоматически.

Именно поэтому фраза «Adal всегда доставит всё после включения компьютера» была бы неточной. Для отложенной доставки должны одновременно выполняться несколько условий:

  • Сервер принял Request;

  • Request сохранён и его retention ещё не закончился;

  • Destination типа Adal CLI по-прежнему настроена;

  • включена настройка Deliver pending requests on connect;

  • CLI подключился с токеном нужного Сервера;

  • локальное приложение доступно по адресу Destination.

Если этот сценарий для вас основной, настройку накопленной доставки лучше проверить заранее, а не после первого пропущенного события.

Buffering, persistence, retries и reconnect delivery — не одно и то же

Эти четыре понятия часто объединяют словом «очередь», хотя они отвечают за разные участки процесса.

Buffering отделяет скорость входящего потока от готовности получателя. Вебхуки могут приходить, пока локальный обработчик временно не способен их принимать немедленно.

Persistence означает, что принятый Request сохранён за пределами локального процесса и не исчезает вместе с выключением ноутбука. В Adal это хранение ограничено retention-периодом.

Reconnect delivery запускает передачу ожидающих Requests после того, как Adal CLI снова установил соединение. Такое поведение контролируется настройкой Deliver pending requests on connect.

Retry — это следующая попытка уже начавшейся, но не завершившейся успешно Delivery. Например, CLI подключён и передал запрос локальному приложению, но приложение вернуло 500 или соединение завершилось тайм-аутом. Тогда Adal записывает результат и применяет правила повторных попыток Destination.

Коротко это можно представить так:

CLI отключён → Delivery ждёт соединения → попытка ещё не началась CLI подключён, приложение вернуло ошибку → попытка завершилась неуспешно → применяется retry-политика

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

Практический пример: вебхуки пришли ночью

Представим, что вы разрабатываете обработчик событий платёжного сервиса. Его webhook URL уже указывает на Сервер Adal, а Destination ведёт через CLI на локальный адрес:

http://127.0.0.1:3000/webhooks/payment

Вечером вы выключаете ноутбук. Ночью тестовая среда платёжного сервиса отправляет три события:

01:14 payment.succeeded 02:07 refund.created 04:31 payment.dispute.opened

Сервер Adal принимает их и создаёт три Requests. Локальной доставки в этот момент нет, потому что CLI отключён.

Утром вы запускаете приложение и Adal CLI. При включённой настройке Deliver pending requests on connect и действующем retention ожидающие Requests начинают поступать в обработчик. По каждому из них в Adal остаётся отдельная история доставки.

Если обработчик вернул 500 для второго события, это уже не ожидание подключения, а неудачная попытка. Дальше работают настроенные retries. Если причина исправлена, конкретную Delivery также можно повторить вручную. А Replay создаст новый Request на основе сохранённого исходного запроса — это отдельная операция, полезная для повторного теста кода.

Что произойдёт при коротком обрыве интернета

Для Adal нет принципиальной разницы между выключенным компьютером, спящим ноутбуком, перезапуском CLI и временным исчезновением сети: во всех этих случаях соединение CLI отсутствует.

После восстановления сети CLI переподключается. Дальнейшее поведение ожидающих Requests снова зависит от Deliver pending requests on connect и retention. Публичный URL Сервера при этом остаётся тем же, поэтому менять настройки webhook-провайдера после каждого обрыва не требуется.

Если CLI успел передать запрос локальному приложению, но соединение оборвалось до получения однозначного ответа, возможна повторная доставка. Это нормальное следствие модели at-least-once: транспорт не всегда может определить, успел ли обработчик выполнить действие до разрыва. Поэтому локальный webhook-обработчик должен быть идемпотентным. Стабильный event ID провайдера следует использовать, чтобы повторный запрос не создавал второй платёж, заказ или уведомление. Подробнее — в статье «Почему вебхуки нужно обрабатывать идемпотентно».

Когда этот сценарий особенно полезен

Приём вебхуков во время офлайна нужен не только для ночной разработки.

  • Локальная разработка. Реальные события продолжают поступать, даже если разработчик не держит приложение и CLI запущенными постоянно.

  • Редкие события. Не нужно заново воспроизводить длинный внешний сценарий только потому, что событие произошло во время перерыва.

  • Демо и интеграционные тесты. Постоянный webhook URL можно зарегистрировать заранее и не менять из-за перезапуска ноутбука.

  • Нестабильное соединение. Короткий обрыв интернета не делает локальную машину публично недоступным webhook endpoint — публичный приём остаётся на стороне Adal.

  • Закрытые сети. Тот же принцип работает не только с ноутбуком, но и с on-premises или private-сервисом, который не должен принимать входящие подключения из интернета.

Для пошаговой настройки локальной доставки используйте руководство «Как принимать вебхуки локально без публичного IP».

Что проверить перед тем, как уйти в офлайн

Короткий чек-лист помогает не обнаружить утром, что один из элементов цепочки не был настроен:

  1. Внешний сервис использует актуальный HTTPS URL Сервера Adal.

  2. На Сервере включено хранение, а retention покрывает ожидаемый период офлайна.

  3. Включена настройка Deliver pending requests on connect.

  4. Destination связана с нужным Сервером и содержит правильный локальный URL.

  5. Токен CLI сохранён безопасно и относится к этому Серверу.

  6. После запуска компьютера стартуют и локальное приложение, и Adal CLI.

  7. Обработчик проверяет подпись провайдера и обрабатывает повторы идемпотентно.

Проверку лучше провести заранее: отключить CLI, отправить тестовый вебхук, убедиться, что Request появился в Adal, затем снова подключить CLI и проверить результат Delivery.

Компьютер может быть выключен — webhook URL остаётся доступным

Получать вебхуки прямо на выключенный компьютер невозможно. Но и держать ноутбук постоянно включённым ради webhook URL не обязательно.

Adal принимает запрос на постоянно доступной публичной стороне, сохраняет его в пределах retention и отделяет этот факт от доставки локальному обработчику. После восстановления соединения CLI накопленные Requests могут быть доставлены приложению, а временные ошибки уже начавшейся доставки обрабатываются через retries.

Именно это разделение делает офлайн-сценарий предсказуемым:

принять сейчас → сохранить → дождаться подключения → доставить → показать результат

Начать можно с быстрого старта Adal, а затем проверить настройки Сервера, retention и повторных попыток под длительность и характер вашей разработки.

Другие материалы блога Adal Cloud

Читайте об обновлениях продукта, работе с вебхуками и инженерных решениях.

Вернуться в блог