bkelley9
bkelley9

Reputation: 21

Task Scheduler failing to auto-refresh stale OAuth token

I am using an R script and the package rdrop2 to automate the upload of a constantly updating file to Dropbox. The code works fine locally and will run in Task Scheduler as desired for 4 hours but then stops updating and "freezes", as Task Scheduler indicates that the task is "running" for an extended period of time. When I go into Task Scheduler and manually end and then run the task, it seems to fix itself and be fine for another four hours and then the same issue happens again

I suspect that this has something to do with the refreshable token I have set up with this code. For a while, I had any error messages being sent to an error_log file using sink (see below), and when this would happen the error_log file would read "Auto-refreshing stale OAuth token". I suspected that the sink function was what was stopping the code from continuing, as when this "error" happens in Rstudio the code continues to execute and performs the upload/download requests as expected, so I removed the sink but the problem persisted (for reference, when the task would run to completion the error_log would read something like "File biostats.csv uploaded as /auto_test/biostats.csv successfully at 2023-06-28T17:36:03Z").

Again, I am running this in task scheduler by executing Rscript.exe with my Rscript passed as the argument (I added Rscript.exe's location to the system environment PATH), and it performs fine most of the time, I just feel like it is getting hung up when it needs to refresh the stale token and I don't know how to fix it.

Here is the Rscript:

library(rdrop2)
library(httr)
library(dplyr)

setwd("C:/Users/benke/Documents/R Main Directory/Data Upload Automation")

error_log <- file("C:/Users/benke/Documents/R Main Directory/Data Upload Automation/error_log.Rout", 
                  open = "wt")

sink(error_log, type = "message")

#Set up refreshable access token, can pass this to any 'drop' function in 'dtoken' argument
.dstate <- new.env(parent = emptyenv())

drop_auth_RT <- function (new_user = FALSE, key = "placeholder", secret = "placeholder", cache = TRUE, rdstoken = NA) 
{
  if (new_user == FALSE & !is.na(rdstoken)) {
    if (file.exists(rdstoken)) {
      .dstate$token <- readRDS(rdstoken)
    }
    else {
      stop("token file not found")
    }
  }
  else {
    if (new_user && file.exists(".httr-oauth")) {
      message("Removing old credentials...")
      file.remove(".httr-oauth")
    }
    dropbox <- httr::oauth_endpoint(authorize = "https://www.dropbox.com/oauth2/authorize?token_access_type=offline",
                                    access = "https://api.dropbox.com/oauth2/token")
    # added "?token_access_type=offline" to the "authorize" parameter so that it can return an access token as well as a refresh token
    dropbox_app <- httr::oauth_app("dropbox", key, secret)
    dropbox_token <- httr::oauth2.0_token(dropbox, dropbox_app, 
                                          cache = cache)
    if (!inherits(dropbox_token, "Token2.0")) {
      stop("something went wrong, try again")
    }
    .dstate$token <- dropbox_token
  }
}

refreshable_token <- drop_auth_RT()

#Upload updated copy of file
drop_upload(file = "biostats.csv", path = "/auto_test",
            mode = "overwrite",
            dtoken = refreshable_token)

Upvotes: 0

Views: 268

Answers (1)

Tom Quigley
Tom Quigley

Reputation: 61

The same happens for me, and I use the same code snippet to get the refreshable token. The error I get is:

Auto-refreshing stale OAuth token.
<http_408 in drop_upload(file = ...

In my case, it always happens during that specific drop_upload call. So, my hack is to tryCatch that call and in the catch, call drop_auth() then drop_upload() again. I'm not sure that the drop_auth() call is even necessary. In any case, for me, this works every time.

tryCatch({
   drop_upload(file = local_path, path = db_path, mode = mode, dtoken = token)
   },
   error = function(e) {
      print(e)
      print(paste("Could not upload file:", file, "Trying again after re-auth."))
      drop_auth(rdstoken = "token.rds")  //same refreshable token as before
      drop_upload(file = local_path, path = db_path, mode = mode, dtoken = token)
   })

Upvotes: 0

Related Questions