Search code examples
phpsymfonyrabbitmqamqp

Rabbitmq / PhpAmqpLib PRECONDITION_FAILED - unknown delivery tag


I know that this question is asked more then once but this once is different.

I am using the PhpAmqpLib (version 2.5.1) and RabbitMq (version 3.5.1). I created a Symfony bundle that is able to crawl a website and uses a worker queue to run it in multiple threads.

What the script basicly does is picking an item from the queue, extract the URL that should be crawl'ed and then crawl it. When new url's are found on the crawled page these URL's are published as new jobs on the queue.

The bundle is located here: https://github.com/keesschepers/concurrent-spider-bundle

I am getting the following error: PRECONDITION_FAILED - unknown delivery tag xxx (where xxx is a number that varies but is often 1, 21 or 30.

It's always when around 30 url's are processed.

What did I try so far:

  • Register multiple channels (a channel for publishing, and one for consuming)
  • Play with delivery mode and durabillity

If you Google for this error, a lot of people say that you are trying to acknowledge a message when no_ack=true, but that is false in my case.

Does anyone can tell me where I should start debugging?

The stacktrace is as follows:

Exception trace:
 () at /home/vagrant/sim-search-admin/vendor/videlalvaro/php-amqplib/PhpAmqpLib/Channel/AMQPChannel.php:191
 PhpAmqpLib\Channel\AMQPChannel->channel_close() at n/a:n/a
 call_user_func() at /home/vagrant/sim-search-admin/vendor/videlalvaro/php-amqplib/PhpAmqpLib/Channel/AbstractChannel.php:170
 PhpAmqpLib\Channel\AbstractChannel->dispatch() at /home/vagrant/sim-search-admin/vendor/videlalvaro/php-amqplib/PhpAmqpLib/Channel/AbstractChannel.php:362
 PhpAmqpLib\Channel\AbstractChannel->wait() at /home/vagrant/sim-search-admin/vendor/simgroep/concurrent-spider-bundle/Queue.php:66
 Simgroep\ConcurrentSpiderBundle\Queue->listen() at /home/vagrant/sim-search-admin/vendor/simgroep/concurrent-spider-bundle/Command/CrawlCommand.php:62
 Simgroep\ConcurrentSpiderBundle\Command\CrawlCommand->execute() at /home/vagrant/sim-search-admin/vendor/symfony/symfony/src/Symfony/Component/Console/Command/Command.php:257
 Symfony\Component\Console\Command\Command->run() at /home/vagrant/sim-search-admin/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php:882
 Symfony\Component\Console\Application->doRunCommand() at /home/vagrant/sim-search-admin/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php:195
 Symfony\Component\Console\Application->doRun() at /home/vagrant/sim-search-admin/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Console/Application.php:96
 Symfony\Bundle\FrameworkBundle\Console\Application->doRun() at /home/vagrant/sim-search-admin/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php:126
 Symfony\Component\Console\Application->run() at /home/vagrant/sim-search-admin/app/console:28

Somehow the channel seems to be closed, where that shouldn't happen.

This error already happends when I am running it in one thread.


Solution

  • I found the cause and the solution some days back, and even though I was "sure" I wasn't acknowleding twice, I still was :)

    The reason:

    public function theCallbackMethod(AMQPMessage $message) {
        try {
           //do something here
        } catch (ExceptionOne $e) {
            $channel->reject(/* ... */, false);
        } catch (ExceptionTwo $e) {
            $channel->reject(/* ... */, true);
        }
    
        $channel->acknowledge(/* ... */);
    }
    

    Offcourse the solution was to move the acknowledge call inside the try catch block.