Skip to content

Commit

Permalink
Merge pull request #248 from cmu-delphi/ds/cache
Browse files Browse the repository at this point in the history
fix: make default cache directory R version portable
  • Loading branch information
dshemetov authored Feb 24, 2024
2 parents 6a9c29a + 4ef7429 commit aa6c641
Show file tree
Hide file tree
Showing 15 changed files with 58 additions and 35 deletions.
11 changes: 6 additions & 5 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

Please:

- [ ] Make sure this PR is against "dev", not "main".
- [ ] Make sure this PR is against "dev", not "main" (unless this is a release
PR).
- [ ] Request a review from one of the current epiprocess main reviewers:
brookslogan, nmdefries.
- [ ] Makes sure to bump the version number in `DESCRIPTION` and `NEWS.md`.
Always increment the patch version number (the third number), unless you are
making a release PR from dev to main, in which case increment the minor
version number (the second number).
- [ ] Makes sure to bump the version number in `DESCRIPTION`. Always increment
the patch version number (the third number), unless you are making a
release PR from dev to main, in which case increment the minor version
number (the second number).
- [ ] Describe changes made in NEWS.md, making sure breaking changes
(backwards-incompatible changes to the documented interface) are noted.
Collect the changes under the next release number (e.g. if you are on
Expand Down
8 changes: 6 additions & 2 deletions .github/workflows/document.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,12 @@ jobs:
- name: Install dependencies
uses: r-lib/actions/setup-r-dependencies@v2
with:
extra-packages: any::roxygen2
needs: roxygen2
extra-packages: |
any::devtools
any::roxygen2
needs: |
devtools
roxygen2
- name: Document
run: roxygen2::roxygenise()
Expand Down
3 changes: 2 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: epidatr
Type: Package
Title: Client for Delphi's 'Epidata' API
Version: 1.0.1
Version: 1.0.2
Date: 2023-12-07
Authors@R:
c(
Expand Down Expand Up @@ -35,6 +35,7 @@ Imports:
MMWRweek,
purrr,
openssl,
rappdirs,
readr,
tibble,
usethis,
Expand Down
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
- `pvt_twitter` and `pub_wiki` now use `time_type` and `time_values` args instead of mutually exclusive `dates` and `epiweeks` (#236). This matches the interface of the `pub_covidcast` endpoint.
- All endpoints now support the use of "\*" as a wildcard to fetch all dates or epiweeks (#234).
- Fixed bug with NAs when parsing ints (#243).
- Updated the default `timeout_seconds` to 15 minutes to allow large queries by default.

# epidatr 1.0.0

Expand Down
18 changes: 12 additions & 6 deletions R/cache.R
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ cache_environ$epidatr_cache <- NULL
#' )
#'
#' @param cache_dir the directory in which the cache is stored. By default, this
#' is `tools::R_user_dir()` if on R 4.0+, but must be specified for earlier
#' versions of R. The path can be either relative or absolute. The
#' environmental variable is `EPIDATR_CACHE_DIR`.
#' is `rappdirs::user_cache_dir("R", version = "epidatr")`. The path can be
#' either relative or absolute. The environmental variable is
#' `EPIDATR_CACHE_DIR`.
#' @param days the maximum length of time in days to keep any particular cached
#' call. By default this is `1`. The environmental variable is
#' `EPIDATR_CACHE_MAX_AGE_DAYS`.
Expand All @@ -103,8 +103,8 @@ set_cache <- function(cache_dir = NULL,
max_size = NULL,
logfile = NULL,
confirm = TRUE) {
if (is.null(cache_dir) && sessionInfo()$R.version$major >= 4) {
cache_dir <- Sys.getenv("EPIDATR_CACHE_DIR", unset = tools::R_user_dir("epidatr"))
if (is.null(cache_dir)) {
cache_dir <- Sys.getenv("EPIDATR_CACHE_DIR", unset = rappdirs::user_cache_dir("R", version = "epidatr"))
} else if (is.null(cache_dir)) {
# earlier version, so no tools
cache_dir <- Sys.getenv("EPIDATR_CACHE_DIR")
Expand Down Expand Up @@ -154,7 +154,6 @@ set_cache <- function(cache_dir = NULL,
}
}


if (!cache_usable) {
print(glue::glue(
"The directory at {cache_dir} is not accessible; check permissions and/or use a different ",
Expand All @@ -168,6 +167,13 @@ set_cache <- function(cache_dir = NULL,
logfile = file.path(cache_dir, logfile)
)
}

cli::cli_inform(c(
"!" = "epidatr cache is being used (set env var EPIDATR_USE_CACHE=FALSE if not intended).",
"i" = "The cache directory is {cache_dir}.",
"i" = "The cache will be cleared after {days} days and will be pruned if it exceeds {max_size} MB.",
"i" = "The log of cache transactions is stored at {file.path(cache_dir, logfile)}."
))
}

#' Manually reset the cache, deleting all currently saved data and starting afresh
Expand Down
10 changes: 5 additions & 5 deletions R/epidatacall.R
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ create_epidata_call <- function(endpoint, params, meta = NULL,
}

#' @importFrom checkmate test_class test_list
request_arguments <- function(epidata_call, format_type, fields = NULL) {
request_arguments <- function(epidata_call, format_type, fields) {
stopifnot(inherits(epidata_call, "epidata_call"))
stopifnot(format_type %in% c("json", "csv", "classic"))
stopifnot(is.null(fields) || is.character(fields))
Expand Down Expand Up @@ -164,7 +164,7 @@ fetch_args_list <- function(
disable_date_parsing = FALSE,
disable_data_frame_parsing = FALSE,
return_empty = FALSE,
timeout_seconds = 30,
timeout_seconds = 15 * 60,
base_url = NULL,
dry_run = FALSE,
debug = FALSE,
Expand Down Expand Up @@ -288,7 +288,7 @@ fetch_classic <- function(epidata_call, fetch_args = fetch_args_list()) {
stopifnot(inherits(epidata_call, "epidata_call"))
stopifnot(inherits(fetch_args, "fetch_args"))

response_content <- request_impl(epidata_call, "classic", fetch_args$fields, fetch_args$timeout_seconds) %>%
response_content <- request_impl(epidata_call, "classic", fetch_args$timeout_seconds, fetch_args$fields) %>%
httr::content(as = "text", encoding = "UTF-8") %>%
jsonlite::fromJSON(simplifyDataFrame = !fetch_args$disable_data_frame_parsing)

Expand Down Expand Up @@ -318,7 +318,7 @@ fetch_debug <- function(epidata_call, fetch_args = fetch_args_list()) {
stopifnot(inherits(epidata_call, "epidata_call"))
stopifnot(inherits(fetch_args, "fetch_args"))

response <- request_impl(epidata_call, fetch_args$format_type, fetch_args$fields, fetch_args$timeout_seconds)
response <- request_impl(epidata_call, fetch_args$format_type, fetch_args$timeout_seconds, fetch_args$fields)
content <- httr::content(response, "text", encoding = "UTF-8")
content
}
Expand Down Expand Up @@ -366,7 +366,7 @@ with_base_url <- function(epidata_call, base_url) {
#' @importFrom httr stop_for_status content http_type
#' @importFrom xml2 read_html xml_find_all xml_text
#' @keywords internal
request_impl <- function(epidata_call, format_type, fields = NULL, timeout_seconds = 30) {
request_impl <- function(epidata_call, format_type, timeout_seconds, fields) {
stopifnot(inherits(epidata_call, "epidata_call"))
stopifnot(format_type %in% c("json", "csv", "classic"))

Expand Down
2 changes: 1 addition & 1 deletion R/request.R
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ join_url <- function(url, endpoint) {
#'
#' @importFrom httr RETRY
#' @keywords internal
do_request <- function(url, params, timeout_seconds = 30) {
do_request <- function(url, params, timeout_seconds) {
# don't retry in case of certain status codes
key <- get_api_key()
if (key != "") {
Expand Down
6 changes: 3 additions & 3 deletions man/clear_cache.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/do_request.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/fetch_args_list.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/request_impl.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions man/set_cache.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions tests/testthat/generate_test_data.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ epidata_call %>%

url <- full_url(epidata_call)
params <- request_arguments(epidata_call, "csv", NULL)
result <- do_request(url, params) %>% readr::write_rds(testthat::test_path("data/test-http401.rds"))
result <- do_request(url, params, timeout_seconds = 10 * 60) %>%
readr::write_rds(testthat::test_path("data/test-http401.rds"))

epidata_call <- pvt_afhsb(
auth = Sys.getenv("SECRET_API_AUTH_AFHSB"),
Expand All @@ -14,7 +15,8 @@ epidata_call <- pvt_afhsb(
)
url <- full_url(epidata_call)
params <- request_arguments(epidata_call, "csv", NULL)
response <- do_request(url, params) %>% readr::write_rds(testthat::test_path("data/test-http500.rds"))
response <- do_request(url, params, timeout_seconds = 10 * 60) %>%
readr::write_rds(testthat::test_path("data/test-http500.rds"))

epidata_call %>%
fetch_debug(format_type = "classic") %>%
Expand Down
14 changes: 11 additions & 3 deletions tests/testthat/test-epidatacall.R
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,23 @@ test_that("request_impl http errors", {
# see generate_test_data.R
do_request = function(...) readRDS(testthat::test_path("data/test-http401.rds")),
)
expect_error(response <- epidata_call %>% request_impl("csv"), class = "http_401")
expect_error(
response <- epidata_call %>%
request_impl("csv", timeout_seconds = 30, fields = NULL),
class = "http_401"
)

# should give a 500 error (the afhsb endpoint is removed)

# see generate_test_data.R
local_mocked_bindings(
do_request = function(...) readRDS(testthat::test_path("data/test-http500.rds"))
)
expect_error(response <- epidata_call %>% request_impl("csv"), class = "http_500")
expect_error(
response <- epidata_call %>%
request_impl("csv", timeout_seconds = 30, fields = NULL),
class = "http_500"
)
})

test_that("fetch_args", {
Expand All @@ -30,7 +38,7 @@ test_that("fetch_args", {
disable_date_parsing = FALSE,
disable_data_frame_parsing = FALSE,
return_empty = FALSE,
timeout_seconds = 30,
timeout_seconds = 15 * 60,
base_url = NULL,
dry_run = FALSE,
debug = FALSE,
Expand Down
2 changes: 1 addition & 1 deletion tests/testthat/test-request.R
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
test_that("requesting works", {
res <- do_request("https://httpbin.org/status/414", list())
res <- do_request("https://httpbin.org/status/414", list(), timeout_seconds = 10 * 60)
expect_equal(res$status_code, 414)
})

0 comments on commit aa6c641

Please sign in to comment.