Skip to content

Commit c1938c7

Browse files
committed
Review P2-T4: broker unavailable error
1 parent 1be48a8 commit c1938c7

1 file changed

Lines changed: 82 additions & 0 deletions

File tree

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
## REVIEW REPORT — P2-T4: Broker unavailability JSON-RPC error
2+
3+
**Scope:** origin/main..HEAD
4+
**Files:** 3 changed (proxy.py, test_broker_proxy.py, test_broker_stubs.py)
5+
**Date:** 2026-03-01
6+
7+
### Summary Verdict
8+
- [ ] Approve
9+
- [x] Approve with comments
10+
- [ ] Request changes
11+
- [ ] Block
12+
13+
---
14+
15+
### Critical Issues
16+
17+
None.
18+
19+
---
20+
21+
### Secondary Issues
22+
23+
**[Low] `except Exception` is broad in `run()`**
24+
25+
The connect-phase catch uses `except Exception`, which captures all non-`BaseException`
26+
exceptions including unexpected ones (e.g., `MemoryError` is not an issue, but e.g., a
27+
programming error in `_spawn_broker_if_needed` that raises `AttributeError` would be silently
28+
swallowed). The guard prevents the client from hanging, so the trade-off is acceptable, but a
29+
future refinement could narrow the catch to `(TimeoutError, OSError)` — the only exception
30+
types that legitimately arise from the connect path.
31+
32+
**Suggested fix (optional):** Narrow to `except (TimeoutError, OSError)` with a fallback
33+
`logger.exception` for anything else. Not a blocker; the current behaviour is safe.
34+
35+
**[Low] `id: null` in error response may confuse some clients**
36+
37+
JSON-RPC 2.0 §5 permits `null` for error responses when the request id is unknown. However,
38+
some strict clients may log a warning or discard the response entirely if they cannot match it
39+
to an outstanding request. Consider a future enhancement to read the pending request's `id`
40+
from stdin with a short timeout (e.g., 0.5s) and use it in the error response. Not a blocker
41+
for current acceptance criteria.
42+
43+
---
44+
45+
### Architectural Notes
46+
47+
- The `_send_broker_error` method is a clean, focused helper: <30 lines, single responsibility,
48+
reused for both spawn and connect failure paths.
49+
- The inner guard in `_send_broker_error` (catching `_make_stdout_writer()` failure) is the
50+
right defensive posture — in non-pipe test environments the writer setup fails, and the guard
51+
ensures the error path doesn't itself raise.
52+
- Existing tests that previously expected `run()` to raise `TimeoutError` have been correctly
53+
updated to verify the JSON-RPC error payload instead. The intent of those tests is preserved.
54+
55+
---
56+
57+
### Tests
58+
59+
- Added `TestBrokerProxyUnavailableError` (5 tests):
60+
- `test_connect_timeout_sends_jsonrpc_error` — full payload verification
61+
- `test_error_code_is_minus_32001` — code field check
62+
- `test_error_message_includes_reason` — prefix + exception text
63+
- `test_run_does_not_raise_on_connect_failure` — clean return
64+
- `test_spawn_failure_sends_jsonrpc_error` — spawn-phase error path
65+
- Updated 2 existing tests (`test_broker_proxy.py` and `test_broker_stubs.py`) that previously
66+
expected `run()` to raise; now they verify the JSON-RPC error payload.
67+
- Coverage: 91.59% (≥ 90% required). ✅
68+
- All 732 tests pass, 5 skipped. ✅
69+
70+
---
71+
72+
### Next Steps
73+
74+
- **Optional FU:** Narrow `except Exception` to `(TimeoutError, OSError)` in `run()` for
75+
tighter exception scope. Low priority — current behaviour is safe and correct.
76+
- **Optional FU:** Attempt to read the pending request's `id` from stdin with a short timeout,
77+
to use a real request id in the error response instead of `null`. Improves client
78+
compatibility. Low priority — JSON-RPC 2.0 permits `null`.
79+
- No documentation changes required (this is an internal error-handling improvement with no
80+
user-visible configuration surface).
81+
82+
**VERDICT: PASS — no blockers; two low-severity observations documented above.**

0 commit comments

Comments
 (0)