Skip to content

queue cache not maintained properly, channel crashes #22

@chrono

Description

@chrono

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions