swoole / swoole-src

🚀 Coroutine-based concurrency library for PHP
https://www.swoole.com
Apache License 2.0
18.45k stars 3.16k forks source link

Redis subscribe does not really do anything, according to Swoole examples #2753

Closed paveljanda closed 5 years ago

paveljanda commented 5 years ago

Code in documentation (https://github.com/swoole/swoole-src/blob/master/examples/coroutine/redis/sub.php):

go(function () {
    $redis = new Swoole\Coroutine\Redis();
    $redis->connect('127.0.0.1', 6379);
    //while (true) 
    {
        $msg = $redis->subscribe(array("msg_1"));
        var_dump($msg);
    }
});

I think it should be like this:

go(function() {
    $redis = new Redis;

    $redis->connect('127.0.0.1', 6379);

    $redis->subscribe(['channel'])

    while ($message = $redis->recv()) {
        var_dump($message);
    }
});

Thanks a lot

doubaokun commented 5 years ago

@paveljanda

Swoole\Coroutine\Redis is the coroutine version of Redis client.

The following code works as a Redis subscription:

<?php
go(function () {
    $redis = new Swoole\Coroutine\Redis();
    $redis->connect('127.0.0.1', 6379);
    while (true) 
    {
        $msg = $redis->subscribe(array("msg_1"));
        var_dump($msg);
    }
});
paveljanda commented 5 years ago

Actually I don't rally think this is true. You should not be calling Redis::subscribe each time you receive a message. You should be calling the example I gave you above:

go(function() {
    $redis = new Redis;

    $redis->connect('127.0.0.1', 6379);

    $redis->subscribe(['channel'])

    while ($message = $redis->recv()) {
        var_dump($message);
    }
});
paveljanda commented 5 years ago

Wtf?

I showed you correct behaviour. You can try those examples by yourself. Your example is wrong. Your example is repeatedly "var_dumping" true even it has not receive any message from the channel. My example subscribes to the channel "channel" only one time and then it receives the message only when there is a message published into this channel.

Please correct the documentation to prevent people directing a dead end.

paveljanda commented 5 years ago

cc @matyhtf @twose

doubaokun commented 5 years ago

@paveljanda you are using a block version redis client which is blocking the whole process which should not be used in the context of coroutine.

Please try the following example with php cli and PUBLISH msg_1 a and PUBLISH msg_2 b in redis client.

You should be able to understand how the redis sub works in Swoole:

<?php
go(function () {
    $redis = new Swoole\Coroutine\Redis();
    $redis->connect('127.0.0.1', 6379);
    while (true) 
    {
        $msg = $redis->subscribe(array("msg_1"));
        var_dump($msg);
    }

});

go(function () {
    $redis = new Swoole\Coroutine\Redis();
    $redis->connect('127.0.0.1', 6379);
    while (true) 
    {
        $msg = $redis->subscribe(array("msg_2"));
        var_dump($msg);
    }
});

Btw, please stop using the word Wtf.

paveljanda commented 5 years ago

I used the word because you suddenly closed the issue. Sorry for that but please, don't close this issue yet. I don't think it is resolved.

On my machine, your code is var_dumping true 900474 times in 5 seconds to cli. I don't think this is really correct behaviour. I think the process should wait for a message to be received from redis. You are not var_dumping the message but result of subscribe command.

My example is actually not blocking. I tried it. Or what am I missing?

paveljanda commented 5 years ago

Try this:

go(function() {
    $redis = new Redis;

    $connectResult = $redis->connect('127.0.0.1', 6379);

    if ($redis->subscribe(['channel-1'])) {
        while ($message = $redis->recv()) {
            var_dump($message);
        }
    } else {
        throw new \RuntimeException('Could not subscribe');
    }
});

go(function() {
    $redis = new Redis;

    $connectResult = $redis->connect('127.0.0.1', 6379);

    if ($redis->subscribe(['channel-2'])) {
        while ($message = $redis->recv()) {
            var_dump($message);
        }
    } else {
        throw new \RuntimeException('Could not subscribe');
    }
});
paveljanda commented 5 years ago

Result of my code:

array(3) {             
  [0]=>                
  string(9) "subscribe"
  [1]=>                
  string(9) "channel-1"
  [2]=>                
  int(1)               
}                      
array(3) {             
  [0]=>                
  string(9) "subscribe"
  [1]=>                
  string(9) "channel-2"
  [2]=>                
  int(1)               
}                      
array(3) {             
  [0]=>                
  string(7) "message"  
  [1]=>                
  string(9) "channel-1"
  [2]=>                
  string(3) "foo"      
}                      
array(3) {             
  [0]=>                
  string(7) "message"  
  [1]=>                
  string(9) "channel-1"
  [2]=>                
  string(3) "bar"      
}                      

Result fo your code:

true
true
true
true
true
true
true
true
true (200k times a second..)
doubaokun commented 5 years ago

@paveljanda when reporting bugs please follow the template like the other people:

Please answer these questions before submitting your issue. Thanks!

  1. What did you do? If possible, provide a simple script for reproducing the error.

  2. What did you expect to see?

  3. What did you see instead?

  4. What version of Swoole are you using (show your php --ri swoole)?

  5. What is your machine environment used (including version of kernel & php & gcc) ?

paveljanda commented 5 years ago

Ok, sorry, will update the first comment. 👍

paveljanda commented 5 years ago

@doubaokun Updated. 👍

doubaokun commented 5 years ago

@paveljanda the example is updated for version > 4.4.0. Closing this thread now.

paveljanda commented 5 years ago

Thanks a lot, appreciate it.