-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
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
Fix redis connection leak with app.send_task
#7685
Conversation
app.send_task
t/integration/test_tasks.py
Outdated
redis = get_redis_connection() | ||
connections_before = len(redis.client_list()) | ||
|
||
result = manager.app.send_task('t.integration.tasks.add', args=(1, 2)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we use add.delay()
then everything works
] | ||
assert result.get(timeout=3) == 3 | ||
assert get_active_redis_channels() == [] | ||
|
||
def test_redis_connection_cleanup_with_send_task(self, manager): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@auvipy Do you have some ideas why this test would fail? Happy to do a fix but I'd need some pointers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it might be related to #6963 .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It definitely seems like that the connection always stays in the pending_unsubscribe_channels
within the Redis client when using app.send_task
. I tried with the solution from the linked issue but that doesn't resolve things.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@auvipy can you please give me some pointers where the issue might be?
This pull request fixes 1 alert when merging 6c3378e into bdbf6d6 - view on LGTM.com fixed alerts:
|
Codecov Report
@@ Coverage Diff @@
## master #7685 +/- ##
==========================================
- Coverage 89.75% 88.74% -1.02%
==========================================
Files 138 138
Lines 17000 17007 +7
Branches 2510 2493 -17
==========================================
- Hits 15259 15093 -166
- Misses 1491 1673 +182
+ Partials 250 241 -9
Flags with carried forward coverage won't be shown. Click here to find out more.
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you please rebase this?
6c3378e
to
6455a47
Compare
done @auvipy |
@@ -328,3 +329,16 @@ def test_asyncresult_get_cancels_subscription(self, manager): | |||
|
|||
new_channels = [channel for channel in get_active_redis_channels() if channel not in channels_before_test] | |||
assert new_channels == [] | |||
|
|||
def test_redis_connection_cleanup_with_send_task(self, manager): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest we mark the test as xfail
ed and merge this PR.
There should be a matching issue for this PR so that we'll know this isn't yet fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@thedrow I don't think that merging this before fixing this is helpful. There are already multiple issues pointing towards a connection leak:
- Redis result consumer is not drained periodically (memory leak and possible connection reset) #6963
- Redis result backend connections leak #6819
What I would I need is some pointers / help. Besides that I'd be more than happy to investigate and help with a fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@thedrow I don't think that merging this before fixing this is helpful. There are already multiple issues pointing towards a connection leak:
* [Redis result consumer is not drained periodically (memory leak and possible connection reset) #6963](https://github.com/celery/celery/issues/6963) * [Redis result backend connections leak #6819](https://github.com/celery/celery/issues/6819)
What I would I need is some pointers / help. Besides that I'd be more than happy to investigate and help with a fix.
that should be the spirit
6455a47
to
9cb11e9
Compare
@auvipy I spent some time debugging it and that's the situation:
|
6c5d575
to
b1cfd8c
Compare
Added a potential fix for the caching issues with eventlet. Any idea why the CI is failing? In my opinion a bit weird as it's failing in somewhat unrelated parts. |
This pull request introduces 1 alert when merging b1cfd8c into 3db7c9d - view on LGTM.com new alerts:
|
try: | ||
from eventlet import corolocal | ||
task_backend_cache = self.app.local | ||
# Whenever an eventlet pool spawns a coroutine it has a different identifier and hence will acquire | ||
# a new coroutine-local storage. To avoid that we leak connections we explicitly clean out the | ||
# cache once the coroutine is done. | ||
if isinstance(task_backend_cache, corolocal.local): | ||
task_backend_cache.__dict__.clear() | ||
except ImportError: | ||
# Eventlet is not installed and hence not used | ||
pass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I am content with coupling eventlet or any other concurrency mode with the backend. Is there another way to resolve this issue?
We're unfortunately no longer running into this (we put |
thanks for the feedback Wong! |
Description
This test shows that there is a Redis connection leak when using
app.send_task
.The connection leak doesn't happen if
task.delay()
is used.Todos: