šŸ“£ Dash Labs 0.3.0: @app.long_callback support

Wow, this is amazing! I canā€™t wait to try it out :smiley:

Amazing stuff!

I love the idea of being able to update a value whilst the function is executing like the progress does. It would be awesome to be able to update more than just a pair of (current iteration, total iterations). For instance Iā€™d love to be able to write:

@app.long_callback(
    ...,
    progress=dict(
        progress1=dl.Output("component1", "attribute1"),
        progress2=dl.Output("component2", ("attribute1", "attribute2"))
    )
)
def my_function(set_progress, *args, **kwargs):
    # Do something
    set_progress({"progress1": ..., "progress2": ...})
    # Do some more stuff
    set_progress({"progress1": ..., "progress2": ...})
   # And some more
    return ...

Is that technically feasible or are there constraints to what can be update while the callback is running?

EDIT: the idea would be for instance to edit a notification message of where the long callback is at.

Thanks for taking a look @RenaudLN.

Yeah, thatā€™s a really good idea. it should be possible to loosen the tuple restriction and basically just pass through whatever set_progress is called with and match it against the dependency grouping provided to the progress argument. I opened long_callback: Make `set_progress` arguments more flexible Ā· Issue #27 Ā· plotly/dash-labs Ā· GitHub to track it.

-Jon

This looks great. Is there any plan to allow the object that the long callback returns remain on the server?
ie like Emilā€™s Server Side Cache:
show-and-tell-server-side-caching

At least for my use-case if I have a long-running callback its usually because I am processing a lot of data that i then want to access later (without having to perform the long process again). I usually donā€™t want to send all that data back to the browser, just filtered view of it.
Thanks!

Hi @jmmease,

Thanks for your information. Itā€™s amazing! :smiley:

Could I ask two more questions:

  1. Does @app.long_callback support normal dash input/output/state? Like:
  1. Does normal dash input/output/state can use together with dl.Output/dl.Input? Like:

Thanks and best regards,

1 Like

I modified the long callback to accept any dependency mapping for the progress part, hereā€™s an example of what it could look like. Could do a PR if that helps :slight_smile:

long_callback_arbitrary_output

7 Likes

Arbitrary dependency support is not available in version 0.4.0. See šŸ“£ Dash Labs 0.4.0: @long_callback caching and Windows support.

1 Like

We really like the ServersideInput/ServersideOutput paradigm that @Emil came up with, and we would like to pull something along these lines into Dash eventually, but it probably wonā€™t be for Dash 2.0.

If/when we get to that point, the idea is that long_callback could output intermediary results to ServersideOutput dependencies to combine the background computation and intermediary result caching features.
-Jon

Hi, I couldnā€™t find the answer anywhere so I did some experimenting and the following works:

@app.long_callback(
    output=dl.Output("paragraph_id", "children"),
    args=(
        dl.Input("button_id", "n_clicks"),
        dl.State("button_id", "n_clicks_timestamp"),
    )
)
def callback(n_clicks):
    print(n_clicks) # (2, 1627354204364)
    time.sleep(2.0)
    return [f"Clicked {n_clicks} times"]

Note that the function has exactly 1 argument which is a tuple of callback args.

Hi,

I am experimenting the longcallback with Dash 2.0 and the function works great with Diskcache, however, it did not work with Celery. I tried the code with both local Windows and Azure VM, but I always got an error:

Windows: redis.exceptions.ConnectionError: Error 10061 connecting to localhost:6379. No connection could be made because the target machine actively refused it.

Linux: Connection refused

Any thoughts on it?

Are you running a Redis server on port 6379?

Yes, I got the Redis server ( https://github.com/MSOpenTech/redis/releases/download/win-3.2.100/Redis-x64-3.2.100.zip) as suggested in this post: redis - Error while starting Celery worker on django Error 10061 No connection could be made because the target machine actively refused it - Stack Overflow. However, the callback is still not responding.

Also, if the app is hosted in an Azure Web Service, how will the Redis server be hosted?

I just hit the wall with @long_callback realising that it does NOT support pattern-matching dependencies. This is clearly stated in the documentation. I just wished I read the docs properly before starting to codeā€¦ :sweat_smile:

What is the reason why the @long_callback does not support pattern-matching dependencies out of the box? Is the support planned for the future versions of Dash?

I created a feature request for this.

1 Like

I tried both the examples mentioned in the documentation in Long Callbacks | Dash for Python Documentation | Plotly.

None of the two (DiskCache and Celery) seems to working on my system. It shows ā€œButton not clickedā€ even after clicking number of times. Attached image:

I am using redis on docker container for Celery.

Hi @saurabh11baghel ,

have you seen this thread? @long_callback with Celery & Redis - how to get the example app work?

Hi @sislvacl , Thanks for providing the link. Got the idea.

Hi Emil,

I am fairly new to Dash, and this is my first message in the community. I hope it is alright to reply to your message here (I think it is relevant).

I have been using your awesome work on DashProxy (with MultiplexerTransform()) because I need callbacks that have same outputs. However, when I try to use long_callbacks with DashProxy in the example above (Example 4: Progress bar) I get the following error:

Traceback (most recent call last):
  File "/home/nima/.local/lib/python3.8/site-packages/flask/app.py", line 2073, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/nima/.local/lib/python3.8/site-packages/flask/app.py", line 1511, in full_dispatch_request
    self.try_trigger_before_first_request_functions()
  File "/home/nima/.local/lib/python3.8/site-packages/flask/app.py", line 1563, in try_trigger_before_first_request_functions
    self.ensure_sync(func)()
  File "/home/nima/.local/lib/python3.8/site-packages/dash_extensions/enrich.py", line 223, in _setup_server
    self.blueprint.register_callbacks(super())
  File "/home/nima/.local/lib/python3.8/site-packages/dash_extensions/enrich.py", line 149, in register_callbacks
    o = cbp.outputs if len(cbp.outputs) > 1 else cbp.outputs[0]
IndexError: list index out of range

The only change I make is app = dash.Dash to app = DashProxy in Exmple 4. Is it possible to use long_callbacks in DashProxy? If not, is there any other way to have long callbacks in DashProxy?

I am using dash==2.4.0 and dash_extensions=0.1.1.

Thank you!
/Nima

@Neema Your observation is correct, long_callbacks are not support by dash-extensions :slight_smile:

Just exploring this feature - must we use diskcache as the cache of choice? Or is it possible to pair this with the cache from flask_caching?