Skip to content

Conversation

@ibetitsmike
Copy link
Contributor

Summary

Terminal input was causing keystroke reordering under fast typing (e.g., ls↵ becoming l↵s).

Root Cause

The IPC communication used ipcRenderer.invoke() which waits for a response before allowing the next input to be sent. This request-response pattern creates artificial latency:

Keystroke 1 → invoke → wait → response
                              Keystroke 2 → invoke → wait → response

With fast typing, keystroke 2 could arrive while keystroke 1 was waiting for its response, leading to reordering.

Solution

Replace request-response (invoke/handle) with fire-and-forget (send/on):

Component Before After
Electron (preload.ts) ipcRenderer.invoke() ipcRenderer.send()
Main process ipcMain.handle() ipcMain.on()
Browser mode (api.ts) invokeIPC() (awaited) sendIPCFireAndForget()

The fire-and-forget pattern is safe here because:

  1. Terminal input doesn't return meaningful data
  2. Errors are logged server-side but don't need UI handling
  3. Message ordering is preserved by the underlying transport

Fixes: #795


Generated with mux

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Terminal input was using ipcRenderer.invoke() which waits for a
response before processing the next keystroke. This caused keystroke
reordering under fast typing (e.g., 'ls↵' becoming 'l↵s').

Fix:
- Electron: Use ipcRenderer.send() instead of invoke()
- Browser: Add sendIPCFireAndForget() helper that doesn't await response
- Main process: Use ipcMain.on() instead of handle() for terminal input

The fire-and-forget pattern is appropriate since:
1. Terminal input doesn't return meaningful data
2. Errors are logged server-side but don't need to propagate
3. Order preservation is guaranteed by IPC channel ordering

Fixes: #795

_Generated with `mux`_
@ibetitsmike ibetitsmike force-pushed the improve-terminal-speed branch from 7c2e304 to b5f73b7 Compare December 1, 2025 09:14
Copy link
Member

@mafredri mafredri left a comment

Choose a reason for hiding this comment

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

It's been a long time since I worked with Electron, and I haven't tried to read the code beyond the diff. I'm just wondering if this will actually solve the issue?

Am I misunderstanding or will this still result in multiple concurrent HTTP requests, in which case they would still arrive out of order?

To me it'd make sense to only ever have one outbound post, or to number them.

  1. One outbound request -> buffer input, flush buffer once previous request is done
  2. Add number, and detect gaps on receiving side, wait until gap is filled before resuming

Message ordering is preserved by the underlying transport

Is this guarantee actually true?

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.

Terminal input lag causes keystroke reordering

2 participants