К содержимому

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

В карточке звонок «завершён», потом снова «идёт». Длительность отрицательная.

restочереди

Интеграция принимает вебхуки о звонке: начался, ответили, завершился. В карточке CRM звонок сначала помечается завершённым, а через секунду снова становится активным. Иногда длительность выходит отрицательной.

Причина

Провайдер отправляет события параллельно, и порядок доставки не гарантирован. Событие «завершён» уходит по более быстрому маршруту и приходит раньше, чем «ответили». Ваш обработчик применяет их в порядке получения — и состояние затирается более старым.

Это не сбой провайдера. Так устроена любая доставка через сеть без явной синхронизации: гарантируется факт доставки, но не очерёдность.

Обычно в теле события есть поле последовательности — счётчик или точная метка времени на стороне провайдера. Именно оно описывает реальный порядок, а не момент, когда запрос долетел до вас.

Решение

Хранить у звонка номер последнего применённого события и отбрасывать всё, что старше:

UPDATE calls
   SET status = :status,
       last_seq = :seq
 WHERE call_id = :call_id
   AND last_seq < :seq;

Ноль обновлённых строк — событие устаревшее, применять нечего. Это одновременно решает и вторую проблему: повторную доставку. Провайдеры переотправляют вебхуки при таймауте, и без такой проверки один звонок обработается дважды.

Условие должно быть в самом запросе, а не в коде до него. Проверка «сначала прочитали, потом сравнили, потом записали» разваливается, когда два вебхука обрабатываются одновременно: оба прочитают старое значение и оба решат, что имеют право писать.

Что ещё стоит учесть

Событие может прийти раньше, чем создан объект. Если «ответили» обогнало «начался», записи о звонке ещё нет. Обработчик должен уметь создать её на месте, а не падать с «звонок не найден».

Метки времени берём провайдерские. Своё время постановки в очередь для восстановления порядка не годится: оно как раз и отражает кривой порядок доставки.

Как проверить, что чинилось не зря

Прогнать события звонка в обратном порядке. Итоговое состояние карточки должно совпасть с прямым прогоном — если совпадает, интеграция больше не зависит от прихотей маршрутизации.

Дальше

Новые разборы выходят в Telegram раньше, чем попадают сюда. Без анонсов курсов — только материалы.

Читать в Telegram →