-
Notifications
You must be signed in to change notification settings - Fork 356
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[QUESTION] Correct way to handle TimeoutError due to EAGAIN from Redis::subscriber? #327
Comments
Hmm, actually the retry-loop didn't help... it still can't connect even after trying multiple times in a loop. What's really weird is that the binary, when running on a different server, is able to connect fine; and |
Hi @skebanga,
Please see this post: #307 (comment)
Try to see if the same libs are being used on all your servers. Run the following command on all your servers and compare the results carefully: $ ldd your_binary In order to be absolutely sure that your libs and binaries are all the same on all servers, you could compare their checksums: $ ldd your_binary |awk -F'(' '{print $1}' |awk -F'=>' '{print $2}' |grep -v '^\s*$' |xargs sha256sum
$ sha256sum your_binary You probably checked the connection (to make sure you don't have a network issue or a firewall problem) with $ redis-cli -h <redis_server> -p <redis_port> ping Regards |
Thanks for the comment! I am statically linking the redis libs, so that's not an issue
I have also managed to boil the issue down to the following, which shows that it is failing on issuing the #include <sw/redis++/redis++.h>
#include <iostream>
#include <chrono>
int main()
{
sw::redis::ConnectionOptions opts("tcp://10.10.6.106:6379");
opts.user = "default";
opts.password = "XXXXXXXX";
opts.socket_timeout = std::chrono::milliseconds(100);
sw::redis::Redis r{opts};
sw::redis::Subscriber sub{r.subscriber()};
return 0;
} It is working with running both through redis_cli:
test_redis:
So major differences I can see are:
I'm a bit lost at this point tbh! :( |
I ran my test program on a server which works, and got the following strace output:
So literally the only difference between the two is that the failing server's
whereas the working server's
|
Well - some progress it seems! The culprit is I'll admit I'm no redis expert... but would it be fair to say it seems a bit weird that 100ms is too low? |
@skebanga Yes, I think the problem is that redis-cli by default might not set a timeout, so it does not have the problem. If you set You’d better check if your redis server in a healthy status, or the network between your application and redis is not fast enough. Regards |
@sewenew thanks for the comment! The only issue with setting a while (!token.stop_requested())
{
try
{
sub.consume(); // without socket_timeout this call never returns if there are no published messages
}
catch (const sw::redis::TimeoutError&)
{
// by using socket_timeout we can catch the TimeoutError and check the std::stop_token
}
catch (const sw::redis::Error& e)
{
LOG_ERROR("redis error: ", e.what());
break;
}
} Ideally there would be a thread-safe way to cause |
😭 |
You don't need to set it to 0. Your problem is that your network latency is too big, and if the socket_timeout is smaller than it, it cannot do authentication and subscription before consuming messages. In order to make it work you need to set socket_timeout larger than the network latency.
As @Mephalich mentioned you can send a termination message to the channel. Once Regards |
@sewenew thanks for the comments! Yes, understand the need to set timeout higher than network latency in this case... However, I think in an ideal world it would be nice to be able to set zero timeout, as in I don't care how long the authentication and subscription takes, just so long as it completes... but also be able to effect a break out of the Forcing the user to have to set a timeout just so they can exit the loop is awkward... Anyway, I'll close the issue, because my question has been answered (even if I don't like the answer!) :) |
Thanks for a great package!
Describe the problem
Attempting to obtain a
Subscriber
from a Redis connection fails with a TimeoutError exception being thrown, with the description being "Resource temporarily unavailable" (ie: errnoEAGAIN
)Stacktrace shows this is from
Connection::recv
as a result ofConnection::_auth
during call toRedis::subscriber
What is the correct way to handle this?
At the moment I'm just attempting to create a subscriber in a loop, and if a
TimeoutError
exception is thrown, I just try again, up to some arbitrarily picked max number of retries... it seems to work... but it also seems inelegant / a bit of a hack.What is the recommended way for obtaining a Subscriber please?
Environment:
ubuntu
gcc-11.2.0
1.0.0
1.3.3
The text was updated successfully, but these errors were encountered: