Closed michaeldain closed 2 years ago
Yes, you're right the socket_timeout
has been reached. If you want to block forever, you have to make socket_timeout
to be 0.
Check the doc for detail:
NOTE: if you set
ConnectionOptions::socket_timeout
, and try to call blocking commands, e.g.Redis::brpop
,Redis::blpop
,Redis::bzpopmax
,Redis::bzpopmin
, you must ensure thatConnectionOptions::socket_timeout
is larger than the timeout specified with these blocking commands. Otherwise, you might getTimeoutError
, and lose message.
If you have to set a non-zero socket timeout, you can do xread in a loop. If Redis::xread
throw TimeoutError, retry it, i.e. continue the loop.
Regards
First of all, thank you for your answer。 But my usage scenario is sentinel,so can't I set the ConnectionOptions::socket_timeout to 0 ?
Hi @michaeldain,
I cut-and-pasted (and slightly modified) the following from examples in the top level README. Maybe this is what you are after?
ConnectionOptions connection_opts;
connection_opts.password = "auth"; // Optional. No password by default.
connection_opts.connect_timeout = std::chrono::milliseconds(100); // Required.
connection_opts.socket_timeout = std::chrono::milliseconds(100); // Required.
ConnectionPoolOptions pool_opts;
pool_opts.size = 3; // Optional. The default size is 1.
auto redis = Redis(sentinel, "master_name", Role::MASTER, connection_opts, pool_opts);
while (true) {
try {
// Do a blocked xread for more than connection_opts.socket_timeout.
redis.xread("stream_key", id, connection_opts.socket_timeout * 2, 10, std::inserter(result, result.end()));
} catch (const TimeoutError &e) {
// We reached the connection_opts.socket_timeout.
continue;
} catch (const Error &err) {
// Handle other exceptions.
}
}
This way you'll block-xread, but will time-out after connection_opts.socket_timeout, in which case you'll just repeat the block-xread.
Regards
I know you. and i have done as your way. But block way don't handle timeout error again and again like try catch ( waste cpu?)
But block way don't handle timeout error again and again like try catch ( waste cpu?)
It's a trade-off. You can increase your socket_timeout if these few cpu cycles bother you.
@michaeldain You can try the following pseudo code:
while (true) {
try {
redis.xread("key", id, timeout-smaller-than-socket_timeout, 10, std::inserter(result, result.end()));
if (result.empty()) {
// no result, continue xread
continue;
} else {
break; // got a result.
}
} catch (const TimeoutError &e) {
continue; // since timeout for xread is smaller than socket_timeout, normally you should not get a TimeoutError.
}
}
If the socket_timeout is not too small, e.g. 1ms, it will not cost too much cpu cycles. You can do some benchmark for it.
Regards
tks,Is it because of the internal mechanism of the current implementation that reading cannot be blocked forever?
@michaeldain Yes, if you use sentinel, you cannot block forever.
Regards
Since there's no update, I'll close this issue.
Regards
Before Asking A Question
For general questions on redis-plus-plus, you can ask questions at StackOverflow with redis tag, and normally, you'll get faster response on StackOverflow.
However, if you still don't get answers, feel free to ask a question here.
Describe the problem Question: How to block reading data in stream. Describe : I use this way from READ.me."id" is the last id for stream, i want to block read data from stream like command "xread count 1 block 0 streams stream_key lastId". But try catch throw error. error msg is "Failed to get reply: Resource temporarily unavailable" redis.xread("stream_key", id, std::chrono::seconds(0), 10, std::inserter(result, result.end()));
Environment:
Additional context catch info: "Failed to get reply: Resource temporarily unavailable" I guess this info return after socket timeout.