Files
portal/app/tests/Feature/Http/Webhook
Дмитрий 541f38d452
Accessibility (Pa11y live) / a11y (push) Has been cancelled
SAST — Semgrep / Semgrep SAST scan (push) Has been cancelled
fix(поставщик): отсрочка добора + живой журнал вебхука — конец ложным «вебхук потерял N»
Повод — письмо тревоги 31.07.2026 05:30 МСК: сверка №1417 отрапортовала «потеряно 7».
Разбор на бою показал, что вебхук по тем же семи пришёл через 2,5 минуты (05:32:32 ×2 +
05:33:03 ×5) и получил «уже есть». Потери не было: поставщик кладёт строку в журнал
отданного РАНЬШЕ, чем шлёт вебхук, а наша сверка (каждые 30 мин) попадала в эту щель.
Цена ошибки не только ложная тревога: добранная карточка беднее живой (в журнале нет
tag/time/phones) — у 4 из 7 не определился регион, у сделок пустые регион и город.

1. Отсрочка добора (CsvReconcileJob::GRACE_MINUTES = 15). Недостача, увиденная впервые,
   уходит в карантин (Redis, карта vid => время первого обнаружения) и добирается только
   следующим прогоном, если провисела дольше отсрочки. Реальная потеря доезжает максимум
   через полчаса. Потеря карантина безопасна: в худшем случае добор на прогон позже.
   drift и «потеряно» в письме считаются ТОЛЬКО по просроченному; «в пути» — отдельно
   (новая колонка supplier_csv_reconcile_log.pending_count).

2. Журнал вебхука поставщика (новая таблица supplier_webhook_log). Прежний
   logSupplierWebhook писал в webhook_log, снесённую 24.05 вместе с legacy-каналом, и
   молча выходил по Schema::hasTable — журнала не было ВООБЩЕ. Из-за этого 70 отказов 404
   за 10 дней никто не видел; нашлись случайно в логе nginx. Пишем статус, адрес
   отправителя, запрошенный хост и отпечаток присланного ключа (первые 8 символов md5 —
   отвечает «наш ключ или чужой», секретом не является). Отказы дополнительно уровнем
   warning: на бою LOG_LEVEL=warning, info в журнал не попадает.

3. Текст письма-тревоги переписан: «потеря» = только то, что не дошло даже за отсрочку;
   «в пути» показывается отдельной строкой и потерей не считается.

4. В catch сверки — Log::error ПЕРВЫМ действием, до обращений к БД: при испорченной
   транзакции следующий запрос бросал своё исключение и настоящая причина терялась.

Проверено: тесты поставщика и вебхука 230/230 (в т.ч. 5 новых на карантин, поздний
вебхук, отчёт «в пути» и смоук шаблона письма), Larastan 0, Pint чисто. Прогон всей базы
3566/3575; 5 падений — чужие и до этих правок (замерено откатом файлов): биллинг на стыке
месяцев и маршруты телеграм-ветки.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 08:52:14 +03:00
..