Shared-storage topics are never freed: streaming leaks ~32 frames per page load
Los mantenedores suelen responder en 2 días
@T4rk1n ya está trabajando en esto.
Desde el 24/9/2026.
Evaluación
Este issue todavía no se ha evaluado.
Descripción
Describe the bug
Shared-storage pub/sub topics are never removed. The streaming transport (#3930/#3931) uses one topic per page load (stream_topic(connection_id) in dash/_stream_hub.py), and each topic keeps its last buffer_size (default 32) frames. So every page load that runs a streaming callback leaves its last 32 frames in memory for the life of the process.
With LocalSharedStorage, StoreEngine._topics (dash/_shared_storage/_engine.py) is a plain dict. _topic() adds an entry on first publish, head_seq or poll, and nothing ever deletes one. Pub/sub is not persisted, so the only thing that frees them is the owner process exiting.
Measured
A streaming callback yielding 40 frames of ~50 KB, driven headless with dash_duo: 20 page loads, then the browser navigates away and we wait 40s (past DOWNLINK_GRACE and POLL_GRACE).
- 20
_dash_stream:topics still inengine._topics - 640 frames still buffered (32 per topic)
- heap grew 39.9 MB, about 2 MB per page load
A long-running app streaming figures or LLM output grows without bound.
Other backends
DiskcacheSharedStorage:ss:seq:<topic>/ss:msg:<topic>:<n>are written withoutexpire. Bounded only by the cachesize_limiteviction.RedisSharedStorage: the seq counter and stream keys have no TTL.MAXLENlimits messages per topic, not the number of topics.
App code using ctx.shared_storage.publish/subscribe with per-session or per-run topic names leaks the same way (about 2.4 KB per empty topic on the local engine).
Expected behavior
A topic nobody uses any more is released. Some options:
- Local engine: drop a topic once it has no subscribers or waiters and has been idle past some window.
- Add
delete_topic(topic)toBaseSharedStorageand call it when aDownlinkconnection is finished (the pump already knows when the browser is gone). - A topic
ttl, matchingset(..., ttl=): RedisEXPIRE, diskcacheexpire=, a deadline in the local engine.
Streaming and shared storage are not released yet (4.5.0rc0), so this can be fixed before 4.5.0.
Repro
import asyncio
from dash import Dash, Input, Output, html
app = Dash(__name__)
app.layout = html.Div([html.Button("go", id="btn"), html.Div(id="out")])
@app.callback(Output("out", "children"), Input("btn", "n_clicks"),
prevent_initial_call=True)
async def cb(n):
for i in range(40):
await asyncio.sleep(0.01)
yield "x" * 50_000 + f"-{i}"
yield "done"
Load the page and click the button N times across reloads, then inspect app.shared_storage._coord.engine._topics: one _dash_stream:<connection_id> entry per page load, each holding 32 frames, long after the browser left.
- Lenguaje dominante
- Python
- Estrellas
- 24.4k
- Forks
- 2.3k
- Merge medio
- 1 d 20 h
- PR fusionados (30 d)
- 21
Preparar el entorno
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de plotly/dash
-
good first issue P3 size: 1 task
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
plotly/dash#3735 · 3 comentarios ·
Los mantenedores suelen responder en 2 días
-
bug P2 plotly-internal size: 3
Dificultad 4/5 3-5 días Aptitud para principiantes 48/100
plotly/dash#4013 · 1 comentario ·
Los mantenedores suelen responder en 2 días
-
bug P3 size: 1
Dificultad 4/5 3-5 días Aptitud para principiantes 68/100
plotly/dash#4011 · 1 comentario ·
Los mantenedores suelen responder en 2 días
-
[BUG] disable autocomplete in the date pickers inputPosiblemente ocupada @AnnMarieW la tomó hace 4 días. Abiertobug P2 size: 1
plotly/dash#4009 · 1 comentario · 1 asignado ·
Los mantenedores suelen responder en 2 días
-
[BUG] Plotly Cloud devtool route crashes with FastAPI and Quart backendsPosiblemente ocupada @T4rk1n la tomó hace 4 días. Abiertobug P1 size: 1
Dificultad 3/5 1-2 días Aptitud para principiantes 65/100
plotly/dash#4008 · 1 comentario · 1 asignado ·
Los mantenedores suelen responder en 2 días
Todos los issues de plotly/dash
Issues similares
-
[Bug] @deck.gl/arcgis dist import resolves to unpublished @deck.gl/core source path (9.3.11, 9.4.0)Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
Los mantenedores suelen responder en 1 día
-
workflow: a tick's dispatch counts as 'only this step', and no review self-grants a round unattendedAbiertoworkflow
Dificultad 2/5 1-3 horas Aptitud para principiantes 85/100
kristofdegrave/homeassistant-smart-charging#1505 ·
Los mantenedores suelen responder en 1 día
-
New Submission: TropWATERAbiertometadata submission
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
-
Wrongly named dashboard variableAbiertobug
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
canonical/content-cache-operator#163 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
[submission]Abiertosubmission
Dificultad 1/5 Menos de una hora Aptitud para principiantes 65/100
leanprover/lean-eval-submissions#1852 ·
Los mantenedores suelen responder en 1 día