nats.py icon indicating copy to clipboard operation
nats.py copied to clipboard

Reconnection logic should not apply for the first connection attempt

Open Kazmirchuk opened this issue 2 years ago • 2 comments

Consider the following code:

import asyncio
import nats

async def run():

    async def error_cb(e):
        print(f'There was an error: {e}')

    try:
        nc = await nats.connect(servers='nats://localhost:4222',
                                error_cb=error_cb,
                                max_reconnect_attempts=2)
        await nc.publish(subject='foo', payload='data'.encode())
        await nc.flush()
        await nc.drain()
    except Exception as err:
        print(f"{type(err)} : {err}")

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    try:
        loop.run_until_complete(run())
    finally:
        loop.close()

Having started nats-server that requires authentication, e.g. with user/password, I get the following output:

There was an error: nats: 'Authorization Violation'
There was an error: nats: 'Authorization Violation'
There was an error: nats: 'Authorization Violation'
<class 'nats.errors.NoServersError'> : nats: no servers available for connection

that clearly shows that the client tries to connect 3 times before giving up, which is not in line with other clients. As far as I understand, the RetryOnFailedConnect option in nats.go is false by default. So, nats.py should give up right after the first failure.

Kazmirchuk avatar Sep 16 '22 15:09 Kazmirchuk

The same would happen in the Go client, there are a couple of attempts to connect to the same server and the it would return a no servers available error.

wallyqs avatar Sep 16 '22 15:09 wallyqs

well, this is my first attempt with Go (I specialize in C++ and Python), so please let me know if I missed anything:

opts := nats.GetDefaultOptions()
opts.MaxReconnect = 3
opts.Servers = []string{"nats://localhost:4222"}
nc, err := opts.Connect()
if err != nil {
    fmt.Println("ERROR: ", err)
    os.Exit(1)
}
nc.Publish("foo", []byte("Hello World"))
nc.Close()

result:

ERROR:  nats: Authorization Violation

Looking at the server log ( -DV ), there was only one attempt to connect.

This is not a real problem for me, because in my (restricted) environment I can always assume that a NATS server is running, and my credentials are correct, but more of a philosophical question, because I'm writing my own NATS client, and wanted to make it as consistent with other clients as possible 🙂 feel free to close this, if you have more important things on your plate.

P.S. To be honest, I'm not super happy with the golang client behaviour either 🙄 when given a pool of servers, and connecting to all of them fails, I get back an error only from the last server in the list. And seems like no callbacks are invoked in the process, so I can't know why connecting to other servers failed.

Kazmirchuk avatar Sep 19 '22 13:09 Kazmirchuk