Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Background callbacks not working on iOS/iPhone and Safari #3123

Open
celia-lm opened this issue Jan 15, 2025 · 0 comments
Open

Background callbacks not working on iOS/iPhone and Safari #3123

celia-lm opened this issue Jan 15, 2025 · 0 comments
Labels
bug something broken cs customer success P2 considered for next cycle

Comments

@celia-lm
Copy link

[workaround and code to reproduce the issue at the end of this message]

Screen.Recording.2025-01-15.at.14.22.34.mov

Text of the error:

[Error] Failed to load resource: The network connection was lost. (_dash-update-component, line 0)
[Error] Error: Callback failed: the server did not respond.
g — dash_renderer.v2_18_2m1736947227.min.js:2:145898

	So (dash_renderer.v2_18_2m1736947227.min.js:2:95216)
	(anonymous function) (dash_renderer.v2_18_2m1736947227.min.js:2:103633)
	(anonymous function) (dash_renderer.v2_18_2m1736947227.min.js:2:206857)
	p (dash_renderer.v2_18_2m1736947227.min.js:2:42868)
	Yi (dash_renderer.v2_18_2m1736947227.min.js:2:115653)
	(anonymous function) (dash_renderer.v2_18_2m1736947227.min.js:2:160719)
	forEach
	observer (dash_renderer.v2_18_2m1736947227.min.js:2:157858)
	(anonymous function) (dash_renderer.v2_18_2m1736947227.min.js:2:105928)
	forEach
	(anonymous function) (dash_renderer.v2_18_2m1736947227.min.js:2:105879)
	p (dash_renderer.v2_18_2m1736947227.min.js:2:42928)
	(anonymous function) (dash_renderer.v2_18_2m1736947227.min.js:2:170393)
	f (dash_renderer.v2_18_2m1736947227.min.js:2:161605)
	(anonymous function) (dash_renderer.v2_18_2m1736947227.min.js:2:162948)
	$u (dash_renderer.v2_18_2m1736947227.min.js:2:168505)
	a (dash_renderer.v2_18_2m1736947227.min.js:2:170597)

The issue is intermittent: it's possible that some of the requests/clicks work, but typically if the first one hasn't worked, none of them will.

Information about the video:

  • MacBook Ait M3 macOS 14.6.1
  • Safari 17.6
  • App deployed to Dash Enterprise 4 > I'm not sure if this happens on DE5 or not. I remember replicating it on DE5 this morning but now the same code doesn't cause the issue on DE5.

Things I have not tested:

  • If the issue happens locally.

Things I have tested:
The issue still happens:

  • If the background callback uses the running and/or cancel arguments.
  • If we use previous versions of Dash (tested from 2.13 to 2.18).
  • The user accesses the app from a Safari incognito window.

Workaround

  • Add a dcc.Interval to the layout with a quite frequent refresh rate (I've used interval=200, that is, 200ms > a higher value might work).
  • Create a callback that uses that interval as Input. It can have no output and return nothing, like this:
@callback(Input("interval_dummy", "n_intervals"))
def dummycb(_):
    return
  • Since this workaround will make a callback run every 200ms, the tab name will constantly show "Updating...". You can disable this by specifying updating_title=None as an argument to app = Dash().

Code to reproduce the issue

  • Deploy the app.
  • Access it from Safari.
  • Open the Inspect window.
  • Click the "Run" button.

requirements.txt

celery
dash
gunicorn
redis

at the time of creation of this ticket, these are the versions my app uses:

  • celery 5.4.0
  • dash 2.18.2
  • gunicorn 23.0.0
  • redis 5.2.1

app.py

import time
import os
import datetime
import dash
from dash import Dash, CeleryManager
from dash import Input, Output, State, ctx, html, dcc, callback #, set_props
from celery import Celery

celery_app = Celery(__name__, broker=f"{os.environ['REDIS_URL']}/5", backend=f"{os.environ['REDIS_URL']}/6")
background_callback_manager = CeleryManager(celery_app)

app = Dash()
server = app.server

app.layout = html.Div(
    [
        html.Div([html.P(id="paragraph_id", children=["Button not clicked"])]),
        html.Button(id="button_id", children="Run Job!"),
        html.Button(id="cancel_button_id", children="Cancel Running Job!"),
        # dcc.Interval(id="interval_dummy", interval=200),
    ]
)

@callback(
    output=Output("paragraph_id", "children"),
    inputs=Input("button_id", "n_clicks"),
    background=True,
    manager=background_callback_manager
)
def update_clicks(n_clicks):
    time.sleep(2.0)
    return [f"Clicked {n_clicks} times"]

# @callback(
#     Input("interval_dummy", "n_intervals")
# )
# def dummycb(_):
#     return 

if __name__ == "__main__":
    app.run(debug=True)

Procfile

web: gunicorn app:server --workers 4 
worker: celery -A app:celery_app worker --loglevel=INFO --concurrency=2

DOKKU_SCALE

web=1
worker=1
@gvwilson gvwilson added bug something broken P2 considered for next cycle cs customer success labels Jan 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug something broken cs customer success P2 considered for next cycle
Projects
None yet
Development

No branches or pull requests

2 participants