mosquito / aio-pika

AMQP 0.9 client designed for asyncio and humans.

Home Page:https://aio-pika.readthedocs.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

connect with url ignores all other parameters

ba1dr opened this issue · comments

This is related to both functions connect and connect_robust.
Being called with parameters url and, say, client_properties the latter is not used.

The problem is in the make_url() function:

def make_url(
    url: Union[str, URL, None] = None,
    ...
) -> URL:
    if url is not None:
        if not isinstance(url, URL):
            return URL(url)
        return url
    ...

If the url is passed - all other parameters are ignored.
In my case I store one connection string in the shared config file but different scripts (many of them) may set their own names (connection_name) upon connecting to the broker.
I am not sure if this is correct to merge kwargs with the connection string (I'd prefer yes), but this is not good to just silently swallow and ignore the parameters.
I'd suggest to at least raise an exception (or put a warning) if there is something except url is passed.
The current behaviour was not obvious and I spent several hours googling and browsing the sources to find the root case.

in this case connection name might be a part of the url, like ?name=my%20custom%20name

Yes, I got this after I found #301 . But it was not obvious at all that the parameter client_properties accepted, but silently ignored. If it threw an exception - I'd understood that faster.
I am migrating my code from kombu and it allows to combine connection string with the additional parameters.
In addition - these parameters are likely not passed to RabbitMQ directly along with hostname/password/etc, but extracted and sent separately, which makes it no sense to be sent only in connection string.
Even aiormq library accepts client_properties in its connect() method, but we have no access to it through aio_pika.

If you know how it's might be fixed, do not keep silence.

I see many ways to fix this, but this is you who could choose a decision.

  1. Ultimate solution. The most correct one as for me.
    To merge connection string with all the other parameters. To decompose url into the parts and overwrite parts with the parameters if passed.
    Can break backward compatibility for those who already uses the library but do not know about the current behaviour. Can bring new bugs as well.

  2. Partial solution. A bit ugly and not obvious either.
    To merge only query part of the url - to merge only client_properties or kwargs.
    Other parameters remain silently ignored. Makes not too much sense.

  3. "You're-doing-it-wrong" way of solution. At least clears further questions on the subject.
    We throw an exception if url is passed with anything else.
    Breaks backward compatibility. But you do not receive any more issues about missing connection_name.

  4. "tag: Known issue" way of solution. Quick'n' lazy.
    Like (3) but write a warning instead of exception.

the MERGE implies CONFLICTS, what is source of truth? The URL should be updated by the params, or the params might replaced by the url parts?

Again, this is just a matter of definition. If you write in the docs that the parameters have more importance if passed - then this is it.
I can see the scenario where the connection string is kept as a base for other parameters to be clarified later. Examples:

  • in my case only connection name can be different
  • there could be connection string in a config file with the credentials (username/password) taken from the more secure storage to be merged into
  • there could be several alternative hosts for the broker and you do not need to rewrite the entire connection string by yourself if you can just rotate the hostname in a loop

I am voting for the merge and resolve the conflicts in favor of additional parameters.
Right now I have to write the sh*t like this in my code:

        if '?' in amqp_connstr:
            amqp_connstr += f'&name={quote(amqp_name)}'
        else:
            amqp_connstr += f'?name={quote(amqp_name)}'

Obviously this contains a mistake too - if the name has been already defined in the connection string - there is a conflict again. But I have no willing to implement a complete url parsing into that part of my code just to replace the connection name.