diff --git a/NEWS.md b/NEWS.md index a80f2d3a..c5536bc3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,6 @@ # httr2 (development version) +* Functions that capture interrutps (like `req_perform_parallel()` and friends) are now easier to escape if they're called inside a loop: you can press Ctrl + C twice to guarantee an exit (#1810). * New `last_request_json()` and `last_response_json()` to conveniently see JSON bodies (#734). * `req_body_json_modify()` can now be used on a request with an empty body. * `resp_timing()` exposes timing information about the request measured by libcurl (@arcresu, #725). diff --git a/R/httr2-package.R b/R/httr2-package.R index a38694ec..3cdfe248 100644 --- a/R/httr2-package.R +++ b/R/httr2-package.R @@ -17,3 +17,4 @@ the$token_cache <- new_environment() the$last_response <- NULL the$last_request <- NULL the$pool_pollers <- new_environment() +the$last_interrupt <- 0 diff --git a/R/req-perform-iterative.R b/R/req-perform-iterative.R index 9c4cae39..a877f9c7 100644 --- a/R/req-perform-iterative.R +++ b/R/req-perform-iterative.R @@ -181,6 +181,8 @@ req_perform_iterative <- function( } }, interrupt = function(cnd) { + check_repeated_interrupt() + # interrupt might occur after i was incremented if (is.null(resps[[i]])) { i <<- i - 1 diff --git a/R/req-perform-parallel.R b/R/req-perform-parallel.R index 88fda143..9639d32a 100644 --- a/R/req-perform-parallel.R +++ b/R/req-perform-parallel.R @@ -91,6 +91,8 @@ req_perform_parallel <- function( tryCatch( queue$process(), interrupt = function(cnd) { + check_repeated_interrupt() + queue$queue_status <- "errored" queue$process() diff --git a/R/req-perform-sequential.R b/R/req-perform-sequential.R index f5607ba2..6c9a1ae3 100644 --- a/R/req-perform-sequential.R +++ b/R/req-perform-sequential.R @@ -92,6 +92,8 @@ req_perform_sequential <- function( } }, interrupt = function(cnd) { + check_repeated_interrupt() + resps <- resps[seq_len(i)] cli::cli_alert_warning( "Terminating iteration; returning {i} response{?s}." diff --git a/R/utils.R b/R/utils.R index 4e8005ab..7a779006 100644 --- a/R/utils.R +++ b/R/utils.R @@ -347,3 +347,13 @@ log_stream <- function(..., prefix = "<< ") { paste_c <- function(..., collapse = "") { paste0(c(...), collapse = collapse) } + +# Give user the get-out-of-jail-free card if interrupt-capturing function +# is wrapped inside a loop +check_repeated_interrupt <- function() { + if (as.double(Sys.time()) - the$last_interrupt < 1) { + cli::cli_alert_warning("Interrupting") + interrupt() + } + the$last_interrupt <- as.double(Sys.time()) +}