amqp: Channel.Publish blocks indefinitely

Channel.Publish sometimes blocks indefinitely. The following code is a test case to reproduce this. It reproduces most of time I run it. Adding a sleep between inside the for loop does not help.

package main

import (
	"log"

	"github.com/streadway/amqp"
)

func main() {

	const queueName = "q1"

	if conn, stdErr := amqp.Dial("amqp://guest:guest@localhost:5672/"); stdErr != nil {
		log.Fatalln(stdErr)
	} else if channel, stdErr := conn.Channel(); stdErr != nil {
		log.Fatalln(stdErr)
	} else if stdErr := channel.Confirm(false); stdErr != nil {
		log.Fatalln(stdErr)
	} else if _, stdErr := channel.QueueDeclare(
		queueName, //queue
		true,      //durable
		false,     //autodelete
		false,     //exclusive
		false,     //nowait
		nil,       //arguments
	); stdErr != nil {
		log.Fatalln(stdErr)
	} else {
		confirmationChan := channel.NotifyPublish(make(chan amqp.Confirmation))

		for i := 0; i < 10000; i++ {
			log.Println("publish ", i)

			if stdErr := channel.Publish(
				"",        // exchange
				queueName, // routing key
				false,     // mandatory
				false,     // immediate
				amqp.Publishing{
					Body: []byte{},
				}); stdErr != nil {
				log.Fatalln(stdErr)
			} else {
				log.Println("pre confirmation check")
				confirmation := <-confirmationChan
				log.Println("post confirmation check")
				if !confirmation.Ack {
					log.Fatalln("confirmation not ack")
				}
			}
			// time.Sleep(time.Millisecond * 1000)
		}
	}
}

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 23

Commits related to this issue

Most upvoted comments

Found the problem!

In my test case, this confirmationChan := channel.NotifyPublish(make(chan amqp.Confirmation)) should be confirmationChan := channel.NotifyPublish(make(chan amqp.Confirmation, 1))

Documentation says

The capacity of the chan Confirmation must be at least as large as the
number of outstanding publishings.  Not having enough buffered chans will
create a deadlock if you attempt to perform other operations on the Connection
or Channel while confirms are in-flight.

Seems like that the deadlock I have been hitting. I don’t understand what other operations are being performed that are causing the deadlock, but making the channel buffered did fix my problem.

@michaelklishin, thanks for helping out. I found this while comparing my code to the producer example.