Skip to content

bare websockets - #6932

Open
benedikt-bartscher wants to merge 38 commits into
reflex-dev:mainfrom
benedikt-bartscher:make-sio-optional
Open

bare websockets#6932
benedikt-bartscher wants to merge 38 commits into
reflex-dev:mainfrom
benedikt-bartscher:make-sio-optional

Conversation

@benedikt-bartscher

@benedikt-bartscher benedikt-bartscher commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

saves ~11.6 KB gz / ~41 KB raw frontend size (a small js chunk replaces whole socketio)
dropped python deps: wsproto, simple-websocket, python-socketio, python-engineio, bidict
new benchmarks in test_event_transport.py show about 2x performance increase compared to socketio

also migrates AppHarness to granian for consistency. otherwise downstream tests using AppHarness still need uvicorn and wsproto/websockets

Review in cubic

@codspeed-hq

codspeed-hq Bot commented Aug 22, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 32 untouched benchmarks
🆕 4 new benchmarks
⏩ 8 skipped benchmarks1

Performance Changes

Benchmark BASE HEAD Efficiency
🆕 test_transport_inbound_socketio N/A 7.9 ms N/A
🆕 test_transport_inbound_websocket N/A 4.4 ms N/A
🆕 test_transport_outbound_socketio N/A 15.4 ms N/A
🆕 test_transport_outbound_websocket N/A 6.7 ms N/A

Comparing benedikt-bartscher:make-sio-optional (5e739cc) with main (c49a85d)

Open in CodSpeed

Footnotes

  1. 8 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@greptile-apps

greptile-apps Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR replaces the default Socket.IO transport with a lightweight plain-WebSocket protocol while retaining Socket.IO as an optional transport.

  • Adds matching browser and ASGI WebSocket implementations with handshake, heartbeat, reconnect, message validation, and token lifecycle handling.
  • Makes Socket.IO and Uvicorn optional dependencies and updates configuration and startup paths accordingly.
  • Migrates AppHarness to Granian and improves dependency-error reporting during cleanup.
  • Fixes streamed-upload event-context isolation and adds transport unit tests and benchmarks.
  • Documents the user-facing transport and dependency changes.

Confidence Score: 5/5

The PR appears safe to merge; no new actionable regressions or outstanding previous findings remain.

The changes since the previous review do not introduce a concrete transport failure, and every previous Greptile thread is resolved and therefore not outstanding.

Important Files Changed

Filename Overview
packages/reflex-base/src/reflex_base/.templates/web/utils/helpers/websocket.js Implements the browser-side plain-WebSocket transport, including framing, heartbeat handling, buffering, and lifecycle cleanup.
packages/reflex-base/src/reflex_base/.templates/web/utils/state.js Selects the configured transport, lazily imports Socket.IO, and safely manages asynchronous connection and unmount cleanup.
reflex/event_namespace.py Implements the server-side plain-WebSocket event protocol and its connection, validation, logging, and token-management behavior.
reflex/socketio_namespace.py Extracts the legacy Socket.IO namespace and ASGI integration behind the optional Socket.IO dependency.
reflex/app.py Configures either the native WebSocket route or optional Socket.IO application according to transport settings.
reflex/testing.py Migrates the test harness backend to Granian and reports a clear optional-dependency error when cleanup lacks psutil.
packages/reflex-base/src/reflex_base/event/processor/event_processor.py Forks the root event context for streaming deltas so unrelated events cannot become children of a completed future.
pyproject.toml Moves Socket.IO and Uvicorn stacks into explicit extras while updating the required Granian version.
tests/units/test_event_namespace.py Adds broad coverage for WebSocket framing, connection validation, event dispatch, rate limiting, and lifecycle behavior.

Reviews (32): Last reviewed commit: "Merge remote-tracking branch 'upstream/m..." | Re-trigger Greptile

Comment thread reflex/event_namespace.py Outdated
Comment thread packages/reflex-base/src/reflex_base/.templates/web/utils/helpers/websocket.js Outdated
@benedikt-bartscher
benedikt-bartscher marked this pull request as ready for review August 22, 2026 22:09
@benedikt-bartscher
benedikt-bartscher requested a review from a team as a code owner August 22, 2026 22:09

@cubic-dev-ai cubic-dev-ai Bot 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.

All reported issues were addressed across 19 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread reflex/event_namespace.py Outdated
Comment thread reflex/event_namespace.py
Comment thread packages/reflex-base/src/reflex_base/.templates/web/utils/helpers/websocket.js Outdated
Comment thread reflex/utils/exec.py Outdated
Comment thread reflex/utils/exec.py Outdated
Comment thread packages/reflex-base/src/reflex_base/.templates/web/utils/state.js Outdated
@benedikt-bartscher
benedikt-bartscher marked this pull request as draft August 22, 2026 22:27
…ace, awaited disconnect cleanup; revert server-wide ws_max_size
Comment thread reflex/event_namespace.py Outdated
@benedikt-bartscher
benedikt-bartscher marked this pull request as ready for review August 22, 2026 22:46

@cubic-dev-ai cubic-dev-ai Bot 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.

All reported issues were addressed across 17 files

Requires human review: Auto-approval blocked because this review re-detected 1 unresolved issue already reported by Cubic.

Re-trigger cubic

Comment thread packages/reflex-base/src/reflex_base/.templates/web/utils/helpers/websocket.js Outdated
Comment thread packages/reflex-base/src/reflex_base/.templates/web/utils/state.js
Comment thread packages/reflex-base/src/reflex_base/.templates/web/utils/helpers/websocket.js Outdated
Comment thread reflex/event_namespace.py Outdated

@cubic-dev-ai cubic-dev-ai Bot 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.

All reported issues were addressed across 4 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/reflex-base/src/reflex_base/.templates/web/utils/state.js
Comment thread reflex/event_namespace.py Outdated
Comment thread reflex/event_namespace.py Outdated

@cubic-dev-ai cubic-dev-ai Bot 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.

All reported issues were addressed across 4 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread reflex/event_namespace.py

@cubic-dev-ai cubic-dev-ai Bot 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.

All reported issues were addressed across 6 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread reflex/testing.py Outdated
Comment thread reflex/utils/exec.py
Comment thread pyproject.toml Outdated

@cubic-dev-ai cubic-dev-ai Bot 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.

All reported issues were addressed across 6 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread reflex/testing.py Outdated
Comment thread tests/units/test_testing.py Outdated

@cubic-dev-ai cubic-dev-ai Bot 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.

All reported issues were addressed across 2 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread tests/units/test_testing.py
Comment thread reflex/testing.py Outdated
Comment thread reflex/event_namespace.py Outdated
Comment thread reflex/event_namespace.py Outdated

@cubic-dev-ai cubic-dev-ai Bot 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.

All reported issues were addressed across 2 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread tests/units/test_event_namespace.py
Comment thread reflex/event_namespace.py Outdated
@abulvenz

Copy link
Copy Markdown
Contributor

I really like this lightweight approach 👍 .
One thing that is dropped, correct me if I see this wrong: under the hood socketio supports HTTP long-polling in case a websocket connection cannot be established (e.g. due to badly configured load balancers, reverse proxies or simply disabled client support). In most cases that should be fixed anyways on server side for performance reasons.

@benedikt-bartscher

Copy link
Copy Markdown
Contributor Author

I really like this lightweight approach 👍 . One thing that is dropped, correct me if I see this wrong: under the hood socketio supports HTTP long-polling in case a websocket connection cannot be established (e.g. due to badly configured load balancers, reverse proxies or simply disabled client support). In most cases that should be fixed anyways on server side for performance reasons.

Thanks 🙏

Yes, the new bare websockets implementation does not support http long-polling yet. However one could still choose the old socketio based transport to archive this. Also iirc longpolling was disabled by default anyway, i guess not a lot of users use it. If this is really needed i could add support to our bare websockets implementation as well.

@benedikt-bartscher

benedikt-bartscher commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

check out #6984

edit: done in 9caa24b

Comment thread reflex/event_namespace.py Outdated
Comment thread reflex/event_namespace.py
Comment thread reflex/event_namespace.py Outdated

@masenf masenf left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

reflex-xy currently uses socketio multiplexing to send binary chart data and interaction payloads over the same reflex websocket, so we can't bring this in directly, yet.

i think there's potential here though. and i like the idea of dependency reduction.

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