mirror of
https://github.com/rstudio/shiny.git
synced 2026-04-07 03:00:20 -04:00
Add 'missing' parameter to get()
This commit is contained in:
@@ -18,6 +18,11 @@
|
||||
#' return a different sentinel value, like \code{NULL}, or even throw an error
|
||||
#' on a cache miss.
|
||||
#'
|
||||
#' When the cache is created, you can supply a value for \code{missing}, which
|
||||
#' sets the default value to be returned for missing values. It can also be
|
||||
#' overridden when \code{get()} is called, by supplying a \code{missing}
|
||||
#' argument, as in \code{cache$get("mykey", missing = NULL)}.
|
||||
#'
|
||||
#' If your cache is configured so that \code{get()} returns a sentinel value
|
||||
#' to represent a cache miss, then \code{set} will also not allow you to store
|
||||
#' the sentinel value in the cache. It will throw an error if you attempt to
|
||||
@@ -106,9 +111,11 @@
|
||||
#' A disk cache object has the following methods:
|
||||
#'
|
||||
#' \describe{
|
||||
#' \item{\code{get(key)}}{
|
||||
#' \item{\code{get(key, missing)}}{
|
||||
#' Returns the value associated with \code{key}. If the key is not in the
|
||||
#' cache, this throws an error.
|
||||
#' cache, then it returns the value specified by \code{missing}. The
|
||||
#' default value for \code{missing} when the DiskCache object is created,
|
||||
#' but it can be overridden when \code{get()} is called.
|
||||
#' }
|
||||
#' \item{\code{set(key, value)}}{
|
||||
#' Stores the \code{key}-\code{value} pair in the cache.
|
||||
@@ -218,10 +225,9 @@ DiskCache <- R6Class("DiskCache",
|
||||
private$evict <- "fifo"
|
||||
}
|
||||
private$missing <- missing
|
||||
private$eval_missing <- is.language(missing)
|
||||
},
|
||||
|
||||
get = function(key) {
|
||||
get = function(key, missing = private$missing) {
|
||||
self$is_destroyed(throw = TRUE)
|
||||
validate_key(key)
|
||||
filename <- private$key_to_filename(key)
|
||||
@@ -239,10 +245,10 @@ DiskCache <- R6Class("DiskCache",
|
||||
}
|
||||
)
|
||||
if (read_error) {
|
||||
if (private$eval_missing) {
|
||||
return(eval(private$missing))
|
||||
if (is.language(missing)) {
|
||||
return(eval(missing))
|
||||
} else {
|
||||
return(private$missing)
|
||||
return(missing)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,7 +259,7 @@ DiskCache <- R6Class("DiskCache",
|
||||
set = function(key, value) {
|
||||
self$is_destroyed(throw = TRUE)
|
||||
validate_key(key)
|
||||
if (!private$eval_missing && identical(value, private$missing)) {
|
||||
if (!is.language(private$missing) && identical(value, private$missing)) {
|
||||
stop("Attempted to store sentinel value representing a missing key.")
|
||||
}
|
||||
|
||||
@@ -427,7 +433,6 @@ DiskCache <- R6Class("DiskCache",
|
||||
destroy_on_finalize = NULL,
|
||||
destroyed = FALSE,
|
||||
missing = NULL,
|
||||
eval_missing = NULL,
|
||||
|
||||
key_to_filename = function(key) {
|
||||
if (! (is.character(key) && length(key)==1) ) {
|
||||
|
||||
@@ -25,6 +25,11 @@
|
||||
#' return a different sentinel value, like \code{NULL}, or even throw an error
|
||||
#' on a cache miss.
|
||||
#'
|
||||
#' When the cache is created, you can supply a value for \code{missing}, which
|
||||
#' sets the default value to be returned for missing values. It can also be
|
||||
#' overridden when \code{get()} is called, by supplying a \code{missing}
|
||||
#' argument, as in \code{cache$get("mykey", missing = NULL)}.
|
||||
#'
|
||||
#' If your cache is configured so that \code{get()} returns a sentinel value
|
||||
#' to represent a cache miss, then \code{set} will also not allow you to store
|
||||
#' the sentinel value in the cache. It will throw an error if you attempt to
|
||||
@@ -88,9 +93,11 @@
|
||||
#' A disk cache object has the following methods:
|
||||
#'
|
||||
#' \describe{
|
||||
#' \item{\code{get(key)}}{
|
||||
#' \item{\code{get(key, missing)}}{
|
||||
#' Returns the value associated with \code{key}. If the key is not in the
|
||||
#' cache, this throws an error.
|
||||
#' cache, then it returns the value specified by \code{missing}. The
|
||||
#' default value for \code{missing} when the DiskCache object is created,
|
||||
#' but it can be overridden when \code{get()} is called.
|
||||
#' }
|
||||
#' \item{\code{set(key, value)}}{
|
||||
#' Stores the \code{key}-\code{value} pair in the cache.
|
||||
@@ -146,16 +153,15 @@ MemoryCache <- R6Class("MemoryCache",
|
||||
private$max_n <- max_n
|
||||
private$evict <- match.arg(evict)
|
||||
private$missing <- missing
|
||||
private$eval_missing <- is.language(missing)
|
||||
},
|
||||
|
||||
get = function(key) {
|
||||
get = function(key, missing = private$missing) {
|
||||
validate_key(key)
|
||||
if (!self$exists(key)) {
|
||||
if (private$eval_missing) {
|
||||
return(eval(private$missing))
|
||||
if (is.language(missing)) {
|
||||
return(eval(missing))
|
||||
} else {
|
||||
return(private$missing)
|
||||
return(missing)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,7 +172,7 @@ MemoryCache <- R6Class("MemoryCache",
|
||||
|
||||
set = function(key, value) {
|
||||
validate_key(key)
|
||||
if (!private$eval_missing && identical(value, private$missing)) {
|
||||
if (!is.language(private$missing) && identical(value, private$missing)) {
|
||||
stop("Attempted to store sentinel value representing a missing key.")
|
||||
}
|
||||
|
||||
@@ -275,7 +281,6 @@ MemoryCache <- R6Class("MemoryCache",
|
||||
max_n = NULL,
|
||||
evict = NULL,
|
||||
missing = NULL,
|
||||
eval_missing = NULL,
|
||||
|
||||
object_info = function() {
|
||||
keys <- ls(private$cache, sorted = FALSE)
|
||||
|
||||
@@ -286,19 +286,9 @@ renderCachedPlot <- function(expr,
|
||||
|
||||
key <- digest::digest(list(outputName, cacheKeyResult, width, height, res, pixelratio), "sha256")
|
||||
|
||||
cached_value <- cache$get(key)
|
||||
|
||||
# Get the key. Instead of using exists() before get(), try to simply
|
||||
# get() the key and catch the exception if it fails. This is to avoid
|
||||
# possible race conditions between calls to exists() and get()
|
||||
get_value_failed <- FALSE
|
||||
tryCatch(
|
||||
cached_value <- cache$get(key),
|
||||
error = function(e) {
|
||||
get_value_failed <<- TRUE
|
||||
}
|
||||
)
|
||||
|
||||
if (!get_value_failed) {
|
||||
if (!is.key_missing(cached_value)) {
|
||||
cat("drawReactive(): cached\n")
|
||||
# This will NOT include the displaylist.
|
||||
return(cached_value)
|
||||
@@ -399,15 +389,9 @@ renderCachedPlot <- function(expr,
|
||||
|
||||
key <- digest::digest(list(outputName, cacheKeyResult, width, height, res, pixelratio), "sha256")
|
||||
|
||||
get_value_failed <- FALSE
|
||||
tryCatch(
|
||||
cached_value <- cache$get(key),
|
||||
error = function(e) {
|
||||
get_value_failed <<- TRUE
|
||||
}
|
||||
)
|
||||
cached_value <- cache$get(key)
|
||||
|
||||
if (!get_value_failed) {
|
||||
if (!is.key_missing(cached_value)) {
|
||||
cat("drawReactive(): cached\n")
|
||||
result <- cached_value
|
||||
|
||||
|
||||
@@ -65,6 +65,11 @@ and \code{evict}.
|
||||
return a different sentinel value, like \code{NULL}, or even throw an error
|
||||
on a cache miss.
|
||||
|
||||
When the cache is created, you can supply a value for \code{missing}, which
|
||||
sets the default value to be returned for missing values. It can also be
|
||||
overridden when \code{get()} is called, by supplying a \code{missing}
|
||||
argument, as in \code{cache$get("mykey", missing = NULL)}.
|
||||
|
||||
If your cache is configured so that \code{get()} returns a sentinel value
|
||||
to represent a cache miss, then \code{set} will also not allow you to store
|
||||
the sentinel value in the cache. It will throw an error if you attempt to
|
||||
@@ -158,9 +163,11 @@ already been deleted.
|
||||
A disk cache object has the following methods:
|
||||
|
||||
\describe{
|
||||
\item{\code{get(key)}}{
|
||||
\item{\code{get(key, missing)}}{
|
||||
Returns the value associated with \code{key}. If the key is not in the
|
||||
cache, this throws an error.
|
||||
cache, then it returns the value specified by \code{missing}. The
|
||||
default value for \code{missing} when the DiskCache object is created,
|
||||
but it can be overridden when \code{get()} is called.
|
||||
}
|
||||
\item{\code{set(key, value)}}{
|
||||
Stores the \code{key}-\code{value} pair in the cache.
|
||||
|
||||
@@ -55,6 +55,11 @@ MemoryCache, it will not be garbage collected.
|
||||
return a different sentinel value, like \code{NULL}, or even throw an error
|
||||
on a cache miss.
|
||||
|
||||
When the cache is created, you can supply a value for \code{missing}, which
|
||||
sets the default value to be returned for missing values. It can also be
|
||||
overridden when \code{get()} is called, by supplying a \code{missing}
|
||||
argument, as in \code{cache$get("mykey", missing = NULL)}.
|
||||
|
||||
If your cache is configured so that \code{get()} returns a sentinel value
|
||||
to represent a cache miss, then \code{set} will also not allow you to store
|
||||
the sentinel value in the cache. It will throw an error if you attempt to
|
||||
@@ -124,9 +129,11 @@ policies are:
|
||||
A disk cache object has the following methods:
|
||||
|
||||
\describe{
|
||||
\item{\code{get(key)}}{
|
||||
\item{\code{get(key, missing)}}{
|
||||
Returns the value associated with \code{key}. If the key is not in the
|
||||
cache, this throws an error.
|
||||
cache, then it returns the value specified by \code{missing}. The
|
||||
default value for \code{missing} when the DiskCache object is created,
|
||||
but it can be overridden when \code{get()} is called.
|
||||
}
|
||||
\item{\code{set(key, value)}}{
|
||||
Stores the \code{key}-\code{value} pair in the cache.
|
||||
|
||||
@@ -7,6 +7,8 @@ test_that("DiskCache: handling missing values", {
|
||||
expect_error(d$set("x", key_missing()))
|
||||
d$set("a", 100)
|
||||
expect_identical(d$get("a"), 100)
|
||||
expect_identical(d$get("y", missing = NULL), NULL)
|
||||
expect_error(d$get("y", missing = quote(stop("Missing key"))), "^Missing key$")
|
||||
|
||||
d <- diskCache(missing = NULL)
|
||||
expect_true(is.null(d$get("abcd")))
|
||||
@@ -14,6 +16,8 @@ test_that("DiskCache: handling missing values", {
|
||||
expect_error(d$set("x", NULL))
|
||||
d$set("a", 100)
|
||||
expect_identical(d$get("a"), 100)
|
||||
expect_identical(d$get("y", missing = -1), -1)
|
||||
expect_error(d$get("y", missing = quote(stop("Missing key"))), "^Missing key$")
|
||||
|
||||
d <- diskCache(missing = quote(stop("Missing key")))
|
||||
expect_error(d$get("abcd"), "^Missing key$")
|
||||
@@ -23,6 +27,8 @@ test_that("DiskCache: handling missing values", {
|
||||
expect_identical(d$get("x"), quote(stop("Missing key")))
|
||||
d$set("a", 100)
|
||||
expect_identical(d$get("a"), 100)
|
||||
expect_identical(d$get("y", missing = NULL), NULL)
|
||||
expect_error(d$get("y", missing = quote(stop("Missing key 1"))), "^Missing key 1$")
|
||||
})
|
||||
|
||||
test_that("MemoryCache: handling missing values", {
|
||||
@@ -32,6 +38,8 @@ test_that("MemoryCache: handling missing values", {
|
||||
expect_error(d$set("x", key_missing()))
|
||||
d$set("a", 100)
|
||||
expect_identical(d$get("a"), 100)
|
||||
expect_identical(d$get("y", missing = NULL), NULL)
|
||||
expect_error(d$get("y", missing = quote(stop("Missing key"))), "^Missing key$")
|
||||
|
||||
d <- memoryCache(missing = NULL)
|
||||
expect_true(is.null(d$get("abcd")))
|
||||
@@ -39,6 +47,8 @@ test_that("MemoryCache: handling missing values", {
|
||||
expect_error(d$set("x", NULL))
|
||||
d$set("a", 100)
|
||||
expect_identical(d$get("a"), 100)
|
||||
expect_identical(d$get("y", missing = -1), -1)
|
||||
expect_error(d$get("y", missing = quote(stop("Missing key"))), "^Missing key$")
|
||||
|
||||
d <- memoryCache(missing = quote(stop("Missing key")))
|
||||
expect_error(d$get("abcd"), "^Missing key$")
|
||||
@@ -48,4 +58,6 @@ test_that("MemoryCache: handling missing values", {
|
||||
expect_identical(d$get("x"), quote(stop("Missing key")))
|
||||
d$set("a", 100)
|
||||
expect_identical(d$get("a"), 100)
|
||||
expect_identical(d$get("y", missing = NULL), NULL)
|
||||
expect_error(d$get("y", missing = quote(stop("Missing key 1"))), "^Missing key 1$")
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user