Req #59965 [Opn->Csd]: Support of pre-fetch.
| From: | pdezwart@php.net | Date: | Wed, 26 Oct 2011 02:02:15 +0000 |
| Subject: | Req #59965 [Opn->Csd]: Support of pre-fetch. | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-164569@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=59965&edit=1
ID: 59965
Updated by: pdezwart@php.net
Reported by: andrew dot hobson at moveonlineretail dot com
Summary: Support of pre-fetch.
-Status: Open
+Status: Closed
Type: Feature/Change Request
Package: amqp
Operating System: Linux 2.6.18-238.12.1.el5.028st
PHP Version: 5.2.17
-Assigned To:
+Assigned To: pdezwart
Block user comment: N
Private report: N
New Comment:
This bug has been fixed in SVN.
Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
For Windows:
http://windows.php.net/snapshots/
Thank you for the report, and for helping us make PHP better.
This is fixed in trunk and will be part of the v1.0 release, coming soon.
Previous Comments:
------------------------------------------------------------------------
[2011-09-23 14:39:54] andrew dot hobson at moveonlineretail dot com
Description:
------------
After discussing this on the rabbitmq-discuss forum it was
suggested that my problem may be being caused by my call to
consume() actually fetching all messages in the queue,
rather than just the top one. I am setting min to 0 and max
to 1 in the hope that this would fetch only one message.
The scenario is that I have one reader process which may die
due to system failure and at restart I'd like the same
single consumer process to start up again and pick up where
it left off. So a summary of what I'd like to happen is:
(1) My transmitter process sends and queues up messages 1,
2, 3, 4, 5 & 6.
(2) My single consumer process reads and acknowledges
messages 1 and 2 in sequence.
(3) My consumer process reads message 3 and then dies
without acknowledging.
(4) I restart my consumer process which will request the
next message, which should be the unacknowledged message 3.
(5) My consumer process would then continue reading messages
from the queue (4, 5, & 6) in sequence.
What I am experiencing is that when my consumer process is
restarted messages 3, 4, 5 & 6 are all delivered out of
sequence and all with a redelivery count of 1. I understand
that message 3 might be out of sequence because it was
unacknowledged and from what I have read about RabbitMQ
message handling, when a message is redelivered then it's
sequence is no longer guaranteed.
However I'm not clear as to why the remaining queued
messages are out of sequence too. This is where the
explanation of my code possibly fetching all messages in the
queue (1 to 6) in the call to consume() and when it dies,
causing RabbitMQ to redelivery all of them, resulting in
them being out of sequence.
So the 'bug', if you can call it that, is to ask whether it
is possible to set a pre-fetch value which only gets a
specified number of messages from the queue, which in this
scenario I would want to set to 1. That way hopefully only
message 3 would get redelivered by RabbitMQ because it was
not acknowledged, and the other messages would still be
delivered in sequence because they haven't yet been read
from the queue.
Hope this makes sense.
Reproduce code:
---------------
#!/usr/bin/php -q
<?php
// config
$exchangeName = 'HERMES_EXCHANGE';
$routingKey = 'DIRECT_ROUTE';
$queueName = 'HERMES_QUEUE';
// connect
$connection = new AMQPConnection();
$connection->connect();
// setup our queue
$q = new AMQPQueue($connection);
// Create the queue to be:
// AMQP_DURABLE - messages will withstand a broker restart (i.e. they are written to disk).
// AMQP_NOACK - when consumed messages will not be marked as delivered until an explicit ACK is
received.
$q->declare($queueName, AMQP_DURABLE | AMQP_NOACK );
// Bind it on the exchange to routing key.
$q->bind($exchangeName, $routingKey);
// Set the options for our consumption of the messages:
// Get a minimum of 0 msg.
// Get a maximum of 1 msg.
// Don't ACK the message on consumption i.e. explicitly acknowledge later.
$options = array(
'min' =0,
'max' =1,
'ack' =false
);
$polling_count = 0;
while (true) {
$polling_count++;
echo "\r\nPolling. Count: " . $polling_count . "\r\n";
// Get the messages
$results_array = $q->consume($options);
// show the message
$delivery_tag = $results_array[0]['delivery_tag'];
$redelivered = $results_array[0]['redelivered'];
$message_body = $results_array[0]['message_body'];
echo "Message read.\r\n";
echo 'delivery_tag: [' . $delivery_tag . "].\r\n";
echo 'redelivered: [' . $redelivered . "].\r\n";
echo 'message_body: [' . $message_body . "].\r\n";
if ($polling_count != 3) {
if ($delivery_tag != 0) {
// Acknowledge receipt of the message if we had a valid delivery tag.
$result = $q->ack($delivery_tag);
echo 'Acknowledge result: ' . $result . "\r\n";
}
} else {
echo 'No Ack';
}
usleep(4000000);
}
// Disconnect
$connection->disconnect();
?>
Expected result:
----------------
In the code above I pre-populated the message queue with 6
messages from a separate transmit script, then ran this
consuming process. After the third message was received I
interrupted the program with ctrl-c and then re-ran it.
I expected that the sequence of messages read after the
interrupt would be 4, 5, & 6 and then 3, due to the re-queuing
of 3 following failure by my script to acknowledge message 3.
Actual result:
--------------
After interrupting the program and re-reading from the queue
the sequence of messages 3 - 6 is completely unpredictable.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=59965&edit=1