Webhook-вызовы против longpoll для результатов потока

Источник: AudD•

Webhook-вызовы против longpoll для результатов потока

Выберите способ получения событий распознавания потоков AudD: webhook-вызовы, если вы можете разместить публичный HTTPS-эндпоинт, или longpoll, если не можете.

После добавления потока результаты распознавания от AudD передаются в ваш код в виде событий. Существует два способа получения событий от AudD. Вы можете получать их через webhook-вызовы на вашем сервере или через longpoll с вашего клиента. Какой именно метод использовать, зависит от того, можете ли вы разместить публичный HTTPS-эндпоинт. На этой странице описываются оба метода, гарантии их доставки и то, как сделать выбор между ними.

Кратко (TL;DR)

  • Можете ли вы разместить публичный HTTPS-эндпоинт, который возвращает 200 OK? Используйте вызовы (callbacks). Установите URL для вызовов один раз с помощью метода API setCallbackUrl. Вызовы представляют собой POST-запросы с результатами распознавания, которые AudD будет отправлять на этот URL. Это рекомендуемый вариант. Он имеет наименьшую задержку и не требует опроса (polling). Если ваш сервер ненадолго отключится или AudD не сможет к нему подключиться, AudD поместит вызовы в очередь повторных попыток.
  • Не можете предоставить публичный эндпоинт (локальная разработка, виджет в браузере, мобильный клиент, отсутствие статического IP)? Используйте longpoll. Вашему клиенту не обязательно иметь доступ из интернета. Адрес для longpoll: GET https://api.audd.io/longpoll/.
  • Ключевой факт, который легко упустить: пожалуйста, укажите в качестве URL обратного вызова реальный URL, способный принимать POST-запросы, даже если вы планируете использовать только longpoll. Если у вас нет таких URL, установите в качестве URL обратного вызова https://audd.tech/empty/. Этот пустой URL просто возвращает 200 OK. В противном случае longpoll ничего не вернет.

Вы можете использовать longpoll вместо получения вызовов или одновременно с ними. Например, бэкенд может использовать вызовы для логирования результатов, в то время как виджет может использовать longpoll для отображения результатов того же потока.

Почему это важно

AudD распознает песни в потоке по мере их воспроизведения. Результат для песни, которая играет в данный момент, приходит через секунды или минуты после добавления потока. Затем приходит результат для следующей песни и так далее до бесконечности. Это асинхронный процесс, поэтому вы не можете блокировать выполнение в ожидании ответа на запрос «получить ответ». Следовательно, что-то должно доставлять событие каждый раз, когда появляется новый результат.

В случае с вызовами управление инвертируется: AudD вызывает вас. Вам не нужно самостоятельно запрашивать эти результаты; вместо этого просто обработайте вызов. Чтобы AudD мог отправлять вызовы, ваш сервер должен быть доступен из интернета по протоколу HTTPS. Убедитесь, что ваш сервер работает, когда AudD отправляет вызовы. При использовании longpoll клиент отправляет запрос и ждет ответа. Соединение остается открытым до тех пор, пока событие не будет готово или не истечет тайм-аут. Это требует лишь того, чтобы клиент устанавливал исходящие HTTPS-соединения с AudD. Клиент может быть браузером, телефоном или ноутбуком за NAT. Нет необходимости хостить входящий эндпоинт.

Выбор неправильного метода редко бывает фатальным, но всегда раздражает: вы либо создадите обработчик вебхуков, к которому у вас нет доступа из браузера, либо будете опрашивать сервер, который мог бы просто принимать push-уведомления. Поэтому определите, где фактически выполняется ваш код обработки результатов, и выберите метод, исходя из этого.

Вызовы: AudD отправляет вам POST-запросы

Установите URL для вызовов с помощью метода API setCallbackUrl. Для каждой учетной записи можно настроить только один URL обратного вызова, и вы можете изменить его в любое время с помощью того же метода. С этого момента вызовы с каждым результатом распознавания и уведомлением будут отправляться на этот URL в виде структуры JSON в теле POST-запроса.

Вы будете получать вызовы с результатами и уведомлениями.

  • Результаты содержат распознанные песни. Каждый результат также содержит выбранный вами для потока radio_id, метку времени (timestamp) и (по умолчанию) длину воспроизведения (play_length).
  • Уведомления содержат информацию о работоспособности потоков. Если с аудиопотоком что-то случится, AudD сообщит вам об этом, отправив уведомление, чтобы вы могли настроить оповещение и исправить поток или изменить его URL. Существует 3 кода: 0 (означает, что все в порядке), 650 (означает, что AudD не может подключиться к потоку) и 651 (означает, что AudD получает от потока только белый шум без музыки).

Убедитесь, что ваш обработчик отвечает статусом HTTP 200 OK при получении вызовов. Если ваш сервер отвечает чем-то другим или AudD не может к нему подключиться, доставка считается неуспешной, и вызовы помещаются в очередь для повторной попытки (см. семантику доставки ниже). Если вы можете разместить принимающий сервер, вызовы являются рекомендуемым методом.

Longpoll: вы запрашиваете данные у AudD

Если вы не можете разместить входящий эндпоинт, longpoll позволяет любому количеству клиентов получать новые результаты через обычные исходящие HTTPS-запросы без необходимости развертывать веб-сервер или иметь статический IP-адрес.

Каждый запрос longpoll завершается либо потому, что готово новое событие, либо потому, что истекло время ожидания (timeout). Когда вы получаете ответ, содержащий поле timestamp, используйте его в качестве обновленного значения since_time для нового запроса, чтобы не пропустить события и не получить их повторно. В качестве категории подписки используйте поле longpoll_category из ответа getStreams или вычислите первые девять символов MD5(MD5("ваш api_token") + "radio_id"). Вы можете передавать категории своим клиентам или пользователям, но никогда не включайте свой API-токен в клиентское программное обеспечение.

Для longpoll по-прежнему требуется настроенный URL обратного вызова. Установите URL обратного вызова, даже если вы хотите использовать только longpoll и никогда не запускать webhook-обработчик; в противном случае longpoll ничего не вернет. Если у вас нет такого URL, установите пустой обработчик https://audd.tech/empty/ в качестве URL обратного вызова. Он отвечает статусом 200 OK и отбрасывает полезную нагрузку. Начинайте опрос только после того, как установите его с помощью метода setCallbackUrl (или в веб-интерфейсе).

Для longpoll по-прежнему требуется настроенный URL обратного вызова. Установите URL обратного вызова, даже если вы хотите использовать только longpoll и никогда не запускать webhook-обработчик; в противном случае longpoll ничего не вернет. Если у вас нет такого URL, установите пустой обработчик https://audd.tech/empty/ в качестве URL обратного вызова. Он отвечает статусом 200 OK и отбрасывает полезную нагрузку. Начинайте опрос только после того, как установите его с помощью метода setCallbackUrl (или в веб-интерфейсе).

Поскольку longpoll работает на стороне клиента, он позволяет отображать результаты в браузере или мобильном приложении. Вы также можете использовать готовый HTML-виджет AudD: https://widget.audd.tech/?ch=-92b1cc7f0&background&history&shadow. Он работает на базе longpoll. Используйте категорию longpoll со знаком «-» перед ней в качестве параметра URL ch. Вы сможете показывать то, что играет в данный момент, вообще без бэкенда.

Семантика доставки: повторные попытки, порядок и пропущенные события

Эти два метода ведут себя по-разному при возникновении сбоев, и это различие часто становится решающим фактором.

У вызовов есть очередь повторных попыток. Если ваш сервер не отвечает на вызовы со статусом 200 OK или AudD не может подключиться к вашему серверу, AudD помещает вызовы в очередь. Когда ваш сервер снова оказывается в сети, AudD постепенно отправляет накопленные данные вместо того, чтобы отбрасывать их. У AudD есть ограничение частоты (rate limit) на отправляемые запросы: при количестве потоков менее 500 вы будете получать не более 3 вызовов в секунду (с размером пакета до 15). Очередь накопленных данных включает в себя все, что не было доставлено, поэтому кратковременный сбой приводит к задержке, а не к потере данных, если ваш эндпоинт в конечном итоге возвращает 200 OK.

Longpoll догоняет данные по курсору. В отличие от вебхуков (callbacks), здесь нет повторных попыток отправки со стороны сервера. Вместо этого вы управляете непрерывностью с помощью since_time: переносите временную метку каждого ответа вперед, и вы получите все данные, начиная с этого момента. Если пропустить этот шаг или если между запросами пройдет слишком много времени, возникает риск появления пробела в данных. Курсор — это то, что предотвращает пропуск и дублирование событий, поэтому его сохранение и повторное использование является обязательным, а не опциональным.

Порядок. Оба метода доставляют события по мере распознавания песен с течением времени. При использовании вебхуков порядок событий совпадает с порядком их отправки AudD. При использовании longpoll это порядок продвижения since_time, которым управляете вы. В обоих случаях никогда не следует полагаться на строгий глобальный порядок для множества потоков; вместо этого сопоставляйте результаты по radio_id (и временной метке).

Вы можете отключить longpoll для своих потоков, добавив disable-lastsong=true в качестве параметра в URL вашего вебхука. Это может быть полезно, если вы используете только вебхуки и не хотите, чтобы результаты сохранялись для опроса.

Опция callbacks="before"

По умолчанию результат отправляется после окончания воспроизведения песни и содержит play_length — общее время нахождения песни в эфире. Это слишком поздно для отображения текущей песни (now-playing), так как песня будет объявлена только тогда, когда она уже закончится.

Установите callbacks="before" при добавлении потока, если вы хотите получать уведомления сразу после начала воспроизведения песни (а не по ее окончании):

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

  • before предназначен для интерактивных интерфейсов текущей трансляции («now playing»).
  • Значение по умолчанию (after) предназначено для эфирных логов и отчетов, где требуется точная продолжительность.

Этот параметр определяет момент создания события и применяется независимо от того, получаете ли вы затем событие через вебхуки или через longpoll.

Практический пример

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

Бэкенд сервера для логирования эфира (вебхуки). У бэкенда есть публичный HTTPS-эндпоинт. Для него вебхуки являются рекомендуемым вариантом. Задайте URL для вебхуков один раз с помощью setCallbackUrl("https://yourapp.example/audd-callback"). Добавьте каждую станцию с помощью метода addStream. По умолчанию AudD будет отправлять новые результаты после окончания воспроизведения песен, поэтому каждый результат содержит play_length. Бэкенд получает вебхуки от API AudD, записывает каждую строку результата с ключом radio_id и возвращает 200 OK для AudD. При развертывании бэкенд будет перезапущен. Тем не менее, очередь повторных попыток достаточно надежна, чтобы вы могли перезагрузиться без потери данных о воспроизведении. Когда бэкенд снова окажется в сети, AudD отправит всю накопленную очередь. Если с потоком что-то случится, AudD сообщит вам об этом, отправив уведомление 650 или 651. Настройте оповещения для уведомлений 650/651, чтобы неработающий поток обнаруживался немедленно.

Виджет текущей песни в браузере (longpoll). Веб-страницы не могут принимать входящие вебхуки, поэтому этот вариант не подходит. Сначала задайте URL вебхука; если его нет, используйте пустой URL https://audd.tech/empty/ (URL вебхука необходим для того, чтобы longpoll возвращал данные). Затем добавьте поток с параметром callbacks="before", чтобы виджет обновлялся сразу после начала воспроизведения песни. После этого вы можете встроить размещенный у себя виджет AudD. Используйте категорию longpoll с дефисом перед ней в качестве параметра URL ch, например ch=-<category>. Если вы отправляете запросы longpoll из собственного фронтенда, опрашивайте https://api.audd.io/longpoll/ с указанием категории и передавайте каждую временную метку в следующий since_time. Таким образом, виджет получает новые результаты без необходимости запуска веб-сервера или наличия статического IP-адреса. Он может работать совместно с бэкендом на основе вебхуков для одного и того же потока.

Распространенные ошибки

  • Запуск longpoll без предварительно настроенного URL вебхука. Для хранения результатов longpoll требуется настроенный URL вебхука. В противном случае опрос ничего не вернет. Если у вас нет таких URL, укажите https://audd.tech/empty/ в качестве URL вебхука.
  • Возврат кода, отличного от 200, из обработчика вебхуков. Если ваш сервер не отвечает на вебхуки со статусом 200 OK, AudD помечает доставку как неудачную и помещает вебхук в очередь. Возвращайте статус 200 немедленно, а затем выполняйте обработку асинхронно, чтобы медленная обработка не переполняла очередь.
  • Игнорирование since_time в longpoll. Если вы не переносите временную метку каждого ответа в следующий since_time или пропускаете одну из временных меток, вы будете повторно запрашивать старые события или пропускать новые. Этот курсор обеспечивает работу longpoll без пропусков.
  • Размещение токена API в коде longpoll на стороне клиента. Вы можете делиться longpoll_category с браузерами и приложениями, но не включайте api_token в программное обеспечение на стороне клиента. Чтобы получить категорию, вычислите первые девять символов MD5(MD5("ваш_api_token") + "radio_id").
  • Ожидание play_length при использовании callbacks="before". Если вы передаете "before", вы не получите общую продолжительность воспроизведения в вебхуках. По умолчанию вебхуки отправляются после окончания воспроизведения песни и содержат общую продолжительность воспроизведения. Когда вам нужна длительность, рекомендуется использовать значение по умолчанию.
  • Создание обработчика вебхуков для браузера или мобильного интерфейса. Браузерные и мобильные клиенты не могут принимать входящие POST-запросы. Вы можете использовать longpoll (или размещенный виджет) для всего, что работает на стороне клиента.
  • Standard, Enterprise или Streams: как сделать выбор
  • Создание виджета текущей трансляции
  • Мониторинг радиоэфира
  • Документация по потокам
  • Справочник API

О чём эта статья