From a71cdab42d126af590f9d8748231621e626d61f0 Mon Sep 17 00:00:00 2001 From: JsLth Date: Fri, 20 Sep 2024 02:05:29 +0200 Subject: [PATCH] clear runtime cache each time a new instance is mounted --- R/local.R | 5 +++++ R/sample.R | 7 ++++--- R/utils-ors.R | 42 +++++++++++++++++++++++++++++++++++++++--- man/get_instance.Rd | 20 ++++++++++++++++++++ man/ors_sample.Rd | 20 ++++++++++++++++++++ 5 files changed, 88 insertions(+), 6 deletions(-) diff --git a/R/local.R b/R/local.R index a3e3046..5ba02a6 100644 --- a/R/local.R +++ b/R/local.R @@ -323,6 +323,11 @@ ORSLocal <- R6Class( .prompts = TRUE, .alive = TRUE, .mount = function() { + if (!self$is_mounted()) { + # if a new instance is mounted, clear runtime cache + clear_runtime_cache() + } + # no idea why this is necessary but when just using envir = rors_cache # $.mount() uses a different environment than defined globally rors_cache <- get("rors_cache", envir = asNamespace("rors")) diff --git a/R/sample.R b/R/sample.R index ecb5166..5bd922d 100644 --- a/R/sample.R +++ b/R/sample.R @@ -38,6 +38,7 @@ #' needs to be enabled on other servers. \code{ors_guess} can make a lot of #' requests and might not be feasible in many situations. #' +#' @inheritSection get_instance Caching #' #' @export #' @@ -85,7 +86,7 @@ ors_sample <- function(size, get_extract_boundaries <- function(instance = NULL, force = FALSE, verbose = TRUE) { - recover_from_cache("extract_boundaries", force = force) + recover_from_cache("poly", force = force) instance <- instance %||% get_instance() if (ors_is_local(instance)) { @@ -119,7 +120,7 @@ get_extract_boundaries <- function(instance = NULL, poly <- proc$get_result() } else { tip <- paste( - "{.code get_extract_boundaries} is not usable for unkown remote", + "{.fn get_extract_boundaries} is not usable for unkown remote", "servers as the extract boundaries cannot easily be determined.", "Consider using {.fn ors_guess}." ) @@ -129,7 +130,7 @@ get_extract_boundaries <- function(instance = NULL, ) } - assign("extract_boundaries", poly, envir = rors_cache) + store_in_cache(poly) poly } diff --git a/R/utils-ors.R b/R/utils-ors.R index 7d80b8e..160f77f 100644 --- a/R/utils-ors.R +++ b/R/utils-ors.R @@ -4,11 +4,29 @@ rors_cache <- new.env(parent = emptyenv()) recover_from_cache <- function(obj, force = FALSE) { obj <- get0(obj, envir = rors_cache) if (!is.null(obj) && !force) { + obj <- obj[[1]] return_from_parent(obj, .envir = parent.frame()) } } +store_in_cache <- function(obj) { + name <- deparse(substitute(obj)) + obj <- list(obj) + class(obj) <- "rors_runtime_cache" + assign(name, obj, envir = rors_cache) +} + + +clear_runtime_cache <- function() { + is_runtime <- eapply(rors_cache, function(x) { + inherits(x, "rors_runtime_cache") + }) + cached <- names(is_runtime)[unlist(is_runtime)] + rm(list = cached, envir = rors_cache) +} + + #' Utility functions #' #' Utility functions to aid the setup of local instances. @@ -51,6 +69,24 @@ recover_from_cache <- function(obj, force = FALSE) { #' @seealso \code{\link{ors_instance}} #' @export #' +#' @section Caching: +#' +#' The following functions make use of a "runtime" caching system: +#' \code{ors_ready()}, \code{ors_status()}, \code{get_profiles()}, +#' \code{get_extract_boundaries()}, \code{ors_sample()}. This means that, +#' if \code{force = FALSE}, previously generated output is re-used instead +#' of sending new requests. This can be particularly useful in automated +#' workflows like loops where speed is important. When run directly, caching +#' should not be necessary, which is why \code{force = FALSE} is the default +#' of most of these functions (except \code{get_extract_boundaries()} because +#' it deals with potentially much larger amounts of data). +#' +#' "Runtime" in this context refers to the runtime of an ORS instance, i.e. +#' the time after it is started. Cached results should only be valid for a +#' specific runtime and discarded afterwards. After starting or stopping +#' an instance or when mounting a new instance, the runtime cache is cleared +#' so that fresh requests must be made. +#' #' @examples #' # initialize an ORS instance #' ors <- ors_instance(dir = tempdir(), dry = TRUE) @@ -147,7 +183,7 @@ ors_status <- function(url = NULL, force = TRUE) { ) } class(status) <- "ors_status" - assign("status", status, envir = rors_cache) + store_in_cache(status) status } @@ -171,7 +207,7 @@ get_profiles <- function(url = NULL, force = TRUE) { ors_ready <- function(url = NULL, force = TRUE, error = FALSE) { ready <- get0("ready", envir = rors_cache) if (isTRUE(ready)) { - t <- recover_from_cache("ready", force = force) + recover_from_cache("ready", force = force) } url <- url %||% get_ors_url() @@ -204,7 +240,7 @@ ors_ready <- function(url = NULL, force = TRUE, error = FALSE) { ) } - assign("ready", ready, envir = rors_cache) + store_in_cache(ready) ready } diff --git a/man/get_instance.Rd b/man/get_instance.Rd index 1576b2f..6f818df 100644 --- a/man/get_instance.Rd +++ b/man/get_instance.Rd @@ -60,6 +60,26 @@ the active profiles of the mounted service. session. } } +\section{Caching}{ + + +The following functions make use of a "runtime" caching system: +\code{ors_ready()}, \code{ors_status()}, \code{get_profiles()}, +\code{get_extract_boundaries()}, \code{ors_sample()}. This means that, +if \code{force = FALSE}, previously generated output is re-used instead +of sending new requests. This can be particularly useful in automated +workflows like loops where speed is important. When run directly, caching +should not be necessary, which is why \code{force = FALSE} is the default +of most of these functions (except \code{get_extract_boundaries()} because +it deals with potentially much larger amounts of data). + +"Runtime" in this context refers to the runtime of an ORS instance, i.e. +the time after it is started. Cached results should only be valid for a +specific runtime and discarded afterwards. After starting or stopping +an instance or when mounting a new instance, the runtime cache is cleared +so that fresh requests must be made. +} + \examples{ # initialize an ORS instance ors <- ors_instance(dir = tempdir(), dry = TRUE) diff --git a/man/ors_sample.Rd b/man/ors_sample.Rd index c55a12a..23b44cb 100644 --- a/man/ors_sample.Rd +++ b/man/ors_sample.Rd @@ -72,6 +72,26 @@ accesses the snap endpoint which also does not work on the public API and needs to be enabled on other servers. \code{ors_guess} can make a lot of requests and might not be feasible in many situations. } +\section{Caching}{ + + +The following functions make use of a "runtime" caching system: +\code{ors_ready()}, \code{ors_status()}, \code{get_profiles()}, +\code{get_extract_boundaries()}, \code{ors_sample()}. This means that, +if \code{force = FALSE}, previously generated output is re-used instead +of sending new requests. This can be particularly useful in automated +workflows like loops where speed is important. When run directly, caching +should not be necessary, which is why \code{force = FALSE} is the default +of most of these functions (except \code{get_extract_boundaries()} because +it deals with potentially much larger amounts of data). + +"Runtime" in this context refers to the runtime of an ORS instance, i.e. +the time after it is started. Cached results should only be valid for a +specific runtime and discarded afterwards. After starting or stopping +an instance or when mounting a new instance, the runtime cache is cleared +so that fresh requests must be made. +} + \examples{ \dontrun{ # ORS sampling only works with a local instance