Когда бэкенд обрывает SSE-поток /api/events (перезапуск uvicorn по --reload, Ctrl+C), vite-прокси не передаёт обрыв клиенту. Соединение браузер ↔ vite остаётся открытым, EventSource не видит разрыва и не переподключается. Вкладка перестаёт получать события в реальном времени до ручного обновления страницы, а ошибок нигде нет.
Как воспроизведено (dev, uvicorn с --timeout-graceful-shutdown 2 из #47):
curl -N на http://127.0.0.1:8000/api/events напрямую → после правки .py поток обрывается со стороны сервера (curl exit 18). EventSource в таком случае переподключится.
curl -N на http://127.0.0.1:5173/api/events через vite → после того же перезапуска поток висит до таймаута самого клиента (curl exit 28 по --max-time 60), хотя бэкенд уже заменён и отвечает на новые запросы.
Касается только dev: в test/prod SPA и API отдаёт один FastAPI за Caddy, vite-прокси там нет. Предположительно, дело в http-proxy внутри vite: при обрыве ответа апстримом (без завершающего чанка) он не закрывает клиентский ответ. Направления для решения: обработчик proxyRes / configure в vite.config.ts, который закрывает res при close/aborted у апстрима, либо таймаут неактивности на клиенте в useServerEvents.ts (пинг приходит каждые 25 с).
Когда бэкенд обрывает SSE-поток `/api/events` (перезапуск uvicorn по `--reload`, Ctrl+C), vite-прокси не передаёт обрыв клиенту. Соединение браузер ↔ vite остаётся открытым, EventSource не видит разрыва и не переподключается. Вкладка перестаёт получать события в реальном времени до ручного обновления страницы, а ошибок нигде нет.
**Как воспроизведено** (dev, uvicorn с `--timeout-graceful-shutdown 2` из #47):
- `curl -N` на `http://127.0.0.1:8000/api/events` напрямую → после правки `.py` поток обрывается со стороны сервера (`curl` exit 18). EventSource в таком случае переподключится.
- `curl -N` на `http://127.0.0.1:5173/api/events` через vite → после того же перезапуска поток висит до таймаута самого клиента (`curl` exit 28 по `--max-time 60`), хотя бэкенд уже заменён и отвечает на новые запросы.
Касается только dev: в test/prod SPA и API отдаёт один FastAPI за Caddy, vite-прокси там нет. Предположительно, дело в `http-proxy` внутри vite: при обрыве ответа апстримом (без завершающего чанка) он не закрывает клиентский ответ. Направления для решения: обработчик `proxyRes` / `configure` в `vite.config.ts`, который закрывает `res` при `close`/`aborted` у апстрима, либо таймаут неактивности на клиенте в `useServerEvents.ts` (пинг приходит каждые 25 с).
Обнаружено при работе над #47.
Agent
added this to the v1.35 - промежуточная полировка версии 1.3 milestone 2026-09-13 12:19:13 +03:00
Agent
added the Kind/Bug label 2026-09-13 12:19:14 +03:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Когда бэкенд обрывает SSE-поток
/api/events(перезапуск uvicorn по--reload, Ctrl+C), vite-прокси не передаёт обрыв клиенту. Соединение браузер ↔ vite остаётся открытым, EventSource не видит разрыва и не переподключается. Вкладка перестаёт получать события в реальном времени до ручного обновления страницы, а ошибок нигде нет.Как воспроизведено (dev, uvicorn с
--timeout-graceful-shutdown 2из #47):curl -Nнаhttp://127.0.0.1:8000/api/eventsнапрямую → после правки.pyпоток обрывается со стороны сервера (curlexit 18). EventSource в таком случае переподключится.curl -Nнаhttp://127.0.0.1:5173/api/eventsчерез vite → после того же перезапуска поток висит до таймаута самого клиента (curlexit 28 по--max-time 60), хотя бэкенд уже заменён и отвечает на новые запросы.Касается только dev: в test/prod SPA и API отдаёт один FastAPI за Caddy, vite-прокси там нет. Предположительно, дело в
http-proxyвнутри vite: при обрыве ответа апстримом (без завершающего чанка) он не закрывает клиентский ответ. Направления для решения: обработчикproxyRes/configureвvite.config.ts, который закрываетresприclose/abortedу апстрима, либо таймаут неактивности на клиенте вuseServerEvents.ts(пинг приходит каждые 25 с).Обнаружено при работе над #47.