Skip to content

improved websocket connection management#3797

Open
T4rk1n wants to merge 7 commits into
devfrom
fix/ws-connection-management
Open

improved websocket connection management#3797
T4rk1n wants to merge 7 commits into
devfrom
fix/ws-connection-management

Conversation

@T4rk1n
Copy link
Copy Markdown
Contributor

@T4rk1n T4rk1n commented May 26, 2026

Fix #3788 and fix #3790

  • Disable/reset inactivity timeout when the app tab is active.
  • Tabbing back restarts the ws connection instead of waiting for a callback.
  • Persistent Callback with no ouputs/inputs that were running while the app disconnected will be restarted automatically.
  • Improved error handling when the websocket disconnect/reconnect.

@T4rk1n T4rk1n assigned camdecoster and unassigned T4rk1n May 28, 2026
@T4rk1n
Copy link
Copy Markdown
Contributor Author

T4rk1n commented May 28, 2026

@camdecoster This is ready for review, I removed the callback adoption that was not working for multi worker production environment.

@sonarqubecloud
Copy link
Copy Markdown

Comment thread dash/backends/_fastapi.py Outdated
Comment thread dash/backends/_fastapi.py Outdated
(acc: any[], cb: any) => {
// Only re-trigger no-output callbacks with no inputs
// These are the "persistent" callbacks that should restart
if (cb.noOutput && cb.inputs.length === 0) {
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.

This checks for persistent callbacks, but why doesn't it look at the persistent flag (from isLoading.ts)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No it's actually just the no Output and no Inputs since those cannot be restarted after startup. Other cases can use reload button or other mechanism.

}

// Handle tab visibility changes
document.addEventListener('visibilitychange', () => {
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.

Is there a situation where you'd need to remove the event listener?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No, it's for the complete page lifecycle.

# Exit gracefully on disconnect
raise PreventUpdate
set_props("progress", {"children": str(i * 10)})
await asyncio.sleep(0.2)
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.

Will this hit the 2s timeout when it makes a new call every 0.2s?

Comment thread CHANGELOG.md
- [#3669](https://github.com/plotly/dash/pull/3669) Selection for DataTable cleared with custom action settings
- [#3680](https://github.com/plotly/dash/pull/3680) Added `search_order` prop to `Dropdown` to allow users to preserve original option order during search
- Added `csrf_token_name` and `csrf_header_name` config options to allow configuring the CSRF cookie and header names. Fixes [#729](https://github.com/plotly/dash/issues/729)
- [#3797](https://github.com/plotly/dash/pull/3797) Improved websocket callback management.
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.

Will the changes in this fix be documented somewhere besides this changelog entry?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

A more comprehensive guide for the websocket shutdown management can be found on the WebsocketCallback docstring and in the .ai/ARCHITECTURE.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants