🚀 Gen 5 of the leading AI app deployment platform launches October 6. Click for the livestream.

Upload component + Dash 2.0 long callback issue

Hi everyone,
so I’m developing an ML/CV app where users can upload images. As processing those usually takes some time, I was excited to try out dash 2.0’s long callbacks to keep users up to date and show intermediate results while the process is running. Everything worked fine on my local machine, but when I deployed to our network, I faced the issue that the app stopped working when uploading too many or too large files (like ~10MB, depending on network). My observations:

  • Frontend stayed in “running” state forever, though callback seemed to be finished in backend
  • pending _dash-update-component requests piling up in network tab, in the end, my browser went oom
  • Network traffic (upload) goes nuts

Here’s a minimum example: I can reproduce the issue by uploading a file which is large enough (upload taking more than 1s, maybe?), but small enough to be accepted by the server. Isssue appreared in both Chrome and Firefox.

from dash import dcc, html, Dash, Input, State, Output
from dash.long_callback import CeleryLongCallbackManager
from celery import Celery
from time import sleep

celery_app = Celery(
    __name__, broker="redis://localhost:6379/0", backend="redis://localhost:6379/1"
)
long_callback_manager = CeleryLongCallbackManager(celery_app)

app = Dash(__name__, long_callback_manager=long_callback_manager)

app.layout = html.Div([
    dcc.Upload(
        id='upload-data',
        children=html.Div([
            'Drag and Drop or ',
            html.A('Select Files')
        ]),
    ),
    html.Progress(id="progress_bar", style=dict(visibility='hidden')),
])


@app.long_callback(Input('upload-data', 'contents'),
                   State('upload-data', 'filename'),
                   manager=long_callback_manager,
                   prevent_initial_call=True,
                   running=[
                       (
                               Output("progress_bar", "style"),
                               {"visibility": "visible"},
                               {"visibility": "hidden"},
                       ),

                   ])
def update_output(contents, file_names):
    sleep(5)
    return list()


if __name__ == '__main__':
    app.run_server()

Using a normal callback seems to work as expected. Any help is greatly appreciated! :slight_smile:

Hi @viking ,

I’ll try to take a closer look soon, but one thing to try is to increase the polling interval. The default is 1s, but could you try setting it to something like 3s and see if that makes a difference.

It looks like this didn’t make it into the long_callback docstring, but you can set @app.long_callback(..., interval=3000) to increase the polling interval to 3 seconds.

-Jon

Hi Jon, thank you very much for looking into it!
I wasn’t aware that the polling interval can be customized, good hint. Increasing the interval did increase the amount of data / number of images I’m able to upload. The issue still occurs with sufficiently large uploads or bad network connection, however.

1 Like