Skip to content

fix: skip updates that do not fit their model instead of crashing - #45

Merged
BushlanovDev merged 1 commit into
BushlanovDev:masterfrom
smotim:fix/unparseable-updates
Sep 30, 2026
Merged

BushlanovDev merged 1 commit into
BushlanovDev:masterfrom
smotim:fix/unparseable-updates

Conversation

@smotim

@smotim smotim commented Sep 27, 2026

Copy link
Copy Markdown
Contributor

Продолжение #17: тихий режим для неподдерживаемых типов событий из issue #15.

Проблема

#17 глушит LogicException из createUpdate(): createUpdateList() и WebhookHandler пишут debug и пропускают событие. Но бывает, что тип события известен, а данные не подходят модели: API сделал поле необязательным или добавил новое значение enum. Тогда ошибка возникает раньше — TypeError или ValueError в конструкторе модели, — и её никто не ловит:

  • Long polling. Ошибка вылетает из getUpdates(), а LongPollingHandler::handle() ловит только \Exception. Цикл останавливается, после перезапуска получает тот же пакет и падает снова.
  • Вебхук. WebhookHandler отвечает 500, и MAX повторяет запрос.

Реальный пример: в схеме 0.0.33 User.last_activity_time стал необязательным, и событие с таким пользователем падает с TypeError: Argument #6 ($lastActivityTime) must be of type int, null given. Так же сломает бота любое новое значение ChatAdminPermission или ChatType: ::from() бросит ValueError.

Решение

createUpdate() превращает TypeError и ValueError в LogicException (исходная ошибка сохраняется в previous) и пишет warning с payload. Дальше работает существующий тихий режим: событие пропускается, бот продолжает работать. Расхождение с API видно в логе на уровне warning, а не debug.

Ошибки в обработчиках пользователя не затронуты: преобразование происходит только внутри createUpdate().

Тесты

  • createUpdate() на payload без обязательного поля выбрасывает LogicException с TypeError в previous и пишет warning.
  • createUpdateList() пропускает событие с TypeError и событие с неизвестным chat_type (ValueError), остальные события возвращает.
  • WebhookHandler с настоящей ModelFactory не падает и не вызывает обработчик.

Покрытие осталось 100%. PR не зависит от #43 и от PR со сверкой схемы 0.0.33; вместе с ним новые модели оттуда тоже не уронят бота, если реальный API разойдётся со схемой.

BushlanovDev#17 made unsupported update types silent: createUpdate() throws a
LogicException, and createUpdateList() and WebhookHandler log it and
skip the update. An update of a known type whose payload no longer
fits the model (the API made a field optional, added an enum value)
fails earlier, with a TypeError or ValueError from the model
constructor, and nothing catches those:

- createUpdateList() lets it out of getUpdates(), and
  LongPollingHandler::handle() catches only \Exception, so the loop
  stops and restarts into the same batch
- WebhookHandler answers 500 and MAX keeps retrying

createUpdate() now turns TypeError and ValueError into a
LogicException (the original one kept as previous) and logs a warning
with the payload, so the existing silent mode skips such an update.
Errors thrown by user handlers are not affected.
@BushlanovDev BushlanovDev self-assigned this Sep 30, 2026
@BushlanovDev
BushlanovDev self-requested a review September 30, 2026 19:30
@BushlanovDev
BushlanovDev merged commit bf5219a into BushlanovDev:master Sep 30, 2026
4 checks passed
@smotim
smotim deleted the fix/unparseable-updates branch September 30, 2026 20:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants