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

allow getting recoverable_connection_errors without an active transport #1471

Merged
merged 10 commits into from
Dec 30, 2021

Conversation

pawl
Copy link
Contributor

@pawl pawl commented Dec 22, 2021

I was looking into solutions for the celery + redis memory leak issue and I was attempting to reduce the references to initialized Transports.

One thing I noticed was that you currently need at least one initialized Transport with an active connection to allow filling the cache for recoverable_connection_errors/recoverable_channel_errors/connection_errors/channel_errors. It seems like it makes more sense to get the errors from the Transport class without needing to initialize it (in case there are connection errors on the first Transport initialization).

This doesn't fix the memory leak issue, but maybe this change is still worth making?

@lgtm-com
Copy link

lgtm-com bot commented Dec 22, 2021

This pull request fixes 1 alert when merging c217795 into b71b421 - view on LGTM.com

fixed alerts:

  • 1 for `__init__` method calls overridden method

super().__init__(*args, **kwargs)

self.connection_errors = (
if consul:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only 3 transports are subject to this adjustments?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I did a search for self.connection_errors and self.channel_errors, and looked at each of the transports.

For some reason, the librabbitmq and mongodb backends don't have the try/except ImportError: logic and they don't use __init__ to fill in connection_errors and channel_errors.

@@ -571,6 +573,16 @@ class MyTransport(Transport):
conn = Connection(transport=MyTransport)
assert conn.channel_errors == (KeyError, ValueError)

def test_channel_errors__exception_no_cache(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

beside the unit tests I would love to see integration tests for this

@lgtm-com
Copy link

lgtm-com bot commented Dec 22, 2021

This pull request fixes 1 alert when merging a08d2ad into c4a8c2a - view on LGTM.com

fixed alerts:

  • 1 for `__init__` method calls overridden method

@lgtm-com
Copy link

lgtm-com bot commented Dec 22, 2021

This pull request fixes 1 alert when merging a8a9913 into 6ddf940 - view on LGTM.com

fixed alerts:

  • 1 for `__init__` method calls overridden method

Copy link
Member

@auvipy auvipy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with pytest.raises(KeyError):
self.channel._receive_one(self.channel.subclient)

  assert not self.channel._in_listen

E assert not True
E + where True = <t.unit.transport.test_redis.Channel object at 0x7f8bf8d594d0>._in_listen
E + where <t.unit.transport.test_redis.Channel object at 0x7f8bf8d594d0> = <t.unit.transport.test_redis.test_Channel object at 0x7f8bf8d591d0>.channel

t/unit/transport/test_redis.py:582: AssertionError

@lgtm-com
Copy link

lgtm-com bot commented Dec 22, 2021

This pull request fixes 1 alert when merging c2c6b1b into 4a6e164 - view on LGTM.com

fixed alerts:

  • 1 for `__init__` method calls overridden method

@lgtm-com
Copy link

lgtm-com bot commented Dec 22, 2021

This pull request fixes 1 alert when merging c6052ff into 4a6e164 - view on LGTM.com

fixed alerts:

  • 1 for `__init__` method calls overridden method

@auvipy auvipy added this to the 5.2.x milestone Dec 22, 2021
Copy link
Member

@auvipy auvipy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to take some time & more eyes and trials before merging this. in the mean the you can push any improvements in mind. and most possibly the more integration tests the better IMHO

@auvipy
Copy link
Member

auvipy commented Dec 22, 2021

besides, do we need any docs changes to mention the adjustments being made?

@auvipy
Copy link
Member

auvipy commented Dec 22, 2021

@michael-lazar

@auvipy
Copy link
Member

auvipy commented Dec 24, 2021

@pawl did you try this in any project with celery? i want to have some integration test for this

@lgtm-com
Copy link

lgtm-com bot commented Dec 24, 2021

This pull request fixes 1 alert when merging 448cdb9 into 47781af - view on LGTM.com

fixed alerts:

  • 1 for `__init__` method calls overridden method

@pawl
Copy link
Contributor Author

pawl commented Dec 24, 2021

@auvipy I added an integration test here: 448cdb9

do we need any docs changes to mention the adjustments being made?

Oops, should I be updating the changelog?

I'm not aware of any documentation changes since old code should continue to work the same way, because the errors are still a class attribute on the same class.

I'm not sure we need to document the removal of _get_errors outside of the release notes since it's an internal method. It also doesn't look like it's overridden in any open source projects: https://github.com/search?q=transport+_get_errors+NOT+MultiChannelPoller+NOT+test_purge+NOT+%22by+Ask+Solem%22&type=Code

@pawl
Copy link
Contributor Author

pawl commented Dec 24, 2021

@auvipy

did you try this in any project with celery?

I've tested the change with this branch of my celery memory leak example repo. It's still able to recover from connection errors successfully after I restart redis. Also, it connects successfully on start-up.

@auvipy
Copy link
Member

auvipy commented Dec 24, 2021

ok we are good to go

@auvipy auvipy modified the milestones: 5.2.x, 5.3 Dec 24, 2021
@auvipy
Copy link
Member

auvipy commented Dec 24, 2021

decided to land this change on 5.3 for now, as it changes some behaviours, but if other core team members agree will end landing in 5.2.x bug fix release

Copy link
Member

@matusvalo matusvalo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not 100% sure but if I read correctly the code get_transport_cls() needs a transport as string or type. Default value is None which I am not sure will work.

def resolve_transport(transport=None):
"""Get transport by name.
Arguments:
transport (Union[str, type]): This can be either
an actual transport class, or the fully qualified
path to a transport class, or the alias of a transport.
"""
if isinstance(transport, str):
try:
transport = TRANSPORT_ALIASES[transport]
except KeyError:
if '.' not in transport and ':' not in transport:
from kombu.utils.text import fmatch_best
alt = fmatch_best(transport, TRANSPORT_ALIASES)
if alt:
raise KeyError(
'No such transport: {}. Did you mean {}?'.format(
transport, alt))
raise KeyError(f'No such transport: {transport}')
else:
if callable(transport):
transport = transport()
return symbol_by_name(transport)
return transport
def get_transport_cls(transport=None):
"""Get transport class by name.
The transport string is the full path to a transport class, e.g.::
"kombu.transport.pyamqp:Transport"
If the name does not include `"."` (is not fully qualified),
the alias table will be consulted.
"""
if transport not in _transport_cache:
_transport_cache[transport] = resolve_transport(transport)
return _transport_cache[transport]

kombu/connection.py Show resolved Hide resolved
kombu/connection.py Show resolved Hide resolved
@pawl
Copy link
Contributor Author

pawl commented Dec 29, 2021

@matusvalo get_transport_cls is already used without arguments in create_transport (used by the transport property):

return self.get_transport_cls()(client=self)

It looks like _init_params will populate self.transport_cls and it will be used by get_transport_cls.

@matusvalo
Copy link
Member

@matusvalo get_transport_cls is already used without arguments in create_transport (used by the transport property):

return self.get_transport_cls()(client=self)

It looks like _init_params will populate self.transport_cls and it will be used by get_transport_cls.

Yeah you are right :-/. I missed that it is wrapped in the same class. Please ignore my comment.

@auvipy auvipy modified the milestones: 5.3, 5.2.x Dec 30, 2021
@auvipy auvipy merged commit 9c062bd into celery:master Dec 30, 2021
keithgg pushed a commit to open-craft/kombu that referenced this pull request Aug 11, 2022
…rt (celery#1471)

* allow getting recoverable_connection_errors without an active transport

* move redis transport errors to class

* move consul transport errors to class

* move etcd transport errors to class

* remove redis.Transport._get_errors and references in tests

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix flake8 errors

* add integration test for redis ConnectionError

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants