From c39aef2a798cb131f1bc3b9ab4a8c0b3753d05d5 Mon Sep 17 00:00:00 2001 From: Ramanth Addala Date: Tue, 8 Sep 2020 12:04:32 +0530 Subject: [PATCH] feat(r): retry configuration for status codes (#5925) * feat(r): retry configuration for status codes * fix(r) : fixing review comments --- .../src/main/resources/r/api_client.mustache | 42 ++++++++++++++++++- samples/client/petstore/R/R/api_client.R | 42 ++++++++++++++++++- 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/r/api_client.mustache b/modules/openapi-generator/src/main/resources/r/api_client.mustache index 8a403315fa1..0c037fd5575 100644 --- a/modules/openapi-generator/src/main/resources/r/api_client.mustache +++ b/modules/openapi-generator/src/main/resources/r/api_client.mustache @@ -24,6 +24,8 @@ #' @field apiKeys #' @field accessToken #' @field timeout Default timeout in seconds +#' @field retryStatusCodes vector of status codes to retry +#' @field maxRetryAttempts maximum number of retries for the status codes #' @importFrom httr add_headers accept timeout content {{#useRlangExceptionHandling}} #' @importFrom rlang abort @@ -48,8 +50,12 @@ ApiClient <- R6::R6Class( accessToken = NULL, # Time Out (seconds) timeout = NULL, + # Vector of status codes to retry + retryStatusCodes=NULL, + # Maximum number of retry attempts for the retry status codes + maxRetryAttempts = NULL, # constructor - initialize = function(basePath=NULL, userAgent=NULL, defaultHeaders=NULL, username=NULL, password=NULL, apiKeys=NULL, accessToken=NULL, timeout=NULL){ + initialize = function(basePath=NULL, userAgent=NULL, defaultHeaders=NULL, username=NULL, password=NULL, apiKeys=NULL, accessToken=NULL, timeout=NULL, retryStatusCodes=NULL, maxRetryAttempts=NULL){ if (!is.null(basePath)) { self$basePath <- basePath } @@ -83,8 +89,42 @@ ApiClient <- R6::R6Class( if (!is.null(timeout)) { self$timeout <- timeout } + + if (!is.null(retryStatusCodes)) { + self$retryStatusCodes <- retryStatusCodes + } + + if (!is.null(maxRetryAttempts)) { + self$maxRetryAttempts <- maxRetryAttempts + } }, + CallApi = function(url, method, queryParams, headerParams, body, ...){ + + resp <- self$Execute(url, method, queryParams, headerParams, body, ...) + statusCode <- httr::status_code(resp) + + if (is.null(self$maxRetryAttempts)) { + self$maxRetryAttempts = 3 + } + + if (!is.null(self$retryStatusCodes)) { + + for (i in 1 : self$maxRetryAttempts) { + if (statusCode %in% self$retryStatusCodes) { + Sys.sleep((2 ^ i) + stats::runif(n = 1, min = 0, max = 1)) + resp <- self$Execute(url, method, queryParams, headerParams, body, ...) + statusCode <- httr::status_code(resp) + } else { + break; + } + } + } + + resp + }, + + Execute = function(url, method, queryParams, headerParams, body, ...){ headers <- httr::add_headers(c(headerParams, self$defaultHeaders)) {{! Adding timeout that can be set at the apiClient object level}} diff --git a/samples/client/petstore/R/R/api_client.R b/samples/client/petstore/R/R/api_client.R index fe61ecfbde9..d2682119f93 100644 --- a/samples/client/petstore/R/R/api_client.R +++ b/samples/client/petstore/R/R/api_client.R @@ -31,6 +31,8 @@ #' @field apiKeys #' @field accessToken #' @field timeout Default timeout in seconds +#' @field retryStatusCodes vector of status codes to retry +#' @field maxRetryAttempts maximum number of retries for the status codes #' @importFrom httr add_headers accept timeout content #' @export ApiClient <- R6::R6Class( @@ -52,8 +54,12 @@ ApiClient <- R6::R6Class( accessToken = NULL, # Time Out (seconds) timeout = NULL, + # Vector of status codes to retry + retryStatusCodes=NULL, + # Maximum number of retry attempts for the retry status codes + maxRetryAttempts = NULL, # constructor - initialize = function(basePath=NULL, userAgent=NULL, defaultHeaders=NULL, username=NULL, password=NULL, apiKeys=NULL, accessToken=NULL, timeout=NULL){ + initialize = function(basePath=NULL, userAgent=NULL, defaultHeaders=NULL, username=NULL, password=NULL, apiKeys=NULL, accessToken=NULL, timeout=NULL, retryStatusCodes=NULL, maxRetryAttempts=NULL){ if (!is.null(basePath)) { self$basePath <- basePath } @@ -87,8 +93,42 @@ ApiClient <- R6::R6Class( if (!is.null(timeout)) { self$timeout <- timeout } + + if (!is.null(retryStatusCodes)) { + self$retryStatusCodes <- retryStatusCodes + } + + if (!is.null(maxRetryAttempts)) { + self$maxRetryAttempts <- maxRetryAttempts + } }, + CallApi = function(url, method, queryParams, headerParams, body, ...){ + + resp <- self$Execute(url, method, queryParams, headerParams, body, ...) + statusCode <- httr::status_code(resp) + + if (is.null(self$maxRetryAttempts)) { + self$maxRetryAttempts = 3 + } + + if (!is.null(self$retryStatusCodes)) { + + for (i in 1 : self$maxRetryAttempts) { + if (statusCode %in% self$retryStatusCodes) { + Sys.sleep((2 ^ i) + stats::runif(n = 1, min = 0, max = 1)) + resp <- self$Execute(url, method, queryParams, headerParams, body, ...) + statusCode <- httr::status_code(resp) + } else { + break; + } + } + } + + resp + }, + + Execute = function(url, method, queryParams, headerParams, body, ...){ headers <- httr::add_headers(c(headerParams, self$defaultHeaders)) httpTimeout <- NULL