From de2f13086b715c4f5f3d8c7ecff3c19480945244 Mon Sep 17 00:00:00 2001 From: max607 <63913351+max607@users.noreply.github.com> Date: Fri, 10 Jul 2026 09:05:45 +0200 Subject: [PATCH] fix(db_perform_request/response): refresh bearer token manually with margin --- R/request-helpers.R | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/R/request-helpers.R b/R/request-helpers.R index 064c0e14..1631131e 100644 --- a/R/request-helpers.R +++ b/R/request-helpers.R @@ -123,6 +123,7 @@ db_req_error_body <- function(resp) { #' @family Request Helpers db_perform_request <- function(req, ...) { req |> + req_refresh_token_margin() |> httr2::req_error(body = db_req_error_body) |> httr2::req_perform() |> httr2::resp_body_json(...) @@ -136,10 +137,34 @@ db_perform_request <- function(req, ...) { #' @family Request Helpers db_perform_response <- function(req, ...) { req |> + req_refresh_token_margin() |> httr2::req_error(body = db_req_error_body) |> httr2::req_perform(...) } +#' Clear the cached token if it is within `margin` seconds of exipry +#' +#' Databricks rejects tokens within 30s of `expires_at`. httr2's +#' client-credentials flow only refreshes at `expires_at`, leaving a rejection +#' window. Preemptively clear the cached token when it is within `margin` +#' seconds of expiry so the next perfom re-mints it. +#' +#' @family Request Helpers +req_refresh_token_margin <- function(req, margin = 300) { + auth <- req$policies$auth_sign + if (is.null(auth)) { + return(req) + } + tok <- tryCatch(auth$cache$get(), error = \(e) NULL) + if (is.null(tok) || is.null(tok$expires_at)) { + return(req) + } + if (tok$expires_at - unclass(Sys.time()) < margin) { + auth$cache$clear() + } + req +} + #' Generate Request JSON #' #' @param req a httr2 request, ideally from [db_request()].