amq-client icon indicating copy to clipboard operation
amq-client copied to clipboard

queue cache not maintained properly, channel crashes

Open chrono opened this issue 13 years ago • 0 comments

Once a queue is deleted, subsequent queue declarations by the same name are not executed. How to reproduce, using the amqp gem:

AMQP.channel.queue('foo', :durable => false) do |queue, declare_ok|                   
  puts "first declare succeeded"                                                      
  puts declare_ok.inspect                                                             
  queue.delete do                                                                     
    puts "first delete succeeded"                                                     
    AMQP.channel.queue('foo', :durable => false) do |queue, declare_ok|               
      puts "second declare succeeded"                                                 
      puts declare_ok.inspect                                                         
      queue.delete do                                                                 
        puts "second delete succeeded"                                                
      end                                                                             
    end                                                                               
  end                                                                                 
end          

output, using a channel level exception handler:

first declare succeeded
0
first delete succeeded
second declare succeeded
nil
Handling a channel-level exception.

AMQP class id : 50
AMQP method id: 40
Status code   : 404
Error message : NOT_FOUND - no queue 'foo' in vhost '/'

Looking at a tcpdump trace of the communication, I can see that a second declare/declare-ok never happens. I suspect the amqp client to be at fault. Also interesting:

# from lib/amq/client/async/queue.rb
        def delete(if_unused = false, if_empty = false, nowait = false, &block)
          nowait = true unless block
          @connection.send_frame(Protocol::Queue::Delete.encode(@channel.id, @name, if_unused, if_empty, nowait))

          if !nowait
            self.append_callback(:delete, &block)

            # TODO: delete itself from queues cache
            @channel.queues_awaiting_delete_ok.push(self)
          end

          self
        end # delete(channel, queue, if_unused, if_empty, nowait, &block)

If i use queue! instead of queue on the second declaration (bypassing the queue cache), the test succeeds.

chrono avatar Jan 07 '13 22:01 chrono