Open ArtsiomAntropau opened 1 year ago
For celery the copy_current_request_context
method doesn't work. An alternative we could do is provide the values like headers, path, remote, etc. inside the callback_context instead.
@T4rk1n can you highlight why it doesn't work? In common, this function simply copies the current request context and provided it inside the function, like dash already doing with dash callback context.
The main problem and thing that we need to remember – we should not try to push it when we're packing the function for celery, it should be passed to the prepared function as arguments (I mean wrapper that will call user's callback function).
The issue is that wrapping the function in the callback where it should be, doesn't return a celery task object to call (Missing func.delay). The callback_context I refactored to use a context_var instead of the flask.g object for that matter.
@T4rk1n so what do you think about it? (except of temp inability to serialize contextvars)
def flask_patcher():
with flask.current_app.app_context():
@flask.copy_current_request_context
def _(fn, *args, **kwargs):
return fn(*args, **kwargs)
return _
def call_job_fn(self, key, job_fn, args, context):
task = job_fn.delay(key, self._make_progress_key(key), args, flask_patcher())
return task.task_id
@celery_app.task(name=f"long_callback_{fn_hash}")
def job_fn(result_key, progress_key, user_callback_args, context=None, patcher=None):
if isinstance(user_callback_args, dict):
user_callback_output = patcher(fn, *maybe_progress, **user_callback_args)
elif isinstance(user_callback_args, (list, tuple)):
user_callback_output = patcher(fn, *maybe_progress, *user_callback_args)
else:
user_callback_output = patcher(fn, *maybe_progress, user_callback_args)
@ArtsiomAntropau If you can prove that works with a test, (can add path=flask.request.path
to tests/integration/long_callback/app_callback_ctx.py
line 34 then test in test_lcbc012_long_callback_ctx) I'll gladly take a look in a PR.
From @JamesKunstle in #2636:
Update: For anyone looking for a solution, you can pass the 'request=flask.request' object into background callbacks and that seems to work.
https://community.plotly.com/t/how-to-read-cookies-inside-a-background-callback/70224/11
Hi @alexcjohnson ! It appears for me (and not only) that this method is not working cus i gor "Working outside of request context"
So, this solution request=flask.request
is working when DiskCache is on, but not for Celery.
Describe your context
Describe the bug
Expected behavior
So, after creating callback function and before providing them to the Celery, we should provide flask contexts inside this function to imitate the default callback behaviour
Any recommendations for now?