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

Publish hangs indefinitely when channel error is caught by the listener #190

Open
muter opened this issue Oct 3, 2021 · 1 comment
Open

Comments

@muter
Copy link

muter commented Oct 3, 2021

Hi!

As described in issue amqp-node/amqplib#649 of the amqplib, channels with no 'error' listeners attached, cause the whole connection to crash. When using amqp-connection-manager this behavior leads to a reconnect of all open channels when one of them is closed with an error. This may cause some issues, such as slower queue processing or message duplication, depending on circumstances.

However, if 'error' listener is attached to a channel, it will not kill the connection, and channel will not reconnect by itself. This causes all further attempts to interact with that channel to fail or hang indefinitely. All published messages are collected in an internal queue possibly causing a memory leak.

Code snippet to reproduce the behavior:

const { connect } = require("amqp-connection-manager");

async  function doSomething() {
  const connection = await connect({ hostname: "message-broker", username: "guest", password: "guest" });
  const channel = connection.createChannel({
    setup: (channel) => {
      channel.on("error", e => console.log("Channel error:", e.message));
    }
  });
  try {
    await channel.publish("nonexistent", "", Buffer.from("non important stuff"));
  } catch (e) {
    console.error("Publish 1 failed", e.message);
  }
}

doSomething().then(() => console.log("Complete"), e => console.error("Failed", e));

Running this will produce:

Channel error: Channel closed by server: 404 (NOT-FOUND) with message "NOT_FOUND - no exchange 'nonexistent' in vhost '/'"

After which process will wait for publish promise forever.

I was also unable to find a way to manually reconnect a channel without reconnecting the whole connection, which will affect all other channels used by app.

In my opinion, reconnecting one channel in case of errors, without affecting the whole connection, would be a great feature. Hope for some discussion here.

Thank you.

@rhsobr
Copy link
Contributor

rhsobr commented Oct 3, 2021

Hi,

I think that reconnecting channel after an error should be the default behavior here.
Checking or deleting inexistent queue/exchange throw same issue.

Sounds like the snippet below in ChannelWrapper:

private _reconnect() {
    if (this._channel) return;

    const { connection } = this._connectionManager;

    if (connection) {
        this._onConnect({ connection });
    }
}

private _onChannelError() {
       this._reconnect();
 }
 
 channel.on('error', () => this._onChannelError());

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants