Paul Wagland Paul Wagland - 1 year ago 66
Perl Question

Using Redis and Perl, how to wait for one published method

I want to do something that is conceptually quite simple, wait for up to thirty seconds for a redid publish to come through. As soon as it comes through, I want to return, or if it doesn't come through, I want to return after thirty seconds.

The perl Redis module has almost everything that I want, except that I cannot return immediately after I get a message in.

The sample code that I am using looks like the following:


use Redis;

my $redisSub = Redis->new;
my $msg = 0;
my @topics = ('mykey');
my $savecallback = sub {
my ($message, $topic, $subscribed_topic) = @_;
print "Message received : $message\n";
$msg = $message;
# I tried adding in the following line, but it complains
# that: Missing required callback in call to unsubscribe()
#$redisSub->unsubscribe ( @topics , $savecallback);
$redisSub->subscribe ( @topics , $savecallback);

my $redis = Redis->new;
print "old: " . $redis->get('mykey') . "\n";
print "Waiting for message to be sent\n";

if ($msg) {
print "old: " . $redis->get('mykey') . "\n";
} else {
print "Timeout occurred\n";

The issue is that the
call waits for thirty seconds of idle activity, so if the message turns up, it prints out, immediately, "Message received", but then waits another thirty seconds before returning control to the script. I could change it to
, but then it returns immediately, and I need to includes this in a sleep loop, which introduces the potential latency in detecting the change outside of the call.

Is this possible using only the Redis module? Or does one need to use the AnyEvent::Redis::PipeRedis module to do this?

Answer Source

Ans : There is no such latency as you have mentioned. To stop with no more waiting when message arrives, use unsubscribe() but I have not tested it.

How : You have to do this:

while ('true' ) {

Why: The above waits for messages for 30 seconds, after that another 30 seconds and so on. But whenever a subscribed event happened, instantly the call-back-subroutine is invoked but wait_for_messages continues from the original state (independent of invoking/event occured/event not occurred). wait_for_messages(n) will not return in n seconds if subscribed messages are coming. So it continues for 30 seconds of wait. So if a matching publish happened every 29 seconds for 10 times, the wait_for_messages will return only after 290+30 seconds with return value 10. (then because of of while('true') it will go back to wait again.)

Note :1) Do/should not add sleep in the above code.
Note :2) If your aim is to stop processing after receiving first
message, you have to use $redisSub->unsubscribe(..) 
inside the call-back-subroutine.