Skip to content

Fix multiple debug messages - #45

Open
cdenig wants to merge 18 commits into
feature/add-inline-helpfrom
fix-multiple-debug-messages
Open

cdenig wants to merge 18 commits into
feature/add-inline-helpfrom
fix-multiple-debug-messages

Conversation

@cdenig

@cdenig cdenig commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

This pull request introduces several improvements and fixes related to WebSocket connection handling, testing, and code quality for the application. The main focus is on making the WebSocket middleware more robust against race conditions, improving test coverage, and adding development tooling. Below are the most important changes:

WebSocket Middleware Robustness and Reliability:

  • Refactored websocketMiddleware to ensure only the latest WebSocket instance can dispatch actions, preventing race conditions and stale event handlers from interfering with the current connection. Added a closeSocket helper to clean up handlers before closing, and improved fallback handling logic. (src/store/websocketMiddleware.ts) [1] [2] [3] [4]

  • Updated the session join logic in App.tsx to prevent multiple simultaneous session requests using a useRef guard, ensuring only one join attempt is in flight at a time. (src/App.tsx)

Testing Improvements:

  • Added comprehensive tests for the WebSocket middleware, including connection deduplication, fallback logic, and disconnection, using a FakeWebSocket stand-in and Vitest. (src/store/websocketMiddleware.test.ts)

  • Updated the main app test to use Redux and React Router providers, and added a test for rendering the help page. (src/App.test.tsx)

Development Tooling:

  • Added eslint as a development dependency to enforce code quality. (package.json)

Repository Configuration:

  • Added a .gitattributes file to enforce consistent LF line endings across the repository. (.gitattributes)

Closes #44

cdenig and others added 6 commits September 23, 2026 11:44
The repository already stores all text files with LF; this keeps
Windows editors and tooling from committing CRLF.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…sages

Detach handlers before closing a socket and ignore events from any
socket that is no longer current, so a replaced connection can't keep
dispatching messages, clobber the active socket, or trigger a spurious
fallback. WS_DISCONNECT now also dispatches disconnected() since the
detached onclose no longer does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nding

Rapid clicks on Join started multiple debug sessions and sockets,
producing duplicate console messages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The server already returns the URL reachable from the browser's side of
the network, so connect to `url` first and use `fallbackUrl` only as the
fallback instead of swapping them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Referenced by .vscode/settings.json and the README; no lint config or
script yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cdenig
cdenig requested review from ndorin and a lite review from Copilot September 23, 2026 16:07
@cdenig cdenig self-assigned this Sep 23, 2026

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.

Copilot review overview

🟡 Changes recommended

WebSocket connection state and session-join behavior have unresolved issues, with missing regression coverage.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 Medium severity · 1 Low severity

Open (2)
What changed in this PR

Improves WebSocket lifecycle handling, prevents duplicate session joins, expands tests, and adds repository tooling.

Changes:

  • Adds stale-socket cleanup and connection guards.
  • Expands middleware and app tests.
  • Adds ESLint dependency and LF line-ending configuration.
File Summary
src/​store/​websocketMiddleware.ts Hardens WebSocket lifecycle and stale-event handling.
src/​store/​websocketMiddleware.test.ts Adds middleware connection and fallback tests.
src/​App.tsx Guards concurrent session joins.
src/​App.test.tsx Updates providers and adds help-page coverage.
package.json Adds ESLint dependency.
package-lock.json Locks dependency updates.
.gitattributes Enforces LF line endings.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/store/websocketMiddleware.test.ts Outdated
Comment thread package.json
@cdenig

cdenig commented Sep 23, 2026

Copy link
Copy Markdown
Contributor Author

hey @ndorin could you please have look at this PR when you have a moment? I ran into this issue when using Debug Console testing a client mock system for Essentials v3 platform.

@ndorin

ndorin commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

@cdenig do you have a minute to address the copilot comments and then I'll review?

@cdenig

cdenig commented Sep 23, 2026 via email

Copy link
Copy Markdown
Contributor Author

cdenig and others added 9 commits September 23, 2026 14:13
- eslint.config.js: @eslint/js + typescript-eslint recommended, React
  hooks, Vite react-refresh, plus type-aware no-floating-promises and
  no-misused-promises; eslint-config-prettier last to avoid conflicts
- Rename prettierrc.json to .prettierrc.json so Prettier finds it, and
  add .prettierignore
- Add lint, lint:fix, format and format:check scripts

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
No functional changes; generated by `npm run format`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GitHub applies .git-blame-ignore-revs automatically; locally run
`git config blame.ignoreRevsFile .git-blame-ignore-revs`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Log failures from join() instead of leaving an unhandled rejection
  when starting a debug session fails
- Mark fire-and-forget RTK Query triggers, refetch() and navigate() with
  `void` (their promises don't reject without unwrap())
- Wrap async click/submit handlers so React gets a void callback
- Replace `any` with `unknown` or a narrow type for the legacy monaco
  languages.json API; String -> string in LogMessage
- Remove unused getAppIdFromPath; rename icons/index.tsx to .ts since it
  holds no components

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Drop legacy eslint.options.extensions (removed in ESLint 10), the
  prettier/prettier rule customization, html validation and the
  deprecated eslint.alwaysShowStatus; the default eslint.validate also
  covers .tsx, which the old list missed
- Use Prettier as the default formatter and format on save
- Recommend the ESLint and Prettier extensions
- Document the lint and format scripts in the README

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ESLint 10, jsdom 29 and Vite 8 require Node ^20.19.0 || ^22.13.0 || >=24,
so Node 18 is no longer supported. Update the README prerequisite and
declare the range in package.json engines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

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.

Copilot review overview

🟡 Changes recommended

Unresolved moderate findings remain in session guarding, stale-socket test coverage, and reconnect state handling.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 3 Medium severity

Open (3)
Resolved since last review (1)

Comment thread src/App.tsx Outdated
Comment thread src/store/websocketMiddleware.ts
Replace the join ref, which was released before the WebSocket opened,
with an isConnecting flag in the websocket slice. It is set when a join
begins and cleared when the socket opens, fails, or disconnects, and the
Start button is disabled while it is set.

Dispatch disconnected() when replacing a socket, since its detached
onclose no longer reports it, so a failed reconnect can't leave
isConnected stuck at true.

Exercise the stale socket's captured handlers in the middleware tests
and cover reconnect failure and the isConnecting lifecycle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

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.

Copilot review overview

🟡 Changes recommended

Unresolved critical stale-session handling and moderate connection-state failure findings remain.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 High severity

Open (1)
Resolved since last review (3)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Clear connection state when fallback connection fails

src/​store/​websocketSlice.ts:45

When an already-open primary socket errors, this branch closes it and tries the fallback without dispatching disconnected(). If the fallback then errors, connectionFailed only clears isConnecting, so isConnected remains true and the UI reports a connected session even though socket is gone; clear isConnected when recording a connection failure and add a regression test for this sequence.

Comment thread src/App.tsx
Co-authored-by: cdenig <86131648+cdenig@users.noreply.github.com>

Copilot AI commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

Copilot review overview...

Addressed in f26a904. Stale start-session responses are now ignored after app navigation, route changes clear the active debug-session connection state, terminal websocket failures clear isConnected, and the added regressions cover both stale responses and fallback failure handling.

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.

Copilot review overview

🟡 Changes recommended

Critical compile/lint failures and unresolved WebSocket/session cleanup issues remain.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 2 High severity · 3 Medium severity

Open (5)
Resolved since last review (1)

Comment thread eslint.config.js Outdated
Comment thread src/App.tsx
function App() {
const dispatch = useDispatch<AppDispatch>();
const isConnected = useSelector((state: RootState) => state.websocket.isConnected);
const store = useStore<RootState>();
Comment thread src/App.tsx
}

joinRequestIdRef.current += 1;
dispatch({ type: WS_DISCONNECT });
Comment thread src/App.tsx
dispatch({ type: WS_DISCONNECT });
if (!appId) return;
stopSession({ appId });
void stopSession({ appId });
Comment on lines +64 to 65
closeSocket();
connectToUrl(fallback);
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
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.

4 participants