router: align SSE to canonical /api/{domain}/events (drop sse.json, derive from x-sse) #121

Merged
mahmoud merged 4 commits from development_router_sse_canonical into development 2026-06-14 16:13:50 +00:00
Owner

Closes #120.

Aligns hero_router's SSE handling to the hero_lib macro/SDK canonical /api/{domain}/events and removes the sse.json divergence. Builds on #118's per-domain spec cache.

What changed

  • Forward verbatim (8dcffe5): the direct HTTP forward no longer renames /api/{domain}/events → socket /api/{domain}/sse.json; it forwards the path as-is (matching hero_lib's own openrpc_proxy/serve_domains).
  • Derive SSE from x-sse (d1dfe88): replaced the blind GET /api/main/sse.json probe with reading each domain's cached OpenRPC x-sse extension (endpoint + filter key). SseDescriptor is now per-domain {channel, domain, endpoint, filter_key}; an entry holds a Vec (one per streaming domain). Removed probe_events/EventsProbe. The multiplexer auto-exposes only firehose channels (no filter key) and streams the real endpoint — filtered per-resource streams (per-job/per-topic) have no global feed and are reached on demand via …/events?<filter>=<value>.
  • Tests (4977424): unit-test sse_descriptors_from_entry with the real x-sse shape (multi-domain filtered/firehose, no-@sse, single-domain Model-B).
  • Carried fix (67e2f48, unrelated to SSE): derive_group_name no longer treats the sockets root as a service group — a pre-existing failing unit test on development (the fix had only landed on integration); included so the suite is green.

Why no service-side change

SSE is per-(domain, method) with a filter — hero_proc is per-job_sid, the demo's dom1 is per-topic, dom2 is a firehose. There is no global proc stream, so a sse.json keepalive stub would entrench a contract hero_lib already dropped. The fix is router-side; no services were changed.

Verification

cargo test -p hero_router143 passed, 0 failed; clippy clean. Verified live against the real hero_demo_server (dom1/dom2 @sse) on development:

  • router-derived descriptors: dom1/api/dom1/events filter=topic; dom2/api/dom2/events no filter
  • GET /hero_demo/api/dom2/events → 200 text/event-stream (verbatim)
  • GET /hero_demo/api/dom1/events?topic=demo → 200 text/event-stream
  • old …/sse.json → 404 (no longer used)
Closes #120. Aligns hero_router's SSE handling to the hero_lib macro/SDK canonical `/api/{domain}/events` and removes the `sse.json` divergence. Builds on #118's per-domain spec cache. ## What changed - **Forward verbatim** (`8dcffe5`): the direct HTTP forward no longer renames `/api/{domain}/events` → socket `/api/{domain}/sse.json`; it forwards the path as-is (matching hero_lib's own `openrpc_proxy`/`serve_domains`). - **Derive SSE from `x-sse`** (`d1dfe88`): replaced the blind `GET /api/main/sse.json` probe with reading each domain's cached OpenRPC `x-sse` extension (endpoint + filter key). `SseDescriptor` is now per-domain `{channel, domain, endpoint, filter_key}`; an entry holds a `Vec` (one per streaming domain). Removed `probe_events`/`EventsProbe`. The multiplexer auto-exposes **only firehose** channels (no filter key) and streams the real endpoint — filtered per-resource streams (per-job/per-topic) have no global feed and are reached on demand via `…/events?<filter>=<value>`. - **Tests** (`4977424`): unit-test `sse_descriptors_from_entry` with the real `x-sse` shape (multi-domain filtered/firehose, no-`@sse`, single-domain Model-B). - **Carried fix** (`67e2f48`, unrelated to SSE): `derive_group_name` no longer treats the `sockets` root as a service group — a pre-existing failing unit test on `development` (the fix had only landed on `integration`); included so the suite is green. ## Why no service-side change SSE is per-(domain, method) with a filter — hero_proc is per-`job_sid`, the demo's dom1 is per-`topic`, dom2 is a firehose. There is no global proc stream, so a `sse.json` keepalive stub would entrench a contract hero_lib already dropped. The fix is router-side; **no services were changed**. ## Verification `cargo test -p hero_router` → **143 passed, 0 failed**; clippy clean. Verified **live against the real `hero_demo_server`** (dom1/dom2 `@sse`) on `development`: - router-derived descriptors: `dom1` → `/api/dom1/events` filter=`topic`; `dom2` → `/api/dom2/events` no filter - `GET /hero_demo/api/dom2/events` → 200 `text/event-stream` (verbatim) - `GET /hero_demo/api/dom1/events?topic=demo` → 200 `text/event-stream` - old `…/sse.json` → 404 (no longer used)
The direct HTTP forward renamed external /api/{domain}/events to socket
/api/{domain}/sse.json — the only HTTP<->socket divergence, and it doesn't match
the hero_lib canonical (serve_domains/openrpc_proxy serve SSE at
/api/{domain}/events verbatim; there is no sse.json). Forward the path as-is so
direct/admin SSE clients hit the real per-domain stream.

Refs #120
Replaces the blind GET /api/main/sse.json probe with deriving SSE channels from
each domain's cached OpenRPC x-sse extension (endpoint + filter key). Canonical
/api/<domain>/events (multi-domain) or /api/events (single-domain Model-B); no
sse.json anywhere.

- SseDescriptor is now per-domain {channel, domain, endpoint, filter_key}; an
  entry holds a Vec (one per streaming domain) instead of Option.
- scanner::sse_descriptors_from_entry builds them from domain_specs/openrpc_json.
- removed probe_events / EventsProbe (no socket probe).
- multiplexer auto-exposes only firehose channels (no filter_key) — filtered
  per-resource streams (per-job/per-topic) have no global feed and are reached
  on demand via .../events?<filter>=<value>; resolve + stream the real endpoint
  instead of bare /events.

Refs #120
/var/sockets/legacy.sock returned parent 'sockets' instead of stem 'legacy'.
Pre-existing failing unit test on development (fix had only landed on
integration); carry it so the suite is green. Unrelated to the SSE work.
test(router): unit-test x-sse SSE derivation (per-domain, filter, single-domain)
All checks were successful
Build & Test / check (pull_request) Successful in 9m44s
4977424f61
Covers scanner::sse_descriptors_from_entry with the real x-sse spec shape and
the single-domain Model-B case. Verified live against the real hero_demo_server.

Refs #120
mahmoud merged commit 78fbd97d7d into development 2026-06-14 16:13:50 +00:00
mahmoud deleted branch development_router_sse_canonical 2026-06-14 16:13:55 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_router!121
No description provided.