Repository: amqp-node/amqplib

Issue #419: Publish confirm callback not called
Created: 2018-05-05T09:26:08Z
Hi,
I have something like this, using a confirm channel:
server.post('/test', async (req, res) => {
  const message = Buffer.from(JSON.stringify(req.body));

  await new Promise((resolve, reject) => channel.publish('test', 'test', message, {persistent: true}, (error) => {
    if (error) {
      console.error('Error publishing', error);

      return reject(error);
    }

    return resolve();
  }));

  return res.status(204).end();
});

The problem is that if I send a request after getting disconnected from the server (literally pulling the network cable) but before the heartbeat detects the connection issue, the callback is never called and thus I'm not sending a response back. I do get an 'error' event on my connection, though.
I would expect the confirm callback to be called with an error.
Maybe it'd be interesting to have a timeout for publish confirms as well? At the moment I'm thinking of implementing a timeout mechanism using Promise.race to send an error response.
Thanks.

Duplicate issue #530: ConfirmChannel.publish does not fail (or hangs) if RabbitMQ gets lost
Created: 2019-07-22T12:01:38Z
Short version:
Problem: I want a publish to fail immediately so that clients know that they need to retry a send. If the RabbitMQ server goes down, amqp doesn't tell me that a publish failed, even on a ConfirmChannel, but hangs forever.
Long version:
Not sure whether I'm looking at a bug here: It appears that a publish does not report an error when I publish a message if RabbitMQ just went down. This results in my clients thinking everything is fine, when it's actually not at all guaranteed that a message will ever even make it to the server.
I tried the following:

using confirmChannel
submitting a callback: The callback is only invoked if a connection to RabbitMQ exists
awaiting channel.waitForConfirms() seems to hang forever

Repro:

start app with a healthy RabbitMQ server
connect and create a confirmChannel
kill the RabbitMQ server (app keeps running)
publish a message before the heartbeats detect that the connection is gone
publish will still return true (!), but the callback will not be invoked. Alternatively, invoking awaitForConfirms will hang indefinitely.

Here's my code (with both the callback/await versions, just comment out what you don't need)
public async publish(exchangeName: string, content: object, headers?: object) {

    try {
        const data = Buffer.from(JSON.stringify(content));

        // publish the message, and escalate in case of a failure
        console.log("publishing...");
        const status: boolean = this.channel.publish(exchangeName, "", data, { persistent: true, timeout: 2000, headers: headers || {} }, (err, ok) => {
            // I never get here with a severed connection
            console.log("ACK PUBLISH - err " + err + ", ok: " + ok);
        });

        await this.channel.waitForConfirms();
        console.log("CONFIRMS"); //i never get there with the await in place, if the connection is gone

        if (!status) {
            // will be logged and rethrown
            throw new Error(`Publishing message to exchange ${exchangeName} failed with status ${status}.`);
        }
    } catch (e) {
        this.logger.error("Could not publish message to exchange.", e, {
            name: "mqPayload",
            exchange: exchangeName,
            headers: headers || null,
            ...content,
        });
        throw e;
    }
}

Closing comment (2019-07-22T19:28:39Z): This could be related to timeouts being disabled withing the library after the initial connection.
Potentially related to #419