web-dev-qa-db-fra.com

Augmenter le temps avant que l'API tidyverse OAuth token expire lors de l'utilisation de bigquery?

Quand en utilisant bigrquery de R , l'API tidyverse demande une authentification, qui, une fois fournie, permet d'accéder à bigquery depuis la session R. Le téléchargement des résultats peut prendre du temps, et si le jeton oauth expire au milieu du transfert, le téléchargement échoue:

Erreur: informations d'identification non valides [authError]

Exemple de code

# install.packages("tidyverse"); install.packages('bigrquery')
Sys.setenv(BIGQUERY_TEST_PROJECT="your-gcp-project-id") 
library(tidyverse)
library(dbplyr)
library(bigrquery)

billing <- bq_test_project()

connection <- dbConnect(
  bigrquery::bigquery(),
  project = "your-gcp-project-id",
  dataset = "dataset-name",
  billing = billing
)

mytable <- tbl(connection, "mytable")

mytable %>%
  -- some heavy dplyr wrangling --
  %>% collect()

Quels retours

Running job [/] 20s
Complete
Billed 400GB
Downloading 230,000,000 rows
Downloading data [=====--------] 28% ETA: 24h

mais après un certain temps

Error: Invalid Credentials [authError]

Question

Comment la durée avant l'expiration du jeton 0Auth peut-elle être augmentée?

9
stevec

Pas une réponse complète, mais les détails de mes recherches jusqu'à présent pour éviter aux gens de revenir sur mes pas.

Le délai d'attente ne semble pas contrôlable via dbplyr

  • dbconnect accepte à la fois le pilote et les arguments à transmettre au pilote ( documentation ): dbConnect(drv, ...).
  • Pour certains types de connexion, les arguments supplémentaires peuvent inclure timeout. Ce problème a un exemple utilisant Cassandra: con <- dbConnect(odbc::odbc(), "Cassandra (DSN)", timeout = 10).
  • Cependant, timeout ne semble pas être pris en charge comme argument pour bigquery. La documentation liste les arguments suivants (project, dataset, billing, page_size, quiet, use_legacy_sql, bigint) et note que les autres arguments sont actuellement ignorés.

Compte tenu de ce qui précède, il semble peu probable que le délai d'expiration puisse être contrôlé par R via dbplyr, DBI ou la connexion.

Diviser la requête en plusieurs requêtes plus courtes

Bien que ce ne soit pas une préférence de OP (les commentaires le précisent), il s'agit toujours d'une solution potentielle. J'utilise une approche de filtrage basée sur une colonne d'identifiant unique, avec une fonction wrapper pour réduire une partie de l'encombrement supplémentaire:

reconnect <- function(jj){
  if(exists("connection"))
    dbDisconnect(connection) # avoids multiple concurrent connections

  print(paste0(as.character(Sys.time()),"-- modulo ",jj," begun")) # track progress

  connection <- dbConnect(
    bigrquery::bigquery(),
    project = "your-gcp-project-id",
    dataset = "dataset-name",
    billing = billing
  )

  mytable <- tbl(connection, "mytable") %>%
    filter(unique_id %% NUM_SUBSETS == jj) # filter to subset, requires unique_id

  # assignment into the parent environment
  assign("connection", connection, envir = parent.frame())
  assign("mytable ", mytable , envir = parent.frame())
}

On itère ensuite comme suit:

## parameters
DEVELOPMENT_MODE = FALSE
NUM_SUBSETS = 50

## subset
modulo = if(DEVELOPMENT_MODE){ modulo = 0 # only one if development mode
} else { modulo = 0:(NUM_SUBSETS-1) # otherwise all of them
}

results = data.frame()

for(jj in modulo){
  reconnect(jj)

  these_results = mytable %>%
    -- some heavy dplyr wrangling --
    %>% collect()

  results = rbind(results, these_results)
}

J'ai mis DEVELOPER_MODE à true lors du test/développement et à false lorsque je veux que tout fonctionne.

Autres pistes à considérer

  • Vérifiez si le délai d'expiration peut être défini/contrôlé dans le compte bigquery (s'il ne peut pas être contrôlé via R).
  • Étude de la complexité -- heavy dplyr wrangling here -- est. Étant donné que dbplyr ne traduit pas de code SQL très efficace, dans mon travail sur le serveur SQL, la sauvegarde de tables intermédiaires a réduit les heures d'exécution. Étant donné que le téléchargement de 10 Go devrait être beaucoup plus rapide que plusieurs heures, le goulot d'étranglement pourrait être une grosse requête conduisant toutes les disputes à la volée (et que l'exécution initiale de 20 secondes se fait avec une évaluation paresseuse). This lien suggère qu'il y a une limite de six heures sur la durée d'une seule exécution.
2
Simon.S.A.