Repeatedly evaluate an expression until a condition is met or timeout is exceeded.

retry(
  expr,
  upon = "error",
  when = NULL,
  until = NULL,
  envir = parent.frame(),
  silent = FALSE,
  timeout = Inf,
  max_tries = Inf,
  interval = 0.1,
  later_run_now = FALSE
)

Arguments

expr

an expression to be evaluated, supports quasiquotation.

upon

a vector of condition classes. The expression will be evaluated again after the delay if a condition is thrown. See the classes parameter of rlang::catch_cnd.

when

regular expression pattern that matches the message of the condition. It is used to decide if we need to evaluate expr.

until

a function of two arguments. This function is used to check if we need to evaluate expr. The first argument is the result of expr and the second argument is the condition thrown when expr was evaluated. It could be also a one sided formula that is later converted to a function using rlang::as_function.

envir

the environment in which the expression is to be evaluated.

silent

suppress messages and warnings

timeout

raise an error if this amount of time in seconds has passed.

max_tries

maximum number of attempts

interval

delay between retries.

later_run_now

execute later::run_now() periodically when later is loaded?

Examples

retry(10, until = ~TRUE)  # returns immediately
#> [1] 10

f <- function(x) {
    if (runif(1) < 0.9) {
        stop("random error")
    }
    x + 1
}
# keep retring when there is a random error
retry(f(1), when = "random error")
#> [1] 2
# keep retring until a condition is met
retry(f(1), until = function(val, cnd) val == 2)
#> [1] 2
# or using one sided formula
retry(f(1), until = ~ . == 2)
#> [1] 2

try({
  # it doesn't capture the error of "a" + 1
  retry(f("a"), when = "random error")
})
#> Error in x + 1 : non-numeric argument to binary operator

try({
  # an error is raised after 1 second
  retry(stop("foo"), when = "foo", timeout = 1)
})
#> Error in retry(stop("foo"), when = "foo", timeout = 1) : 
#>   timeout exceeded.

try({
  # timeout also works for indefinite R code
  retry(while(TRUE) {}, until = ~FALSE, timeout = 1)
})
#> Error in retry(while (TRUE) { : timeout exceeded.