Phpredis: [RFC] Add a way to make Redis::subscribe() async

Created on 20 Mar 2020  路  4Comments  路  Source: phpredis/phpredis

Expected behaviour

<?php

$redis = new \Redis();
$redis->connect('172.17.0.2');

function f() {
    dump(func_get_args());
}

dump("START");

$redis->subscribe(['test'], 'f');

// Be able to run some code...
dump('we continue');

This is does not work since Redis::subscribe() is blocking.
It would be nice to have the same system as pcntl_signal().

It would be even more awesome it this could work with signal:

<?php

$redis = new \Redis();
$redis->connect('172.17.0.2');

function f() {
    dump(func_get_args());
}

dump("START");

pcntl_async_signals(true);
$shouldStop = false;
pcntl_signal(SIGINT, function () use (&$shouldStop) {
    dump('CTRL+C detected!');
    $shouldStop = true;

    exit(1);
});

$redis->subscribe(['test'], 'f');

while (true) {
    echo ".";
    if ($shouldStop) {
        echo "\n";
        return;
    }
    sleep(1);
}

Actual behaviour

The following line blocks the script

$redis->subscribe(['test'], 'f');

I'm seeing this behaviour on

  • OS: ubuntu
  • Redis: 5+
  • PHP: 7.4+
  • phpredis: 5.2.0

I've checked

  • [x] There is no similar issue from other users
  • [x] Issue isn't fixed in develop branch
wishlist

Most helpful comment

Adding support for non-blocking sockets would be non-trivial, although I can see the appeal.

We're going to be making some pretty substantial changes to the library to fully support Redis 6.0 and I'll keep non-blocking sockets in mind.

It may be possible to implement this kind of support _only_ for subscribe and psubscribe, which likely makes it more feasible to implement.

All 4 comments

Adding support for non-blocking sockets would be non-trivial, although I can see the appeal.

We're going to be making some pretty substantial changes to the library to fully support Redis 6.0 and I'll keep non-blocking sockets in mind.

It may be possible to implement this kind of support _only_ for subscribe and psubscribe, which likely makes it more feasible to implement.

I am using this extension, but had to roll my own socket just for the pub/sub. This being a PHP extension i assume many are using it to maintain bi-directional sync to some frontend object model. Would be nice to have native support for servicing other requests and not hang blocked on subscriptions.

@michael-grunder Can you expand a bit on why this would be a non-trivial change? I would dig into i and get you a PR if its not a monumental task. I dont know this code base well so a few pointers on how wide you expect the blast radius extends and why. Not a tome just a few "obvious" areas of concern. I would want to limit the scope and only make the reading of subscription messages a non-blocking call rather than a block + call back.

Hi @merlinthemagic,

I haven't taken a deep look at how specifically to tackle non-blocking functionality in PhpRedis, but it's non-trivial by nature. There would need to be some way to either hook into PHP's event loop or into a third party one (possibly using the libev extension).

I do think it's worth looking at for PhpRedis 6 since we're already going to be replacing all the RESP parsing machinery with hiredis.

Maybe, we should have a look at pcntl, and see how this extension is implemented. Because it support some "interuption"

Was this page helpful?
0 / 5 - 0 ratings

Related issues

namjitharavind picture namjitharavind  路  4Comments

danielignatius picture danielignatius  路  4Comments

yalks picture yalks  路  4Comments

fidelhuang picture fidelhuang  路  5Comments

HunterEl picture HunterEl  路  4Comments