graze / queue

:postbox: Flexible abstraction for working with queues in PHP.
MIT License
49 stars 10 forks source link

AMQP Adapter #32

Open stevenscg opened 8 years ago

stevenscg commented 8 years ago

This is just a placeholder for discussion regarding a new AMQP adapter (RabbitMQ, etc).

I did some prototyping of a new adapter using the SqsAdapter as a baseline and my preferred library (one of the best AFAIK): https://github.com/videlalvaro/php-amqplib.

I was able to enqueue and dequeue the messages rather easily, but have had trouble with acknowledge thus far. I'll continue to work on that and link to it when I have something functional.

The AMQP library recommends that consumers use $channel->basic_consume(). https://github.com/videlalvaro/php-amqplib/blob/master/PhpAmqpLib/Channel/AMQPChannel.php#L898

This works by declaring a callback and the consumer will remain attached and receiving messages as long as the callback is registered.

The core logic looks roughly like this:

try {
    // params: $queue, $consumer_tag, $no_local, $no_ack, $exclusive, $nowait, $callback
    $channel->basic_consume($this->name, '', false, false, false, false, $callback);
} catch (Exception $e) {
    // @TODO Channel setup exception
}

// Loop as long as the channel has callbacks registered
while (count($channel->callbacks)) {
    try {
        var_dump('waiting');
        $channel->wait();
    } catch (Exception $e) {
        // @TODO Channel wait exception
    }
}

I have not yet been able to dequeue using the above basic_consume logic which I think will be the best long-term approach for this new adapter. I'll circle back to this after I can get acknowledge working.

However, I was able to get the $channel->basic_get() operation to work within a loop yielding $factory->createMessage() items. https://github.com/videlalvaro/php-amqplib/blob/master/PhpAmqpLib/Channel/AMQPChannel.php#L981

The AMQP library doesn't recommend this due to inefficiencies (etc), but I have seen their maintainers suggest this method as an option for people trying to build their own blocking consumers.

A third option is also a possibility: $channel->batch_basic_publish() https://github.com/videlalvaro/php-amqplib/blob/master/PhpAmqpLib/Channel/AMQPChannel.php#L1115 I haven't used it myself and didn't know it was even available until last week.

sjparkinson commented 8 years ago

Relates to #8.

Thanks for posting your progress so far @stevenscg, it's great to understand your thinking before a PR comes along. I'll make sure to have a good read of videlalvaro/php-amqplib.

Would you mind linking to where basic_consume is the recommended call for consumers? Sounds like a good place for me to start.

stevenscg commented 8 years ago

Yup.

This library is used for the official RabbitMQ tutorials: http://www.rabbitmq.com/tutorials/tutorial-two-php.html

While AMQP can work in a number of interesting and useful queuing scenarios, I almost always end up back with simple work queues where I can run N producers and consumers to load balance and parallelize work.

Basic "consume" vs "get":

sjparkinson commented 8 years ago

Brilliant, thanks very much for the reading material :eyeglasses:!