nats-io / nats.ts

TypeScript Node.js client for NATS, the cloud native messaging system
https://www.nats.io
Apache License 2.0
178 stars 13 forks source link

out of band errors from the server on initial connect are reported by emitting #95

Closed aricart closed 1 year ago

aricart commented 4 years ago

It is possible for the server to send an -ERR protocol to the client while the client is still in the process of connecting. Currently, such notifications are emitted, this happens before the client is able to connect and thus resolve the connection.

aricart commented 4 years ago

@chiaolun - still trying to understand how it was possible for you not to register an error handler. If you await the initial connection, the tcp connection will resolve it, and thus make it available for you to add an error handler, which means that errors emitted by the protocol (errors from the server), will go to your handler.

This is my test:

test('server error before connect rejects', async (t) => {
    let port: number;

    const p = new Promise((resolve, reject) => {
        const server = net.createServer((socket: Socket) => {
            socket.write("-ERR 'fake error'\r\n")
        });
        server.on('listening', async () => {
            try {
                const nc = await connect({ url: `nats://localhost:${port}`, debug: true } as NatsConnectionOptions)
                nc.on('error', (err) => {
                    t.log(err.code)
                    t.pass();
                    resolve();
                })
            } catch(err) {
                reject(err);
            }
        });

        // if '0' is provided we get a random port
        server.listen(0, () => {});

        // @ts-ignore
        port = server.address().port;
    })

    p.then(() => {
        t.log('didnt throw');
    }).catch((err) => {
          t.log('error', err);
    })
    await p;
})

The things to note, are that - the TCP dial did happen, however the mock server never sent an INFO, instead it sent an -ERR protocol message, which is processed and emits.

✔ basics › server error before connect rejects ℹ NATS_PROTOCOL_ERR ℹ didnt throw

1 test passed

Can you describe when you are registering the listener?

chiaolun commented 4 years ago

I think it's a race condition, you can see this by adding a sleep between the await connect and nc.on('error', ...) - there's no reason why a -ERR cannot be received in that gap.

chiaolun commented 4 years ago

I was registering the listener exactly as you have it in this test, right after the connect.

aricart commented 4 years ago

@chiaolun thanks.

tvvignesh commented 4 years ago

@aricart @chiaolun Hi. Is this related? I am getting out of band errors. I was able to connect one client successfully to my NATS server. This error comes up for the second client I am trying to connect using the same username and password.

1

This is how I am connecting:

let nc = await connect({
    url: config.api.nats.host,
    name: 'My NATS Server',
    timeout: 60 * 1000,
    pingInterval: 20 * 1000,
    maxPingOut: 5,
    reconnect: true,
    maxReconnectAttempts: 30,
    payload: Payload.JSON
  });

Any workarounds? Thanks,

tvvignesh commented 4 years ago

Its working now. It was because of Linkerd. Had added skip outbound ports now: https://github.com/linkerd/linkerd2/issues/1715