diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dfb54c487..64c6d059b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,12 @@ This project adheres to [Semantic Versioning](https://semver.org/). - [#2417](https://github.com/plotly/dash/pull/2417) Disable the pytest plugin if `dash[testing]` not installed, fix [#946](https://github.com/plotly/dash/issues/946). - [#2417](https://github.com/plotly/dash/pull/2417) Do not swallow the original error to get the webdriver, easier to know what is wrong after updating the browser but the driver. +## [UNRELEASED] + +## Fixed + +- [#2415](https://github.com/plotly/dash/pull/2415) Fix background callbacks progress not deleted after fetch. + ## [2.8.1] - 2023-01-30 ## Fixed diff --git a/dash/long_callback/managers/celery_manager.py b/dash/long_callback/managers/celery_manager.py index fba09af65c..b4e0165c8d 100644 --- a/dash/long_callback/managers/celery_manager.py +++ b/dash/long_callback/managers/celery_manager.py @@ -98,6 +98,7 @@ def get_progress(self, key): progress_key = self._make_progress_key(key) progress_data = self.handle.backend.get(progress_key) if progress_data: + self.handle.backend.delete(progress_key) return json.loads(progress_data) return None diff --git a/dash/long_callback/managers/diskcache_manager.py b/dash/long_callback/managers/diskcache_manager.py index c12bafeb98..fea69f37f5 100644 --- a/dash/long_callback/managers/diskcache_manager.py +++ b/dash/long_callback/managers/diskcache_manager.py @@ -127,7 +127,11 @@ def call_job_fn(self, key, job_fn, args, context): def get_progress(self, key): progress_key = self._make_progress_key(key) - return self.handle.get(progress_key) + progress_data = self.handle.get(progress_key) + if progress_data: + self.handle.delete(progress_key) + + return progress_data def result_ready(self, key): return self.handle.get(key) is not None diff --git a/tests/integration/long_callback/app_progress_delete.py b/tests/integration/long_callback/app_progress_delete.py new file mode 100644 index 0000000000..2fdf08af61 --- /dev/null +++ b/tests/integration/long_callback/app_progress_delete.py @@ -0,0 +1,45 @@ +from dash import Dash, Input, Output, State, html, clientside_callback +import time + +from tests.integration.long_callback.utils import get_long_callback_manager + +long_callback_manager = get_long_callback_manager() +handle = long_callback_manager.handle + +app = Dash(__name__, long_callback_manager=long_callback_manager) + +app.layout = html.Div( + [ + html.Button("Start", id="start"), + html.Div(id="output"), + html.Div(id="progress-output"), + html.Div(0, id="progress-counter"), + ] +) + +clientside_callback( + "function(_, previous) { return parseInt(previous) + 1;}", + Output("progress-counter", "children"), + Input("progress-output", "children"), + State("progress-counter", "children"), + prevent_initial_call=True, +) + + +@app.callback( + Output("output", "children"), + Input("start", "n_clicks"), + progress=Output("progress-output", "children"), + interval=200, + background=True, + prevent_initial_call=True, +) +def on_bg_progress(set_progress, _): + set_progress("start") + time.sleep(2) + set_progress("stop") + return "done" + + +if __name__ == "__main__": + app.run_server(debug=True) diff --git a/tests/integration/long_callback/test_basic_long_callback.py b/tests/integration/long_callback/test_basic_long_callback.py index 70b8cb9c68..e82e4dc628 100644 --- a/tests/integration/long_callback/test_basic_long_callback.py +++ b/tests/integration/long_callback/test_basic_long_callback.py @@ -538,3 +538,12 @@ def test_lcbc013_unordered_state_input(dash_duo, manager): dash_duo.find_element("#click").click() dash_duo.wait_for_text_to_equal("#output", "stored") + + +def test_lcbc014_progress_delete(dash_duo, manager): + with setup_long_callback_app(manager, "app_progress_delete") as app: + dash_duo.start_server(app) + dash_duo.find_element("#start").click() + dash_duo.wait_for_text_to_equal("#output", "done") + + assert dash_duo.find_element("#progress-counter").text == "2"