[codex] Suppress notification snapshot timeout tracebacks#1192
Conversation
axisrow
left a comment
There was a problem hiding this comment.
Review: APPROVE — готов к мержу
Чистый, точечный фикс под #1172. Поведение корректно, тест валидирует acceptance-критерии напрямую.
Корректность подтверждена:
- Порядок
except-клауз верный:CancelledError(BaseException, не ловитсяexcept Exception) → новыйTimeoutError→ genericException. Новая клауза стоит ПЕРЕДexcept Exception, иначе не сработала бы. - Источник таймаута —
asyncio.wait_for(client.get_me(), timeout=15.0)вnotification_service.py:77. На Python 3.12 (этот репо)wait_forпри таймауте кидаетTimeoutErrorнапрямую — новая клауза ловит его корректно.asyncio.TimeoutError— алиас builtinTimeoutErrorс 3.11. - Нет утечки клиента:
use_client()(notification_target_service.py:211-214) освобождает клиент вfinally,TimeoutErrorиз телаasync withкорректно триггеритrelease_client. - Внешний
asyncio.wait_for(_publish_snapshots(...), timeout=publish_timeout)не задет: его таймаут даётCancelledErrorвнутри корутины (ловится клаузой на 212), а неTimeoutError— новая клауза ловит только внутренний 15s-таймаутget_me(), как и задумано. exc_infoне передаётся → стека в логе нет, что и проверяетassert "Traceback" not in caplog.text.
Проверки:
ruff check src/runtime/worker.py tests/test_runtime_worker.py— clean.- Новый тест
test_publish_snapshots_notification_bot_timeout_is_nonfatal— PASSED (0.07s). Зеркалит существующий cancelled-path тест, ассертит и наличие короткого WARNING, и отсутствие трейсбэка.
Замечания (необязательные, не блокеры):
- Опциональный пункт из issue (throttle/дедуп повторных WARNING раз в N) не реализован — он был помечен как опциональный, оставление на потом приемлемо.
connection-таймауты помимоTimeoutError(напримерConnectionErrorот Telethon при флапе) по-прежнему пойдут в genericexcept Exceptionс полным трейсбэком. Issue прямо упоминает толькоTimeoutErrorкак наблюдаемый случай, так что для закрытия #1172 этого достаточно; если в логах всплывутConnectionError-стеки — отдельным фиксом.
Failing-тесты из описания PR (test_quality_scoring_service, test_pipelines_page_renders, test_deepagents_all_tools_smoke) не связаны с диффом — окружение/существующие. Дифф их не затрагивает.
Вердикт: approved.
| raise | ||
| logger.warning("Notification bot snapshot refresh was cancelled; continuing worker") | ||
| except asyncio.TimeoutError: | ||
| logger.warning("Notification bot snapshot timed out (network); continuing") |
There was a problem hiding this comment.
Корректно: ловит внутренний таймаут get_me() (notification_service.py:77, asyncio.wait_for(..., timeout=15.0)). Клауза стоит перед except Exception — порядок важен, иначе generic-путь перехватил бы первым. asyncio.TimeoutError == builtin TimeoutError (Py 3.11+), так что покрывает и тот, и другой. Внешний publish-wait_for не задет (он даёт CancelledError, ловится выше).
Summary
Closes #1172.
asyncio.TimeoutErrorseparately while refreshing the notification bot snapshot.exc_info=Truehandler.Tracebackappears incaplog.Validation
ruff check src/ tests/ conftest.pypassed.pytest tests/test_runtime_worker.py -vpassed: 19 passed.pytest tests/ -v -m "not aiosqlite_serial" -n autofailed on unrelated existing/local-environment tests:tests/test_quality_scoring_service.py::{test_score_content_uses_default_provider,test_score_and_check_with_default_provider,test_score_and_check_custom_threshold_higher,test_score_content_long_string}andtests/test_pipelines.py::test_pipelines_page_renders.pytest tests/ -v -m aiosqlite_serialfailed on unrelated existing/local-environment timeout:tests/test_agent_tool_smoke_contract.py::test_deepagents_all_tools_smoke_with_minimal_contract_args.