Pull requests / #2497

#2497 serve: an engine program that cannot be started is a 503, not a dropped connection

open · @devYRPauli · 0 commentaires · Sur GitHub

Server & APIModels & quantsWindows

Description

## Title
Issue: Resolves #2496

## Summary

A request that starts the engine now gets a 503 with the reason when the engine program cannot be started. Before this change, the client saw a closed connection with no status line. Each failed start also left one start narrator thread running, and the last failed start kept its engine log open.

## What changed

- `serve/server.py`, `StrataEngine.__init__`: when `popen()` raises an `OSError`, the start sets the `loading` event and closes its handle on the engine log. Then it re-raises the same `OSError`, so the startup path keeps its exception type.
- `serve/server.py`, `Service.ensure_loaded`: an `OSError` from `engine.restart()` becomes `EngineDied("the engine could not be started: ...")`. The request path already answers `EngineDied` with a 503. The vision encoder unload on failure is unchanged.
- `serve/test_ready_timeout.py`: new class `SpawnFailure`. A lazy engine with a missing program gets a 503 on chat, messages, responses and a streamed chat. The test also checks that the log handle is closed and that no narrator thread stays alive. The class runs on Windows too, because a missing program fails the same way there.

## Extra Notes

What this PR leaves alone:

- The `/load` route catches only `GpuBusy`, so `EngineDied` and `EngineStuck` still drop its connection. That is a separate change.
- A failed load on `/v1/responses` answers 503 without the "the next request restarts it" suffix. That text comes from the Responses handler, and this PR does not change it.
- #2435 makes the same change for the elastic image encoder. #1563 edits the same `popen()` call, so one of the two PRs needs a rebase after the other merges.

How I checked it:

- The new test fails on main 296b59d2: 4 requests end with `RemoteDisconnected`, and 4 narrator threads stay alive. With the fix, the test passes.
- I reverted each half of the fix on its own. Without the `ensure_loaded` change, the 4 requests drop. Without the `__init__` change, the log handle stays open and the narrator threads stay alive.
- A wider script sent 6 requests for each of 3 causes: a missing program, a file that is not executable, and a simulated WinError 4551 (#735). All 18 requests get a 503 with the reason. The monitor records them as errors, not `disconnected`. No narrator thread and no extra file descriptor remain. A later request succeeds when the program exists again.
- Full serve suite on macOS with Python 3.12.14: 786 tests, 774 pass, 11 skip and 1 fails. `VisionTempFiles.test_work_dir_has_no_space_when_temp_has_one` fails on main too, because my checkout path contains a space.

Sur le site

Liens install, modèles, releases.