How to read a message only once from a queue - php

I am using ActiveMQ to store a queue of messages.
I am using the PECL Stomp extension to connect to it.
I am publishing to the queue successfully, and reading from it successfuly.
How do I configure the queue to delete a message after I consumed it?
In my listener, I use
$c = new Stomp($url);
$c->subscribe('/queue/something');
echo $c->readFrame();

You have to acknowledge the consumption of a message to get them "deleted" from the queue. You can do that with $stomp->ack($messageID).
If you don't want to explicitely acknowledge the receipt, you can set the headers of $stomp->subscribe of ack to auto. This will make the server auto acknowledge the message and assume it was correctly delivered.
$stomp->subscribe('/queue/something', array('ack' => 'auto'));
References:
http://php.net/manual/en/stomp.ack.php
http://php.net/manual/en/stomp.subscribe.php
https://stomp.github.io/stomp-specification-1.1.html#SUBSCRIBE

Related

aws-sdk-php v3.44 fails to sendMessage to SQS FIFO Queue: MessageGroupId missing?

I am using the Amazon SDK for PHP version 3.44 (released 2017-11-30). I can connect to my Amazon SQS account and execute the listQueues(), getQueueUrl(), getQueueAttributes(), and receiveMessage() commands just fine. However, the sendMessage() command consistently fails with the following message:
The request must contain the parameter MessageGroupId.
I am most definitely including this parameter. It doesn't seem to matter which version of the aws-sdk-php API I use, this message keeps coming back. Here is my code:
$queue = SqsClient::factory([
'profile' => $profile,
'region' => $region,
'version' => '2012-11-05',
'credentials' => $credentials,
]);
$queue_list = $queue->listQueues(); // ok
$url = $queue->getQueueUrl(['QueueName'=>$queue_name]); // ok
$received = $queue->receiveMessage(['QueueUrl'=>$url->get('QueueUrl')]); // ok
$response = $queue->sendMessage([
'MessageBody' => $message,
'MessageGroupId' => $message_group_id,
'QueueUrl' => $url->get('QueueUrl'),
]); // fails with message indicating MessageGroupId is missing
I have spent several hours searching for a working example of sending a message up to an Amazon SQS FIFO queue through the PHP SDK, and am beginning to believe this is not possible. Has anybody out there been able to get the aws-sdk-php library to work with an SQS FIFO queue?
The first line is creating an instance of SqsClient, not creating a SQS queue. You still still need to call $queue->createQueue. See the documentation. For fifo queues, you will need to enable "FifoQueue" to "true", and set up the "ContentBasedDeduplication" when creating the queue. When you send your message, depending on the ContentBasedDeduplication setting of the queue you created, you may or may not also need to send a "MessageDeduplicationId" along with the "MessageGroupId".
From your code, I can't see how you created the Queue.
Did you enable fifo queues with the property "FifoQueue" => "true"
Did you set "ContentBasedDeduplication" to "true" or "false" ?
Did you name your queue with the extension ".fifo" ?
I did all of these things, and configured my queue with ContentBasedDeduplication set to "false". When I send a message, the only other property that I'm sending that you aren't (along with the MessageGroupId) is MessageDeduplicationId. I'm able to send messages to the fifo queue just fine using sdk 3.44.
It looks like Amazon has quietly resolved whatever bug was blocking my API call. I did not change my queue settings or my code. The same API call that resulted in error messages last week now runs just fine.
I ran into this problem on 3.3.0 forever. In my case, I just needed to upgrade to 3.44.2, then pass in MessageDeduplicationId in addition to MessageGroupId. I would probably double check your SDK version if you run into this issue.

Message sending Telegram bot (PHP)

I know it's somehow weird to ask something like this, but I'm trying to program a telegram bot with PHP.
The bot is in a channel (e.g. Channel A) and I'm going to send messages in that channel, so the bot will copy X number of messages to another channel (Channel B), Every Y minutes.
Example:
X = 5
Y = 60
Channel A = ID .....
Channel B = ID .....
So it will COPY 5 messages from A to B every hour...
Can anybody write me a template please? I think I can configure the VPS and webhook stuff (SSL and etc).
If you need send message per minutes, and get message from Telegram callback, you need read about queue (zmq, redis, gearman or etc).
Create daemons. These are your bots. They can read messages from queue and send callbacks.
Write Controller to get callback from telegram. It can take message and push to queue.
Install Ev or Event extension on PHP. (You can use reactphp, it simple solution to create timer)
Bot1 create timer, and listen messages. If we have more 5 messages, timer can push message in queue for Bot2.
You can use reactphp/zmq, nrk/predis-async to helpful your task
P.S. It is most simple solution. But you can use pthreads (instead create daemon process) or use simple socket to send message in bot.
If you want to use webhook things you can do this.
write a sample code like this:
<?php
$texts_from_other_channel = [];
array_push($texts_from_other_channel , $update_array['message']['text']);
$t_size = sizeof($texts_from_other_channel)
for($i=0 ; $i < $t_size ; $i++){
$post_prs = ['chat_id' => $channel_id , 'text' => $texts_from_other_channel[$i]];
send_reply($sendmessag_url , $post_prs);
end
?>
other things like send_reply() function or $update_array are up to you and I left to yourself.

Laravel queue (iron.io) keeps sending same email over and over

I am using the Iron.io API with Laravel 5.1. It sends out emails fine. However, it seems to be sending the same message over and over again (4 times or more). Any idea why this might happen?
The code I am using is:
Mail::queue([], [], function ($message) use ($template, $order, $filename) {
$message
->to($order->email)
->subject($template->subject)
->setBody(DbView::make($template)->with($order->toArray())->render(), 'text/html');
$message->attach(storage_path('exports/'.$filename));
});
Ben hit the nail on the head.
In case it's handy, here's a link to the Iron.io developer docs:
This call gets/reserves messages from the queue. The messages will not be deleted, but will be reserved until the timeout expires. If the timeout expires before the messages are deleted, the messages will be placed back onto the queue. As a result, be sure to delete the messages after you're done with them.
http://dev.iron.io/mq/reference/api/#get_messages_from_a_queue

ActiveMQ not returning message when queue has n number of pending messages

Environment/Background:
Using PHP Stomp library to send and receive message from ActiveMQ (v5.4.3).
Steps:
Client sends a message with reply-to & correlation-id headers to request queue (say /queue/request)
Subscribe to the response queue (say /queue/response)
Read frame
ack
unsubscribe
The above steps works fine when there is no pending message or pending message < n. In my case, n =200. When the number of pending message is > 200, the message is not delivered. The process waits till timeout and finally timeout without response. I can see the message (using admin UI) after timeout. Here is the code that I'm using for this case:
<?php
// make a connection
$con = new Stomp("tcp://localhost:61616");
// Set read timeout.
$con->setReadTimeout(10);
// Prepare request variables.
$correlation_id = rand();
$request_queue = '/queue/com.domain.service.request';
$response_queue = '/queue/com.domain.service.response';
$selector = "JMSCorrelationID='$correlation_id'";
$headers = array('correlation-id' => $correlation_id, 'reply-to' => $response_queue);
$message = '<RequestBody></RequestBody>';
// send a message to the queue.
$con->send($request_queue, $message, $headers);
// subscribe to the queue
$con->subscribe($response_queue, array('selector' => $selector, 'ack' => 'auto'));
// receive a message from the queue
$msg = $con->readFrame();
// do what you want with the message
if ( $msg != null) {
echo "Received message with body\n";
var_dump($msg);
// mark the message as received in the queue
$con->ack($msg);
} else {
echo "Failed to receive a message\n";
}
unset($con);
Other findings:
Sending messages from one file (say from sender.php) and receive using another script (say receiver.php) working fine.
Allows to send more than 1000 message in the same request queue(and eventually processed and placed in response queue). So it doesn't look like memory issue.
Funny enough, while waiting for timeout, if I browse the queue on admin UI, I get the response.
By default, the stomp broker that I use set the prefetch size to 1.
Without knowing more my guess is that you have multiple consumers and one is hogging the messages in it's prefetch buffer, the default size is 1000 I think. To debug situations like this it's usually a good idea to look at the web console or connect with jconsole and inspect the Queue MBean to see the stats for in-flight messages, number of consumers etc.
Answering my own question.
The problem I'm facing is exactly what is described in http://trenaman.blogspot.co.uk/2009/01/message-selectors-and-activemq.html and the solution is to increase the maxPageSize as specified in ActiveMQ and maxPageSize
As you can match that the 200 is not a varying number, but the default value of maxPageSize.
More references:
http://activemq.2283324.n4.nabble.com/Consumer-is-not-able-to-pick-messages-from-queue-td2531722.html
https://issues.apache.org/jira/browse/AMQ-2217
https://issues.apache.org/jira/browse/AMQ-2745

Keep messages from ACKing on get() using pecl-amqp

I'm attempting to use pecl-amqp for a project of mine. I'm having difficulties though with the ACK process. I need to manually ACK each message I receive off a queue, but the messages appear to be auto-ACKing when the message is retrieved.
I've set my queue to AMQP_NOACK and am using AMQPQueue->get(AMQP_NOACK) but none of it seems to have any affect, the messages are still removed from the queue without me sending AMQPQueue->ack().
If anyone has any experience with the pecl-amqp I would appreciate the help.
I have been having the same problem but have managed to get the acknowledge mechanism to work using the consume method. Using rabbitmqctl to list the entries in the queue it appears to work OK, though I seems to be getting the messages off the queue in a different order to that in which they were sent - which kind of defeats the object of a queue. My code is as follows:
// 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 acknoledge later.
$options = array(
'min' => 0,
'max' => 1,
'ack' => false
);
// Get the messages
$results_array = $q->consume($options);
// show the message
print_r($results_array);
$delivery_tag = $results_array[0]['delivery_tag'];
echo 'delivery_tag: [' . $delivery_tag . "].\r\n";
// Acknowledge receipt of the message.
$q->ack($delivery_tag);
For reference, the AMQP extension did not support the AMQP_NOACK correctly. You can get it to do what you want, but it isnt pretty. I am working on fixing that now. FYI, AMQP_NOACK means that you will not have to come back to acknowledge the message later, i.e. as soon as the server sends the message to the client, the server marks the message as ack'ed. There has been some confusion around this, so I wanted to clarify.

Categories