Skip to content

feat: read the debug console and routing feedback over HTTP polling on VC-4 - #56

Merged
ndorin merged 11 commits into
mainfrom
feature/http-polling-streams
Oct 22, 2026
Merged

ndorin merged 11 commits into
mainfrom
feature/http-polling-streams

Conversation

@ndorin

@ndorin ndorin commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #55 (it uses apiUrl and the host layout from there). Needs PepperDash/Essentials#1536.

Why

On Virtual Control the debug console and routing feedback WebSockets listen on ports the server's firewall blocks, so they needed a firewall rule for 65335–65534 plus a certificate acceptance for each port. Essentials#1536 adds HTTP long-polling routes for both streams. On VC-4, this PR switches the app to those routes, so both work over the same HTTPS port as everything else.

What

  • src/store/messagePoller.ts: a long-poll loop over .../messages.
    • Without since, the first request starts the session; after that it requests ?since=<next>&wait=5000.
    • It pauses 250 ms after a response that had messages, so a busy log isn't fetched nonstop.
    • On failure it retries every 2 s and gives up after 5 failures in a row.
    • restartOnMissed starts a new session when the server reports a gap. Routing uses this to get a fresh snapshot.
  • websocketMiddleware and routingFeedbackMiddleware: WS_CONNECT and ROUTING_WS_CONNECT now also accept { pollUrl }. Each message is handed to the same parsing as a WebSocket message, so the slices are unchanged.
  • streamsUseHttpPolling() in hostPaths: true on VC-4. When it's true:
    • App.join skips the WebSocket session request and polls debugSession/messages. Stop still calls POST debugSession, which ends the polling session.
    • The routing page polls routingFeedbackSession/messages.
  • Processors keep using the WebSockets, unchanged.
  • Docs:
    • The VC-4 guide now only needs the Mobile Control port opened, explains how the streams connect, and says how to remove the old WebSocket port rule.
    • The two polling routes are added to the API reference.

Testing

  • New messagePoller.test.ts, plus polling cases in both middleware tests and in hostPaths.test.ts. All 304 tests pass, and lint, Prettier and npm run build are clean.
  • VC-4 (bosd-vc401, room DEMOV3), with this build packaged in an Essentials build that includes #1532 and #1536:
    • The Debug Console joins and streams.
    • The routing page goes live.
    • There's no certificate prompt for either.
  • Processors: the WebSocket path is covered by the existing middleware tests. It wasn't rechecked in a browser on a processor with this build.

🤖 Generated with Claude Code

ndorin and others added 2 commits October 22, 2026 14:37
…n VC-4

On Virtual Control the debug and routing WebSockets listen on ports the server's firewall blocks.
There, both streams now long-poll the new debugSession/messages and
routingFeedbackSession/messages routes over the same HTTPS port as every other API call, so no
firewall rules or per-port certificate steps are needed. Appliances keep using the WebSockets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Debug Console and routing poll over HTTPS on VC-4, so the WebSocket port range and the
per-port certificate step are gone from the guide. Document the two polling routes in the API
reference.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ndorin
ndorin added this pull request to stack #57 October 22, 2026 21:05
Copilot AI balanced review requested due to automatic review settings October 22, 2026 21:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Successful gap responses do not reset the failure counter, which can stop routing polling prematurely during snapshot recovery.

1 open issue
What changed in this PR

Adds HTTP long-polling for the Debug Console and live routing on VC-4, avoiding extra WebSocket firewall ports and certificate prompts. Builds on the VC-4 host-path support and requires the polling endpoints in Essentials#1536.

Changes:

  • Adds a shared poller with cursor tracking, retries, cancellation, and snapshot recovery.
  • Selects HTTP polling on VC-4 while preserving WebSockets on processors.
  • Adds polling tests and updates API and deployment documentation.
File Description
src/​store/​websocketSlice.ts Allows polling URLs in debug connection actions.
src/​store/​websocketMiddleware.ts Integrates polling with debug message handling.
src/​store/​websocketMiddleware.test.ts Tests debug polling and cancellation.
src/​store/​routingFeedbackSlice.ts Allows polling URLs in routing connection actions.
src/​store/​routingFeedbackMiddleware.ts Integrates routing polling and snapshot recovery.
src/​store/​routingFeedbackMiddleware.test.ts Tests routing polling and cancellation.
src/​store/​messagePoller.ts Implements the shared long-polling lifecycle.
src/​store/​messagePoller.test.ts Tests cursors, retries, gap recovery, and stopping.
src/​shared/​functions/​hostPaths.ts Selects polling for VC-4 hosts.
src/​shared/​functions/​hostPaths.test.ts Tests host-specific transport selection.
src/​features/​Routing.tsx Starts routing polling on VC-4.
src/​App.tsx Starts debug polling on VC-4.
docs/​reference/​api-endpoints.md Documents both polling endpoints.
docs/​README.md Updates the VC-4 connectivity overview.
docs/​how-to/​use-dev-tools-on-vc4.md Explains polling requirements and firewall setup.
docs/​how-to/​troubleshoot-connection.md Updates VC-4 connection troubleshooting.
docs/​how-to/​README.md Updates the guide’s firewall learning objective.

Review effort: Balanced

Comment thread src/store/messagePoller.ts Resolved
ndorin and others added 3 commits October 22, 2026 16:26
- Top nav folds behind a toggle below 1200px, keeping the app selector and connection light in
  view, and closes after a page is picked. Brand shortens to "Dev Tools" on phones.
- Devices: on a phone, the list takes the whole width; picking a device shows its detail with a
  way back. Can Read/Can Write columns hide on phones and long values wrap.
- Debug Console: toolbar wraps by control, device filters show on phones (they were hidden below
  lg), and each log row stacks timestamp/key/level over the message.
- Help: sidebar folds behind a Contents button on phones; page gets padding (it sits outside the
  main layout).
- API Paths: the table now scrolls (it couldn't on any screen) and long names wrap.
- Plugin Load Issues and Secrets scroll as a whole page on phones; category folds under the
  message, date columns hide, row actions wrap.
- Routing: toolbar wraps by control; the minimap hides on phones.
- Config viewer: no minimap and word wrap on phones, via a small useIsNarrowScreen hook.
- Drawers take the full width on phones; the root uses 100dvh so phone browser toolbars don't
  hide the bottom of the page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e/http-polling-streams

# Conflicts:
#	src/App.tsx
A successful response with missed: true skipped the reset, so with routing's restartOnMissed,
four failures, a gap and one failed snapshot request used up the five-failure budget and stopped
polling though the failures weren't consecutive.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 22, 2026 22:45
…to feature/mobile-responsive

# Conflicts:
#	src/features/Help/Help.test.tsx

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No unresolved blocking issues remain in the polling integration, recovery, cancellation, or retained processor WebSocket behavior.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

feat: make Dev Tools usable on a phone in portrait
Copilot AI balanced review requested due to automatic review settings October 22, 2026 22:53
@ndorin
ndorin requested a review from jonnyarndt October 22, 2026 22:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The expanded navigation can clip lower links on short viewports because it lacks a height constraint and scrolling.

1 open issue

Review effort: Balanced

Comment thread src/features/TopNav.tsx Resolved
Below xl the expanded menu stacks every link and the version block, which on a landscape phone is
taller than the screen. MainLayout clips its column, so Help and the links near it couldn't be
reached. The nav now takes up to the full height and scrolls, with the header row (brand, app
selector, connection light, toggle) pinned above the links so the toggle stays in reach even when
that row wraps. xl and up are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 22, 2026 23:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Responsive navigation can clip application choices and reopen menus on Back navigation, obscuring the returned page.

1 open issue
2 previously missed issues

In code that hasn't changed since last review

Medium severity Clear Contents state when navigating between help articles

src/​features/​Help/​Help.tsx:17

On a phone, open Contents on article A, select article B, then press Back. contentsOpenedOn still contains A, so showContents becomes true again and the restored article is hidden by d-none. Clear the stored opening pathname when leaving the article so returning through browser history shows the article rather than reopening Contents. Add this sequence to the Help tests.

Medium severity Clear collapsed menu state when navigating away

src/​features/​TopNav.tsx:65

Open the collapsed menu on /app01/console, choose Devices, then press Back. openedOn still contains the console pathname, so the menu reopens without another toggle; on short screens it can obscure the restored page. Clear the stored opening pathname when navigation leaves it, and add a regression test for the open → navigate → Back sequence.

1 resolved since last review

Review effort: Balanced

Comment thread src/styles.scss Resolved
jonnyarndt
jonnyarndt previously approved these changes Oct 22, 2026
Base automatically changed from feature/vc4-support to main October 22, 2026 23:29
@ndorin
ndorin dismissed jonnyarndt’s stale review October 22, 2026 23:29

The merge-base changed after approval.

- The nav scrolled below xl even with the menu closed, which clipped the app selector's list so
  app slots couldn't be switched on a phone or tablet. It now scrolls only while the menu is open,
  and the list uses fixed positioning so a scrolling nav can't clip it.
- The nav menu and Help's Contents remembered the page they were opened on, so Back to that page
  reopened them. Both now close on every navigation, by resetting their state during render when
  the path changes.
- The nav toggle now reports aria-expanded, which React-Bootstrap's toggle doesn't.

Tests cover open → navigate → Back for both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 22, 2026 23:34
@ndorin

ndorin commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

Fixed the two "previously missed" issues from the latest review in c5ba700:

  • Back reopened the menu. TopNav and Help remembered the page they were opened on, so Back to that page reopened them. Both now keep { open, path } and reset it during render whenever the path changes. That's React's alternative to an effect, so the menu closes on every navigation, Back included.
  • New tests: open → navigate → Back for the nav menu (the new TopNav.test.tsx) and for Help's Contents. Both fail against the old code.
  • Toggle state: the nav toggle now sets aria-expanded. React-Bootstrap's toggle didn't, so screen readers couldn't tell whether the menu was open.

All 337 tests pass, and lint, Prettier and the build are clean.

🤖 Generated with Claude Code

@ndorin
ndorin requested a review from jonnyarndt October 22, 2026 23:37
@ndorin
ndorin merged commit a7eba7d into main Oct 22, 2026
2 checks passed
@ndorin
ndorin deleted the feature/http-polling-streams branch October 22, 2026 23:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

An unresolved mobile overflow regression and the combined transport and responsive-layout scope warrant final human integration and visual review.

No open issues 🎉

1 previously missed issue

In code that hasn't changed since last review

Medium severity Preserve horizontal scrolling for wide tables

src/​styles.scss:930

Below md, the Secrets and Plugin Load Issues pages retain overflow-x: hidden from their outer overflow-hidden class: this rule overrides only the vertical axis. The rule below also removes scrolling from the inner pane. When a table exceeds the viewport width—for example, a secret description contains a long unbroken string—its right-hand actions are clipped and cannot be reached by horizontal scrolling. Previously, the inner overflow-auto pane allowed this. Set overflow: auto on the outer scroller to preserve access to wide content while keeping whole-page vertical scrolling.

1 resolved since last review

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings October 22, 2026 23:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Same-page selections leave the mobile navigation and Help Contents open, obscuring the selected content.

2 open issues

Review effort: Balanced

Comment on lines +18 to +20
if (contents.path !== pathname) {
setContents({ open: false, path: pathname });
}
Comment thread src/features/TopNav.tsx
Comment on lines +61 to +74
// Below the xl breakpoint the links fold behind a toggle. The links are router NavLinks rather
// than Nav.Links, so collapseOnSelect doesn't close it. Close it on every navigation instead,
// including Back to the page it was opened on, by resetting the state during render when the
// path changes (React's alternative to an effect for this).
const [menu, setMenu] = useState({
expanded: false,
path: location.pathname,
});
if (menu.path !== location.pathname) {
setMenu({ expanded: false, path: location.pathname });
}
const expanded = menu.expanded && menu.path === location.pathname;
const setExpanded = (open: boolean) =>
setMenu({ expanded: open, path: location.pathname });
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants