Adds connection timeout option to redis-cli (#10609)
This allows specifying the timeout value for opening the TCP connection to a server. The timeout, default 0 means no limit, depending on the OS. It can be specified using the new `-t` switch. revive #3764, fixes #3763 --------- Co-authored-by: Itamar Haber <itamar@redislabs.com> Co-authored-by: yoav-steinberg <yoav@redislabs.com>
This commit is contained in:
parent
492021db95
commit
76adbf6ff0
@ -424,3 +424,21 @@ sds cliVersion(void) {
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
/* This is a wrapper to call redisConnect or redisConnectWithTimeout. */
|
||||
redisContext *redisConnectWrapper(const char *ip, int port, const struct timeval tv) {
|
||||
if (tv.tv_sec == 0 && tv.tv_usec == 0) {
|
||||
return redisConnect(ip, port);
|
||||
} else {
|
||||
return redisConnectWithTimeout(ip, port, tv);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is a wrapper to call redisConnectUnix or redisConnectUnixWithTimeout. */
|
||||
redisContext *redisConnectUnixWrapper(const char *path, const struct timeval tv) {
|
||||
if (tv.tv_sec == 0 && tv.tv_usec == 0) {
|
||||
return redisConnectUnix(path);
|
||||
} else {
|
||||
return redisConnectUnixWithTimeout(path, tv);
|
||||
}
|
||||
}
|
||||
|
@ -53,4 +53,7 @@ sds escapeJsonString(sds s, const char *p, size_t len);
|
||||
|
||||
sds cliVersion(void);
|
||||
|
||||
redisContext *redisConnectWrapper(const char *ip, int port, const struct timeval tv);
|
||||
redisContext *redisConnectUnixWrapper(const char *path, const struct timeval tv);
|
||||
|
||||
#endif /* __CLICOMMON_H */
|
||||
|
@ -211,6 +211,7 @@ static int createClusterManagerCommand(char *cmdname, int argc, char **argv);
|
||||
static redisContext *context;
|
||||
static struct config {
|
||||
cliConnInfo conn_info;
|
||||
struct timeval connect_timeout;
|
||||
char *hostsocket;
|
||||
int tls;
|
||||
cliSSLconfig sslconfig;
|
||||
@ -1648,9 +1649,10 @@ static int cliConnect(int flags) {
|
||||
/* Do not use hostsocket when we got redirected in cluster mode */
|
||||
if (config.hostsocket == NULL ||
|
||||
(config.cluster_mode && config.cluster_reissue_command)) {
|
||||
context = redisConnect(config.conn_info.hostip,config.conn_info.hostport);
|
||||
context = redisConnectWrapper(config.conn_info.hostip, config.conn_info.hostport,
|
||||
config.connect_timeout);
|
||||
} else {
|
||||
context = redisConnectUnix(config.hostsocket);
|
||||
context = redisConnectUnixWrapper(config.hostsocket, config.connect_timeout);
|
||||
}
|
||||
|
||||
if (!context->err && config.tls) {
|
||||
@ -2593,7 +2595,8 @@ static redisReply *reconnectingRedisCommand(redisContext *c, const char *fmt, ..
|
||||
fflush(stdout);
|
||||
|
||||
redisFree(c);
|
||||
c = redisConnect(config.conn_info.hostip,config.conn_info.hostport);
|
||||
c = redisConnectWrapper(config.conn_info.hostip, config.conn_info.hostport,
|
||||
config.connect_timeout);
|
||||
if (!c->err && config.tls) {
|
||||
const char *err = NULL;
|
||||
if (cliSecureConnection(c, config.sslconfig, &err) == REDIS_ERR && err) {
|
||||
@ -2648,6 +2651,15 @@ static int parseOptions(int argc, char **argv) {
|
||||
fprintf(stderr, "Invalid server port.\n");
|
||||
exit(1);
|
||||
}
|
||||
} else if (!strcmp(argv[i],"-t") && !lastarg) {
|
||||
char *eptr;
|
||||
double seconds = strtod(argv[++i], &eptr);
|
||||
if (eptr[0] != '\0' || isnan(seconds) || seconds < 0.0) {
|
||||
fprintf(stderr, "Invalid connection timeout for -t.\n");
|
||||
exit(1);
|
||||
}
|
||||
config.connect_timeout.tv_sec = (long long)seconds;
|
||||
config.connect_timeout.tv_usec = ((long long)(seconds * 1000000)) % 1000000;
|
||||
} else if (!strcmp(argv[i],"-s") && !lastarg) {
|
||||
config.hostsocket = argv[++i];
|
||||
} else if (!strcmp(argv[i],"-r") && !lastarg) {
|
||||
@ -3011,6 +3023,8 @@ static void usage(int err) {
|
||||
"Usage: redis-cli [OPTIONS] [cmd [arg [arg ...]]]\n"
|
||||
" -h <hostname> Server hostname (default: 127.0.0.1).\n"
|
||||
" -p <port> Server port (default: 6379).\n"
|
||||
" -t <timeout> Server connection timeout in seconds (decimals allowed).\n"
|
||||
" Default timeout is 0, meaning no limit, depending on the OS.\n"
|
||||
" -s <socket> Server socket (overrides hostname and port).\n"
|
||||
" -a <password> Password to use when connecting to the server.\n"
|
||||
" You can also use the " REDIS_CLI_AUTH_ENV " environment\n"
|
||||
@ -4072,7 +4086,7 @@ cleanup:
|
||||
|
||||
static int clusterManagerNodeConnect(clusterManagerNode *node) {
|
||||
if (node->context) redisFree(node->context);
|
||||
node->context = redisConnect(node->ip, node->port);
|
||||
node->context = redisConnectWrapper(node->ip, node->port, config.connect_timeout);
|
||||
if (!node->context->err && config.tls) {
|
||||
const char *err = NULL;
|
||||
if (cliSecureConnection(node->context, config.sslconfig, &err) == REDIS_ERR && err) {
|
||||
@ -7897,7 +7911,7 @@ static int clusterManagerCommandImport(int argc, char **argv) {
|
||||
char *reply_err = NULL;
|
||||
redisReply *src_reply = NULL;
|
||||
// Connect to the source node.
|
||||
redisContext *src_ctx = redisConnect(src_ip, src_port);
|
||||
redisContext *src_ctx = redisConnectWrapper(src_ip, src_port, config.connect_timeout);
|
||||
if (src_ctx->err) {
|
||||
success = 0;
|
||||
fprintf(stderr,"Could not connect to Redis at %s:%d: %s.\n", src_ip,
|
||||
@ -9832,6 +9846,8 @@ int main(int argc, char **argv) {
|
||||
memset(&config.sslconfig, 0, sizeof(config.sslconfig));
|
||||
config.conn_info.hostip = sdsnew("127.0.0.1");
|
||||
config.conn_info.hostport = 6379;
|
||||
config.connect_timeout.tv_sec = 0;
|
||||
config.connect_timeout.tv_usec = 0;
|
||||
config.hostsocket = NULL;
|
||||
config.repeat = 1;
|
||||
config.interval = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user