sewenew / redis-plus-plus

Redis client written in C++
Apache License 2.0
1.64k stars 351 forks source link

[QUESTION] How to interrupt subscriber's consume? #338

Closed ivan-ushakov closed 2 years ago

ivan-ushakov commented 2 years ago

Documentation shows typical pattern for Subscriber:

// Consume messages in a loop.
while (true) {
    try {
        sub.consume();
    } catch (const Error &err) {
        // Handle exceptions.
    }
}

Since there is no any way to interrupt waiting on consume message, there is no way to "exit" such loop. Te only possible solution is to set socket timeout, but this leads to unnecessary wake ups. Is it possible to close subscriber connection somehow? Maybe to add such method to interface?

sewenew commented 2 years ago

Normally, there're two ways to exit the loop. One is the solution you mentioned, i.e. set a socket timeout. The other is to publish a STOP message to the channel to wake up the consume call.

but this leads to unnecessary wake ups

If the timeout is not too short, it should not be a problem.

Also once the async interface for Subscriber is ready, we might have another choice.

Regards

alexolog commented 1 year ago

Is it possible to add an option to check if there is published data on the socket (maybe using ioctl) so the user can check before entering a blocking consume?

sewenew commented 1 year ago

redis-plus-plus is based on hiredis, and hiredis does not have such a feature. So we can not add such an option.

The async interface for subscriber is ready. With AsyncSubscriber, if you want to interrupt the consuming work, you can destroy AsyncSubscriber, e.g. make it out of scope.

auto async_redis = AsyncRedis("redis://127.0.0.1");

{
    auto sub = async_redis.subscriber();
    sub.on_message([](string channel, string msg) { cout << channel << ": " << msg << "\n"; });
    sub.subscribe("c");      // <----- begin to consume messages in event loop.
    string input;
    cin >> input;        // <----- wait signal to stop consuming.
}     // <------ once `sub` is out of scope, redis-plus-plus stops consuming.

Regards