Skip to content

Commit 72bcdef

Browse files
committed
Implement connect with timeout
1 parent 5b24b02 commit 72bcdef

File tree

7 files changed

+51
-18
lines changed

7 files changed

+51
-18
lines changed

.Rbuildignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@
2121
^docs$
2222
^doc$
2323
^Meta$
24+
^\.vscode$

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,6 @@ autobrew
1717
docs/
1818
doc
1919
Meta
20+
.vscode/
21+
*.o
22+
*.so

R/config.R

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
##' \code{SELECT}. Do not use in a redis clustering context.
2424
##' (default: \code{NULL}; i.e., don't switch).}
2525
##'
26+
##' \item{\code{timeout}}{The maximum number of milliseconds to wait for the
27+
##' connection to be established. (default: \code{NULL}; i.e. wait forever).}
28+
##'
2629
##' }
2730
##'
2831
##' The way that configuration options are resolved follows the design
@@ -70,7 +73,8 @@ redis_config <- function(..., config = list(...)) {
7073
port = as.integer(Sys_getenv("REDIS_PORT", 6379L)),
7174
path = NULL,
7275
password = NULL,
73-
db = NULL)
76+
db = NULL,
77+
timeout = NULL)
7478
dots <- list(...)
7579
if (length(dots) > 0L && !identical(dots, config)) {
7680
warning("Ignoring dots in favour of config")

R/redis.R

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
## from user code; see the functions in connection.R for what to use.
55
redis_connect <- function(config) {
66
if (config$scheme == "redis") {
7-
ptr <- redis_connect_tcp(config$host, config$port)
7+
ptr <- redis_connect_tcp(config$host, config$port, config$timeout)
88
} else {
9-
ptr <- redis_connect_unix(config$path)
9+
ptr <- redis_connect_unix(config$path, config$timeout)
1010
}
1111
if (!is.null(config$password)) {
1212
redis_command(ptr, c("AUTH", config$password))
@@ -17,12 +17,12 @@ redis_connect <- function(config) {
1717
ptr
1818
}
1919

20-
redis_connect_tcp <- function(host, port) {
21-
.Call(Credux_redis_connect, host, as.integer(port))
20+
redis_connect_tcp <- function(host, port, timeout) {
21+
.Call(Credux_redis_connect, host, as.integer(port), as.integer(timeout))
2222
}
2323

24-
redis_connect_unix <- function(path) {
25-
.Call(Credux_redis_connect_unix, path)
24+
redis_connect_unix <- function(path, timeout) {
25+
.Call(Credux_redis_connect_unix, path, as.integer(timeout))
2626
}
2727

2828
redis_command <- function(ptr, command) {

src/connection.c

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,23 @@ static void redis_finalize(SEXP extPtr);
55
char * string_duplicate(const char * x);
66

77
// API functions first:
8-
SEXP redux_redis_connect(SEXP host, SEXP port) {
9-
redisContext *context = redisConnect(CHAR(STRING_ELT(host, 0)),
10-
INTEGER(port)[0]);
11-
if (context == NULL) {
8+
SEXP redux_redis_connect(SEXP host, SEXP port, SEXP timeout) {
9+
redisContext *context;
10+
if (LENGTH(timeout) == 0)
11+
{
12+
context = redisConnect(CHAR(STRING_ELT(host, 0)),
13+
INTEGER(port)[0]);
14+
}
15+
else
16+
{
17+
int timeout_ms = INTEGER(timeout)[0];
18+
struct timeval tvout = {timeout_ms / 1000,
19+
(timeout_ms % 1000) * 1000};
20+
context = redisConnectWithTimeout(CHAR(STRING_ELT(host, 0)),
21+
INTEGER(port)[0], tvout);
22+
}
23+
if (context == NULL)
24+
{
1225
error("Creating context failed catastrophically [tcp]"); // # nocov
1326
}
1427
if (context->err != 0) {
@@ -22,9 +35,21 @@ SEXP redux_redis_connect(SEXP host, SEXP port) {
2235
return extPtr;
2336
}
2437

25-
SEXP redux_redis_connect_unix(SEXP path) {
26-
redisContext *context = redisConnectUnix(CHAR(STRING_ELT(path, 0)));
27-
if (context == NULL) {
38+
SEXP redux_redis_connect_unix(SEXP path, SEXP timeout) {
39+
redisContext *context;
40+
if (LENGTH(timeout) == 0)
41+
{
42+
context = redisConnectUnix(CHAR(STRING_ELT(path, 0)));
43+
}
44+
else
45+
{
46+
int timeout_ms = INTEGER(timeout)[0];
47+
struct timeval tvout = {timeout_ms / 1000,
48+
(timeout_ms % 1000) * 1000};
49+
context = redisConnectUnixWithTimeout(CHAR(STRING_ELT(path, 0)), tvout);
50+
}
51+
if (context == NULL)
52+
{
2853
error("Creating context failed catastrophically [unix]"); // # nocov
2954
}
3055
if (context->err != 0) {

src/connection.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
#include <hiredis.h>
44
#include <stdbool.h>
55

6-
SEXP redux_redis_connect(SEXP host, SEXP port);
7-
SEXP redux_redis_connect_unix(SEXP path);
6+
SEXP redux_redis_connect(SEXP host, SEXP port, SEXP timeout);
7+
SEXP redux_redis_connect_unix(SEXP path, SEXP timeout);
88

99
SEXP redux_redis_command(SEXP extPtr, SEXP cmd);
1010

src/registration.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
#include <Rversion.h>
99

1010
static const R_CallMethodDef callMethods[] = {
11-
{"Credux_redis_connect", (DL_FUNC) &redux_redis_connect, 2},
12-
{"Credux_redis_connect_unix", (DL_FUNC) &redux_redis_connect_unix, 1},
11+
{"Credux_redis_connect", (DL_FUNC) &redux_redis_connect, 3},
12+
{"Credux_redis_connect_unix", (DL_FUNC) &redux_redis_connect_unix, 2},
1313

1414
{"Credux_redis_command", (DL_FUNC) &redux_redis_command, 2},
1515

0 commit comments

Comments
 (0)