mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-10-05 23:05:10 +00:00
feat(web): a start that waits for the display answers 202 and is delivered in the background
The start route held a request open for up to 45 s while a cold-started display loaded its plugins; the MQTT bridge (15 s timeout) and browsers reported a failure for a request that was then delivered. Now, when no display is listening, the route starts the service if asked and answers 202 with status "starting" at once. A single worker in the web process (web_interface/on_demand_dispatch.py) sends the request until the display acknowledges it or the wait runs out (45 s cold start, 10 s for a running service without a socket yet). A newer start supersedes the pending one; a stop cancels it (and succeeds, with cancelled_request_id, even with no display listening). The outcome is reported by /display/on-demand/status (source "web": starting, or error with start-timeout or the socket's reason, until the display publishes something newer) and by /display/current-status as on_demand_pending. Callers: the web UI's on-demand modal and "Preview on display" treat "starting" as taken (an info toast); the MQTT bridge already treats any non-error 2xx as success (now pinned by a test). Tests: the dispatcher (ack, retry then ack, start-timeout, other failures, superseded, an in-flight ack for a superseded start, stop while pending, a per-start wait, outcome lifetime); the routes (202, status routes while pending and after a timeout, a later display state replacing the failure, stop while pending, a new start superseding); a JS suite for app.js. Mutation check: 20 mutants on the worker, the routes and app.js, 20 killed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+11
-5
@@ -42,11 +42,17 @@ to for one release are gone.
|
||||
pomodoro-timer still write the mailbox, but only as their fallback when
|
||||
those methods are missing or answer `None`.
|
||||
- **On-demand routes without a listening display.** `POST
|
||||
/api/v3/display/on-demand/start` with the service stopped starts it (when
|
||||
`start_service`, the default) and sends the request once the display's
|
||||
socket answers, waiting up to 45 s (10 s for a service that is running but
|
||||
has no socket yet); otherwise it answers `400` (`start_service` false) or
|
||||
`503` with `socket_error`. Every other socket failure (`unknown_command`
|
||||
/api/v3/display/on-demand/start` with no display listening starts the
|
||||
service (when `start_service`, the default) and answers **`202`** with
|
||||
`status: "starting"` at once; a single background worker in the web
|
||||
process (`web_interface/on_demand_dispatch.py`) sends the request until
|
||||
the display acknowledges it, for up to 45 s (10 s for a service that is
|
||||
running but has no socket yet). `GET /display/on-demand/status` reports it
|
||||
(`starting`, then the display's state, or `error` / `start-timeout`), and
|
||||
`/display/current-status` adds `on_demand_pending`. A newer start replaces
|
||||
a pending one and a stop cancels it (`cancelled_request_id`). The web UI
|
||||
and the MQTT bridge treat `202` as taken. With the service stopped and
|
||||
`start_service` false it answers `400`. Every other socket failure (`unknown_command`
|
||||
from an older display, `disabled`/`unsupported`, `busy`, a timeout) is a
|
||||
`503`. `/stop` answers `503` when no display is listening, unless
|
||||
`stop_service` stops the service. `transport` is always `"socket"`; the
|
||||
|
||||
Reference in New Issue
Block a user