Fix get exchange memory leak #677
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Issue: #396
There is a memory leak in
get_exchange. This is because each timeget_exchangeis called with theRobustExchangea new class is created and added to the set. A set is used because it's expected that this will deduplicate the objects. This doesn't work because__eq__and__hash__are not defined on theExchangeclass. If a user keeps calling this method, it keeps adding to this set, and it can grow very quickly.There are two ways of fixing this. #678 makes it so we can compare two exchanges, but I think this is not actually expected behavior. If we look at
aio-pika/tests/test_amqp.py
Line 1624 in c281314
get_exchangeis actually returning a class withoutauto_delete:However, it's clear that what is expected to happen here is we return the already declared exchange, which this PR does. There is no way to do this for non robust connections. With these connection,
get_exchangeis going to create a new class, but it will not fail because ofpassive=True, so it's sort of cheating as it's not really getting the exchange; it's trying to make a new one and failing as it already exists, therefore the object properties from the get and the declared exchange will not be the same.I've copied the test across to the robust connection. Here,
get_exchangecan return the actual object we originally declared, which I think is nicer.I think this is not breaking because it's not actually possible to declare exchanges with the same name. So, if you had in the past called
declare_exchangetwice with the same name but different arguments and not passive, you would have gotten an error anyway.Queues also need unique names but I think this
setstuff happened because the server name created for the name might not return or sometimes?aio-pika/aio_pika/queue.py
Line 109 in c281314
I think it would be better to make unnamed into a unique string so that we could do away with sets for queues as well further simplifying this function