fix requests queued while the arm is down never being answered

_run_control never drained the job queue while the arm had not been reached, so
every request that arrived during an outage waited for a connection that might
never come. That breaks the one-response-per-request rule the node states as
absolute, and it was circular: requests are queued before the arm is reached
because recover is what a caller sends then, yet recover is served by the
control thread and so was the one service that could never run while down.

Serve the queue during the wait between connection attempts. Non-motion services
are tried on the arm, which is what lets recover and clear reach a controller
that answers while refusing to serve. A motion is refused rather than held: the
arm is somewhere unknown and nobody is watching, so a held motion would fire
unattended the moment the link came back.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 12:32:31 -05:00
co-authored by Claude Opus 5
parent 608e22078e
commit 4427da9c34
4 changed files with 104 additions and 5 deletions
+6 -1
View File
@@ -85,7 +85,12 @@ while it runs. So:
dataflow, and so the arm can be told whether this is a restart.
- **`dora_ulite6/control.py`** — `Control`: both arm threads and the mailboxes the loop
drains. The **control thread** runs one job at a time and is allowed to block: startup,
the `INIT_MODE` move, and every service including the motions that take seconds. The
the `INIT_MODE` move, and every service including the motions that take seconds. Its
wait between connection attempts serves the queue (`_serve_while_down`) rather than
sleeping through it: a request is answered exactly once whatever the arm is doing, and
an arm that is down is an outcome to report, not a reason to go quiet. A motion is
refused there rather than held, since a held one would fire unattended the moment the
link came back. The
**reporter thread** never blocks: it reads the report cache at the telemetry cadence,
so `tcp_pose` keeps flowing right through a move. **Nothing outside this file may call
the driver**, except `stop` and `read_report`, both written for another thread. Same