exlab_wizard.tray.server_runner#
Programmatic uvicorn launcher with atomic server.json writes. Backend Spec §4.3.2.
The tray process owns the FastAPI server in-process. ServerRunner
encapsulates the lifecycle:
Pick a free localhost port from the OS at start time (Backend §15.3.1).
Launch
uvicorn.Server.runon a dedicated worker thread so the pystray main-thread event loop is unaffected.Atomically write
<state_dir>/server.jsonwith{port, pid, started_at}soexlab_wizard.window(a separate process) can discover the live server (Backend §4.2 – “Window<->server discovery”).On stop, signal uvicorn to exit and delete the state file.
The atomic write follows the §4.4.5 idiom (write tmp, fsync, replace) so a crash during the write never leaves a half-written state file behind that the window subprocess could try to parse.
Functions
Return a free localhost port from the OS. |
Classes
|
Starts uvicorn on a free localhost port and tracks its state file. |
- class exlab_wizard.tray.server_runner.ServerRunner(*, app, state_dir)[source]#
Bases:
objectStarts uvicorn on a free localhost port and tracks its state file.
Backend Spec §4.3.2 + §15.3.1.
- property port: int#
Return the port the server is bound to.
Raises
RuntimeErrorwhen called beforestart().
- exlab_wizard.tray.server_runner.pick_free_port()[source]#
Return a free localhost port from the OS.
Binds a SOCK_STREAM socket to
("127.0.0.1", 0)and reads the OS-assigned port back, then closes the socket. Subject to the usual tiny race between close and re-bind by uvicorn – acceptable in practice; the alternative is leaking the socket which uvicorn cannot accept ownership of.- Return type: