From 90febfa189890fc1f1c850753ef064d3c66336e8 Mon Sep 17 00:00:00 2001 From: Constantinos Giachalis Date: Mon, 18 May 2026 17:43:02 +0300 Subject: [PATCH 01/24] Doc fix --- R/TileDBStorr.R | 2 +- man/TileDBStorr.Rd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/R/TileDBStorr.R b/R/TileDBStorr.R index 9a6b9ad..c42c137 100644 --- a/R/TileDBStorr.R +++ b/R/TileDBStorr.R @@ -1050,7 +1050,7 @@ TileDBStorr <- R6::R6Class( #' @description Get multiple objects given their hashes. #' #' - #' @param hash A vector of hash values." + #' @param hash A vector of hash values. #' @param use_cache `r sto_cache` #' @param missing Value to use for missing elements. #' diff --git a/man/TileDBStorr.Rd b/man/TileDBStorr.Rd index 80cb637..337ec23 100644 --- a/man/TileDBStorr.Rd +++ b/man/TileDBStorr.Rd @@ -638,7 +638,7 @@ requested digest (hash) of the supplied R object. \subsection{Arguments}{ \if{html}{\out{
}} \describe{ - \item{\code{hash}}{A vector of hash values."} + \item{\code{hash}}{A vector of hash values.} \item{\code{use_cache}}{Should the cache be used? Default is \code{TRUE}.} \item{\code{missing}}{Value to use for missing elements.} } From e7fe0061290cc85d305ec0f17d6eeff48966c90b Mon Sep 17 00:00:00 2001 From: Constantinos Giachalis Date: Tue, 19 May 2026 09:45:32 +0300 Subject: [PATCH 02/24] `TTDriver` - a `TileDriver` variant with time-travel support --- R/TTDriver.R | 875 ++++++++++++++++++++++++++++++++++++++++++++++++ man/TTDriver.Rd | 636 +++++++++++++++++++++++++++++++++++ 2 files changed, 1511 insertions(+) create mode 100644 R/TTDriver.R create mode 100644 man/TTDriver.Rd diff --git a/R/TTDriver.R b/R/TTDriver.R new file mode 100644 index 0000000..3c2a505 --- /dev/null +++ b/R/TTDriver.R @@ -0,0 +1,875 @@ +#' @title Generate a `TTDriver` Object +#' +#' @description A [TileDBDriver] variant with read only class methods and +#' time-travel support. +#' +#' This class is intended for usage in [StorrTimeTravel]. +#' +#' @returns A `TTDriver`, `R6` object. +#' +#' @export +#' +#' @keywords internal +#' +TTDriver <- R6::R6Class( + inherit = TileDBGroup, + cloneable = FALSE, + classname = "TTDriver", + + public = list( + + #' @field traits Driver traits (**immutable**). + #' + traits = NULL, + + #' @description Instantiate a new `TTDriver` object. + #' + #' @param uri URI path for the `TTDBDriver` object. + #' @param ctx Optional [tiledb::tiledb_ctx()] object. + #' @param timestamp Set a `TileDB` timestamp range that + #' the resource will be opened at. Effective in `"READ"` mode only. + #' Valid options: + #' - A `NULL` value (default) + #' - An `R` object coercible to `POSIXct` with length 1 which is used for end timestamp, + #' or length 2 with start, end timestamps + #' - An object of class `tiledb_timestamp`. See [R6.tiledb::set_tiledb_timestamp()] + #' + initialize = function(uri, ctx = NULL, timestamp = NULL) { + + super$initialize(uri, ctx = ctx, tiledb_timestamp = timestamp) + + if (self$exists()) { + self$open(instantiate = TRUE) + } + + self$traits <- list(accept = "string", + throw_missing = TRUE) + + lockBinding("traits", self) + + }, + + #' @description Driver type. + #' + #' @return A character string. + #' + type = function() { + "tiledb" + }, + + #' @description Open `TTDriver` object for read or write. + #' + #' Setting`instantiate` argument to `TRUE`, all members will be instantiated + #' and cached on opening. They can be accessed via `members` active field, i.e., using + #' `$object` element. + #' + #' @param mode Mode to open : either `"READ"` or `"WRITE"`. Default is `"READ"`. + #' @param instantiate Should be all members be instantiated at opening? + #' Default is `FALSE`. + #' + #' @return The object, invisibly. + #' + open = function(mode = c("READ", "WRITE"), instantiate = FALSE) { + + super$open(mode = mode) + + type <- self$get_metadata("type") + + if (type != "storr" || is.null(type)) { + + cli::cli_abort("Not a {.arg TileDB Storr} at URI: {.url {self$uri}}", call = NULL) + + } + + if (instantiate) { + private$instantiate_members() + private$.members_instantiated <- TRUE + } + + invisible(self) + + }, + + #' @description Close the group object. + #' + #' All instantiated group members will be closed if opened, and before + #' closing the group object. + #' + #' @return The object, invisibly. + #' + close = function() { + + super$close() + private$.members_instantiated <- NULL + + invisible(self) + }, + + #' @description Filter `tbl_keys` by key and namespace + #' + #' @param key `r roxy_key` + #' @param namespace `r roxy_namespace` + #' @param attrnames A character vector with tiledb attributes (columns). + #' + #' @return A `data.table. + #' + filter_keys = function(key, namespace, attrnames = character()) { + + arrobj <- private$keys_array() + + sp <- list(namespace = namespace, key = key) + + arr <- arrobj$object + tiledb::attrs(arr) <- attrnames + tiledb::selected_points(arr) <- sp + tiledb::return_as(arr) <- "arrow" + + # arr <- arrobj$tiledb_array(attrs = attrnames, + # selected_points = sp, + # return_as = "arrow", + # ctx = self$ctx) + + dt <- data.table::as.data.table(arr[]) + + # TODO: Remove when TileDB fixes it + if (attrnames == "expires_at" || length(attrnames) == 0) { + expires_at <- NULL + dt[expires_at <= 0 , expires_at := as.POSIXct(NA)] + } + + dt + }, + + #' @description Get hash values. + #' + #' @param key `r roxy_key` + #' @param namespace `r roxy_namespace` + #' + #' @return A vector of hashes. + #' + get_hash = function(key, namespace) { + + result <- private$query_hash(key, namespace) + + if (is.na(result)) { + # 'get_hash' always returns NA if missing as we need + # this for mget_hash. Here, an error is raised to + # support 'throw_missing' trait. Doing so, we're + # avoiding the extra query (e.g., exists_hash) in storr + # layer. + stop(KeyError(key, namespace)) + } + + result + }, + + + #' @description Get hash values. + #' + #' @param key `r roxy_key` + #' @param namespace `r roxy_namespace` + #' + #' @return A vector of hashes. + #' + mget_hash = function(key, namespace) { + + private$query_hash(key, namespace) + + }, + + #' @description Get R object given a hash. + #' + #' @param hash A hash value. + #' + #' @return A de-serialized R object. + #' + get_object = function(hash) { + + private$check_scalar_character(hash) + result <- self$mget_object(hash)[[1]] + + if (is.null(result)) { + # NB: 'get_object' always returns NULL if missing as we need + # this for mget_object. Here, an error is raised to + # support 'throw_missing' trait. Doing so, we're + # avoiding the extra query (e.g., exists_object) in storr + # layer. + stop(HashError(hash)) + } + + result + + }, + + #' @description Get a list R objects given a hash vector. + #' + #' @param hash `r roxy_hash` + #' + #' @return A list with de-serialized R objects. + #' + mget_object = function(hash) { + + if (length(hash) == 0L){ + return(list()) + } + + arrobj <- private$data_array() + + sp <- list(hash = hash) + arr <- arrobj$object + tiledb::selected_points(arr) <- sp + tiledb::return_as(arr) <- "arrow" + # arr <- arrobj$tiledb_array(extended = TRUE, + # selected_points = sp, + # return_as = "arrow") + + x <- arrow::Array$create(hash) + nona_hash <- arrow::call_function("is_in", + x, + options = list( + value_set = arr[]$GetColumnByName("hash"), + skip_nulls = TRUE + )) + + status_nona <- arrow::call_function("all", nona_hash) + status_nona <- status_nona$as_vector() + + if (status_nona) { + result <- lapply(arr[]$value$as_vector(), { + function(.s) unserialize(charToRaw(.s)) } + ) + } else { + result <- vector("list", length(hash)) + + idx <- which(nona_hash$as_vector()) + + vals <- arr[]$value$as_vector() + for (i in seq_along(idx)) { + result[idx[i]] <- unserialize(charToRaw(vals[i])) + } + } + + # NB: The read query gives unordered results, so we + # extract them in order to match the requested order. + names(result) <- arr[]$hash$as_vector() + unname(result[hash]) + + }, + + #' @description Get key-namespace metadata. + #' + #' @param key A single character key. + #' @param namespace A single character namespace. + #' + #' @return A named list with key-metadata, `"expires_at"` + #' and `"notes".` + #' + get_keymeta = function(key, namespace) { + + arrobj <- private$keys_array() + + sp <- list(namespace = namespace, key = key) + + arr <- arrobj$object + tiledb::extended(arr) <- FALSE + tiledb::attrs(arr) <- c("expires_at", "notes") + tiledb::selected_points(arr) <- sp + tiledb::return_as(arr) <- "arrow" + + # arr <- arrobj$tiledb_array(extended = FALSE, + # attrs = c("expires_at", "notes"), + # selected_points = sp, + # return_as = "arrow") + + DT <- data.table::as.data.table(arr[]) + + # TODO: Remove when TileDB fixes it + expires_at <- NULL + DT[expires_at <= 0 , expires_at := as.POSIXct(NA)] + + + if (nrow(DT) == 0) { + stop(KeyError(key, namespace)) + } + + as.list(DT) + }, + + #' @description Get multiple key-namespace metadata. + #' + #' @param key `r roxy_key` + #' @param namespace `r roxy_namespace` + #' @param nomatch Value to fill in case of no match. + #' + #' @return A list with key metadata for each key-namespace + #' pair. For not found pairs will return the nomatch value. + #' + mget_keymeta = function(key, namespace, nomatch = NULL) { + + arrobj <- private$keys_array() + + # Slice array + sp <- list(namespace = namespace, key = key) + arr <- arrobj$object + tiledb::selected_points(arr) <- sp + tiledb::return_as(arr) <- "arrow" + + # arr <- arrobj$tiledb_array(selected_points = sp, return_as = "arrow") + + DT <- data.table::as.data.table(arr[], key = c("namespace", "key")) + + # TODO: Remove when TileDB fixes it + # Sanitise datetime columns + expires_at <- NULL + DT[expires_at <= 0 , expires_at := as.POSIXct(NA)] + + DT <- DT[.(namespace, key), env = list(namespace = I(namespace), key = I(key))] + hash_isna <- is.na(DT[["hash"]]) + + out <- vector("list", nrow(DT)) + + if (is.null(nomatch)) { + nomatch <- list(nomatch) + } + + for (i in seq_along(out)) { + + if (!hash_isna[i]) { + out[[i]] <- as.list(DT[i, c("expires_at", "notes")]) + } else { + out[[i]] <- nomatch + } + + } + + attr(out, "missing") <- which(hash_isna) + + out + + }, + + #' @description Check a key-namespace pair exists. + #' + #' @param key `r roxy_key` + #' @param namespace `r roxy_namespace` + #' + #' @return A logical vector. + #' + exists_hash = function(key, namespace) { + + p <- storr::join_key_namespace(key, namespace) + + arrobj <- private$keys_array() + + sp <- list(namespace = namespace, key = key) + + arr <- arrobj$object + tiledb::attrs(arr) <- "hash" + tiledb::selected_points(arr) <- sp + tiledb::return_as(arr) <- "arrow" + + # arr <- arrobj$tiledb_array(attrs = "hash", + # selected_points = sp, + # return_as = "arrow") + + DT <- data.table::as.data.table(arr[]) + + data.table::setkeyv(DT, c("namespace", "key")) + + key <- p$key + namespace <- p$namespace + i <- DT[.(namespace, key), "hash", with = FALSE, + env = list(namespace = I(namespace), + key = I(key))] + + !is.na(i[["hash"]]) + }, + + #' @description Check a serialised object exists. + #' + #' @param hash `r roxy_hash` + #' + #' @return A logical vector. + #' + exists_object = function(hash) { + + arrobj <- private$data_array() + + arr <- arrobj$object + tiledb::attrs(arr) <- NA_character_ + tiledb::selected_points(arr) <- list(hash = hash) + tiledb::return_as(arr) <- "arrow" + + # arr <- arrobj$tiledb_array(attrs = NA_character_, + # selected_points = list(hash = hash), + # return_as = "arrow") + + hashes <- arr[]$GetColumnByName("hash")$as_vector() + + x <- arrow::Array$create(hash) + out <- arrow::call_function("is_in", + x, + options = list( + value_set = arr[]$GetColumnByName("hash"), + skip_nulls = TRUE + )) + out$as_vector() + + }, + + #' @description List all hash values. + #' + #' + #' @return A vector of hash values. + #' + list_hashes = function() { + + arrobj <- private$data_array() + + arr <- arrobj$object + tiledb::attrs(arr) <- NA_character_ + tiledb::return_as(arr) <- "arrow" + + # arr <- arrobj$tiledb_array(attrs = NA_character_, + # return_as = "arrow") + + ns <- arr[]$GetColumnByName("hash") + ns$as_vector() + + }, + + #' @description List all namespace values. + #' + #' + #' @return A vector of namespace values. + #' + list_namespaces = function() { + + arrobj <- private$keys_array() + + arr <- arrobj$object + tiledb::attrs(arr) <- NA_character_ + tiledb::return_as(arr) <- "arrow" + + # arr <- arrobj$tiledb_array(attrs = NA_character_, + # return_as = "arrow") + + ns <- arr[]$GetColumnByName("namespace") + ns <- arrow::call_function("unique", ns) + ns$as_vector() + + }, + + #' @description List keys given a namespace. + #' + #' @param namespace A single character namespace. + #' + #' @return A vector of key values. + #' + list_keys = function(namespace) { + + private$check_scalar_character(namespace) + + arrobj <- private$keys_array() + + arr <- arrobj$object + tiledb::attrs(arr) <- NA_character_ + tiledb::selected_points(arr) <- list(namespace = namespace) + tiledb::return_as(arr) <- "arrow" + + # arr <- arrobj$tiledb_array(attrs = NA_character_, + # selected_points = list(namespace = namespace), + # return_as = "arrow") + + keys <- arr[]$GetColumnByName("key") + keys$as_vector() + + }, + + #' @description List unused hashes. + #' + #' + #' @return A vector of hash values. + #' + list_unused_hashes = function() { + + # Get unique hash values from 'tbl_keys' + arrobj <- private$keys_array() + + arr <- arrobj$object + tiledb::attrs(arr) <- "hash" + tiledb::return_as(arr) <- "arrow" + + # arr <- arrobj$tiledb_array(extended = TRUE, + # attrs = "hash", + # return_as = "arrow") + + yh <- arr[]$GetColumnByName("hash") + yh <- arrow::call_function("unique", yh) + yh <- yh$as_vector() + + # Get object hash values from 'tbl_data' + xh <- self$list_hashes() + + # Find unused hashes (equiv. setdiff(x, y)) + xh[data.table::chmatch(xh, yh, 0L) == 0L] + + }, + + #' @description Get the key-namespace pairs with expiration timestamps. + #' + #' @param namespace `r sto_namespaces_or_null` + #' @param datetimes Should the `expires_at` column be returned? + #' Default is `TRUE`. + #' + #' @return An `ArrowObject` object. + #' + keys_with_expiration = function(namespace, datetimes = TRUE) { + + check_character_or_null(namespace) + + arrobj <- private$keys_array() + arr <- arrobj$object + + # Ignore NA datetimes + qc <- tiledb::tiledb_query_condition_init(attr = "expires_at", + value = as.POSIXct(NA), + dtype = "DATETIME_MS", + op = "NE") + + sp <- list() + + if (!is.null(namespace)) { + sp <- list(namespace = namespace) + } + + if (datetimes) { + attrs <- "expires_at" + } else { + attrs <- NA_character_ + } + + tiledb::attrs(arr) <- attrs + tiledb::selected_points(arr) <- sp + tiledb::query_condition(arr) <- qc + tiledb::return_as(arr) <- "arrow" + arr[] + # arrobj$tiledb_array(attrs = attrs, + # selected_points = sp, + # query_condition = qc, + # return_as = "arrow")[] + }, + + #' @description Get the key-namespace pairs without expiration timestamps. + #' + #' @param namespace `r sto_namespaces_or_null` + #' @param datetimes Should the `expires_at` column be returned? + #' Default is `TRUE`. + #' + #' @return An `ArrowObject` object. + #' + keys_without_expiration = function(namespace, datetimes = TRUE) { + + check_character_or_null(namespace) + + arrobj <- private$keys_array() + arr <- arrobj$object + + # Ignore NA datetimes + qc <- tiledb::tiledb_query_condition_init(attr = "expires_at", + value = as.POSIXct(NA), + dtype = "DATETIME_MS", + op = "EQ") + + sp <- list() + + if (!is.null(namespace)) { + sp <- list(namespace = namespace) + } + + if (datetimes) { + attrs <- "expires_at" + } else { + attrs <- NA_character_ + } + + tiledb::attrs(arr) <- attrs + tiledb::selected_points(arr) <- sp + tiledb::query_condition(arr) <- qc + tiledb::return_as(arr) <- "arrow" + arr[] + # + # arrobj$tiledb_array(attrs = attrs, + # selected_points = sp, + # query_condition = qc, + # return_as = "arrow")[] + }, + + #' @description Get the expired key-namespace pairs. + #' + #' @param namespace `r sto_namespaces_or_null` + #' @param datetimes Should the `expires_at` column be returned? + #' Default is `TRUE`. + #' + #' @return An `ArrowObject` object. + #' + expired_keys = function(namespace, datetimes = TRUE) { + + check_character_or_null(namespace) + + arrobj <- private$keys_array() + arr <- arrobj$object + + # Ignore NA datetimes + qc_dttm1 <- tiledb::tiledb_query_condition_init(attr = "expires_at", + value = as.POSIXct(NA), + dtype = "DATETIME_MS", + op = "NE") + # Expired datetimes (now > index) + qc_dttm2 <- tiledb::tiledb_query_condition_init(attr = "expires_at", + value = Sys.time(), + dtype = "DATETIME_MS", + op = "LT") + + qc <- tiledb::tiledb_query_condition_combine(qc_dttm1, qc_dttm2, "AND") + + sp <- list() + + if (!is.null(namespace)) { + sp <- list(namespace = namespace) + } + + if (datetimes) { + attrs <- "expires_at" + } else { + attrs <- NA_character_ + } + + tiledb::attrs(arr) <- attrs + tiledb::selected_points(arr) <- sp + tiledb::query_condition(arr) <- qc + tiledb::return_as(arr) <- "arrow" + arr[] + + # arrobj$tiledb_array(attrs = attrs, + # selected_points = sp, + # query_condition = qc, + # return_as = "arrow")[] + }, + + #' @description Get the unexpired key-namespace pairs. + #' + #' @param namespace `r sto_namespaces_or_null` + #' @param datetimes Should the `expires_at` column be returned? + #' Default is `TRUE`. + #' + #' @return An `ArrowObject` object. + #' + unexpired_keys = function(namespace, datetimes = TRUE) { + + check_character_or_null(namespace) + + arrobj <- private$keys_array() + arr <- arrobj$object + + # Ignore NA datetimes + qc_dttm1 <- tiledb::tiledb_query_condition_init(attr = "expires_at", + value = as.POSIXct(NA), + dtype = "DATETIME_MS", + op = "NE") + # Expired datetimes (now > index) + qc_dttm2 <- tiledb::tiledb_query_condition_init(attr = "expires_at", + value = Sys.time(), + dtype = "DATETIME_MS", + op = "GT") + + qc <- tiledb::tiledb_query_condition_combine(qc_dttm1, qc_dttm2, "AND") + + sp <- list() + + if (!is.null(namespace)) { + sp <- list(namespace = namespace) + } + + if (datetimes) { + attrs <- "expires_at" + } else { + attrs <- NA_character_ + } + + tiledb::attrs(arr) <- attrs + tiledb::selected_points(arr) <- sp + tiledb::query_condition(arr) <- qc + tiledb::return_as(arr) <- "arrow" + arr[] + + # arrobj$tiledb_array(attrs = attrs, + # selected_points = sp, + # query_condition = qc, + # return_as = "arrow")[] + }, + + #' @description Get the number of expired key-namespace pairs. + #' + #' @param namespace `r sto_namespaces_or_null` + #' + #' @return A numeric value. + #' + num_expired_keys = function(namespace) { + + arr <- self$expired_keys(namespace, datetimes = FALSE) + arr[]$num_rows + }, + + #' @description Get the number of unexpired key-namespace pairs. + #' + #' @param namespace `r sto_namespaces_or_null` + #' + #' @return A numeric value. + #' + num_unexpired_keys = function(namespace) { + + arr <- self$unexpired_keys(namespace, datetimes = FALSE) + arr[]$num_rows + }, + + #' @description Check for expired key-namespace pairs. + #' + #' @param namespace `r sto_namespaces_or_null` + #' + #' @return `TRUE` for expired keys, `FALSE` otherwise. + #' + has_expired_keys = function(namespace) { + + arr <- self$expired_keys(namespace, datetimes = FALSE) + arr[]$num_rows != 0 + }, + + #' @description Check for unexpired key-namespace pairs. + #' + #' @param namespace `r sto_namespaces_or_null` + #' + #' @return `TRUE` for unexpired keys, `FALSE` otherwise. + #' + has_unexpired_keys = function(namespace) { + + arr <- self$unexpired_keys(namespace, datetimes = FALSE) + arr[]$num_rows != 0 + } + + ), + + active = list( + + #'@field timestamp Set or retrieve a `TileDB` timestamp range that + #' the resource will be opened at. Effective in `"READ"` mode only. + #' + timestamp = function(value) { + + if (!missing(value)) { + super$tiledb_timestamp <- value + + private$instantiate_members() + + } else { + super$tiledb_timestamp + } + + }, + + #' @field members_instantiated Have the members been instantiated? + #' + members_instantiated = function(value) { + + private$check_object_exists() + + if (!missing(value)) { + private$check_read_only("members_instantiated") + } + + if (is.null(private$.members_instantiated)) { + private$.members_instantiated <- FALSE + } + + private$.members_instantiated + + } + ), + + private = list( + + # @field Query for instantiated members + # + .members_instantiated = NULL, + + # @description Instantiate group members. + # + instantiate_members = function() { + + members <- private$.member_cache + + dev_null <- lapply(members, function(.m) { + + obj <- if (is.null(.m$object)) { + private$log_debug0("instantiate_members", "Constructing member '{}' type {}", .m$name, .m$type) + obj <- private$construct_member(.m$uri, .m$type) + } else { + .m$object + } + + if (!obj$is_open()) { + obj$open(self$mode) + + } else { + obj$reopen(self$mode) + } + + private$log_debug0("instantiate_members", "Adding cached member '{}' type {}", .m$name, .m$type) + + # Explicitly add the new member to member_cache + private$add_cache_member(.m$name, obj) + }) + + invisible(NULL) + }, + + # @description Get cached 'tbl_keys' array object + # + keys_array = function() { + # TODO: should we check for cached first? + self$members$tbl_keys$object + }, + + # @description Get cached 'tbl_data' array object + # + data_array = function() { + self$members$tbl_data$object + }, + + # @description Query 'tbl_keys' array by single attribute + # + query_hash = function(key, namespace) { + + p <- storr::join_key_namespace(key, namespace) + arrobj <- private$keys_array() + + # Slice array + sp <- list(namespace = namespace, key = key) + arr <- arrobj$object + tiledb::attrs(arr) <- "hash" + tiledb::selected_points(arr) <- sp + tiledb::return_as(arr) <- "arrow" + + # arr <- arrobj$tiledb_array(attrs = "hash", + # selected_points = sp, + # return_as = "arrow", + # ctx = self$ctx) + + + dta <- data.table::as.data.table(arr[], key = c("namespace", "key")) + dta[.(namespace, key), "hash", with = FALSE, + env = list(namespace = I(namespace), key = I(key))][[1]] + + } + ) # private +) diff --git a/man/TTDriver.Rd b/man/TTDriver.Rd new file mode 100644 index 0000000..12a0d0c --- /dev/null +++ b/man/TTDriver.Rd @@ -0,0 +1,636 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/TTDriver.R +\name{TTDriver} +\alias{TTDriver} +\title{Generate a \code{TTDriver} Object} +\value{ +A \code{TTDriver}, \code{R6} object. +} +\description{ +A \link{TileDBDriver} variant with read only class methods and +time-travel support. + +This class is intended for usage in \link{StorrTimeTravel}. +} +\keyword{internal} +\section{Super classes}{ +\code{\link[R6.tiledb:TileDBObject]{R6.tiledb::TileDBObject}} -> \code{\link[R6.tiledb:TileDBGroup]{R6.tiledb::TileDBGroup}} -> \code{TTDriver} +} +\section{Public fields}{ + \if{html}{\out{
}} + \describe{ + \item{\code{traits}}{Driver traits (\strong{immutable}).} + } + \if{html}{\out{
}} +} +\section{Active bindings}{ + \if{html}{\out{
}} + \describe{ + \item{\code{timestamp}}{Set or retrieve a \code{TileDB} timestamp range that +the resource will be opened at. Effective in \code{"READ"} mode only.} + + \item{\code{members_instantiated}}{Have the members been instantiated?} + } + \if{html}{\out{
}} +} +\section{Methods}{ +\subsection{Public methods}{ + \itemize{ + \item \href{#method-TTDriver-initialize}{\code{TTDriver$new()}} + \item \href{#method-TTDriver-type}{\code{TTDriver$type()}} + \item \href{#method-TTDriver-open}{\code{TTDriver$open()}} + \item \href{#method-TTDriver-close}{\code{TTDriver$close()}} + \item \href{#method-TTDriver-filter_keys}{\code{TTDriver$filter_keys()}} + \item \href{#method-TTDriver-get_hash}{\code{TTDriver$get_hash()}} + \item \href{#method-TTDriver-mget_hash}{\code{TTDriver$mget_hash()}} + \item \href{#method-TTDriver-get_object}{\code{TTDriver$get_object()}} + \item \href{#method-TTDriver-mget_object}{\code{TTDriver$mget_object()}} + \item \href{#method-TTDriver-get_keymeta}{\code{TTDriver$get_keymeta()}} + \item \href{#method-TTDriver-mget_keymeta}{\code{TTDriver$mget_keymeta()}} + \item \href{#method-TTDriver-exists_hash}{\code{TTDriver$exists_hash()}} + \item \href{#method-TTDriver-exists_object}{\code{TTDriver$exists_object()}} + \item \href{#method-TTDriver-list_hashes}{\code{TTDriver$list_hashes()}} + \item \href{#method-TTDriver-list_namespaces}{\code{TTDriver$list_namespaces()}} + \item \href{#method-TTDriver-list_keys}{\code{TTDriver$list_keys()}} + \item \href{#method-TTDriver-list_unused_hashes}{\code{TTDriver$list_unused_hashes()}} + \item \href{#method-TTDriver-keys_with_expiration}{\code{TTDriver$keys_with_expiration()}} + \item \href{#method-TTDriver-keys_without_expiration}{\code{TTDriver$keys_without_expiration()}} + \item \href{#method-TTDriver-expired_keys}{\code{TTDriver$expired_keys()}} + \item \href{#method-TTDriver-unexpired_keys}{\code{TTDriver$unexpired_keys()}} + \item \href{#method-TTDriver-num_expired_keys}{\code{TTDriver$num_expired_keys()}} + \item \href{#method-TTDriver-num_unexpired_keys}{\code{TTDriver$num_unexpired_keys()}} + \item \href{#method-TTDriver-has_expired_keys}{\code{TTDriver$has_expired_keys()}} + \item \href{#method-TTDriver-has_unexpired_keys}{\code{TTDriver$has_unexpired_keys()}} + } +} +\if{html}{\out{
Inherited methods + +
}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TTDriver-initialize}{}}} +\subsection{\code{TTDriver$new()}}{ + Instantiate a new \code{TTDriver} object. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TTDriver$new(uri, ctx = NULL, timestamp = NULL)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{uri}}{URI path for the \code{TTDBDriver} object.} + \item{\code{ctx}}{Optional \code{\link[tiledb:tiledb_ctx]{tiledb::tiledb_ctx()}} object.} + \item{\code{timestamp}}{Set a \code{TileDB} timestamp range that +the resource will be opened at. Effective in \code{"READ"} mode only. +Valid options: +\itemize{ +\item A \code{NULL} value (default) +\item An \code{R} object coercible to \code{POSIXct} with length 1 which is used for end timestamp, +or length 2 with start, end timestamps +\item An object of class \code{tiledb_timestamp}. See \code{\link[R6.tiledb:set_tiledb_timestamp]{R6.tiledb::set_tiledb_timestamp()}} +}} + } + \if{html}{\out{
}} + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TTDriver-type}{}}} +\subsection{\code{TTDriver$type()}}{ + Driver type. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TTDriver$type()} + \if{html}{\out{
}} + } + \subsection{Returns}{ + A character string. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TTDriver-open}{}}} +\subsection{\code{TTDriver$open()}}{ + Open \code{TTDriver} object for read or write. + +Setting\code{instantiate} argument to \code{TRUE}, all members will be instantiated +and cached on opening. They can be accessed via \code{members} active field, i.e., using +\verb{$object} element. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TTDriver$open(mode = c("READ", "WRITE"), instantiate = FALSE)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{mode}}{Mode to open : either \code{"READ"} or \code{"WRITE"}. Default is \code{"READ"}.} + \item{\code{instantiate}}{Should be all members be instantiated at opening? +Default is \code{FALSE}.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + The object, invisibly. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TTDriver-close}{}}} +\subsection{\code{TTDriver$close()}}{ + Close the group object. + +All instantiated group members will be closed if opened, and before +closing the group object. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TTDriver$close()} + \if{html}{\out{
}} + } + \subsection{Returns}{ + The object, invisibly. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TTDriver-filter_keys}{}}} +\subsection{\code{TTDriver$filter_keys()}}{ + Filter \code{tbl_keys} by key and namespace + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TTDriver$filter_keys(key, namespace, attrnames = character())} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{key}}{A character vector of keys.} + \item{\code{namespace}}{A character vector of namespaces.} + \item{\code{attrnames}}{A character vector with tiledb attributes (columns).} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + A `data.table. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TTDriver-get_hash}{}}} +\subsection{\code{TTDriver$get_hash()}}{ + Get hash values. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TTDriver$get_hash(key, namespace)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{key}}{A character vector of keys.} + \item{\code{namespace}}{A character vector of namespaces.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + A vector of hashes. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TTDriver-mget_hash}{}}} +\subsection{\code{TTDriver$mget_hash()}}{ + Get hash values. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TTDriver$mget_hash(key, namespace)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{key}}{A character vector of keys.} + \item{\code{namespace}}{A character vector of namespaces.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + A vector of hashes. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TTDriver-get_object}{}}} +\subsection{\code{TTDriver$get_object()}}{ + Get R object given a hash. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TTDriver$get_object(hash)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{hash}}{A hash value.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + A de-serialized R object. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TTDriver-mget_object}{}}} +\subsection{\code{TTDriver$mget_object()}}{ + Get a list R objects given a hash vector. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TTDriver$mget_object(hash)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{hash}}{A vector of hash values.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + A list with de-serialized R objects. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TTDriver-get_keymeta}{}}} +\subsection{\code{TTDriver$get_keymeta()}}{ + Get key-namespace metadata. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TTDriver$get_keymeta(key, namespace)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{key}}{A single character key.} + \item{\code{namespace}}{A single character namespace.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + A named list with key-metadata, \code{"expires_at"} +and \verb{"notes".} + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TTDriver-mget_keymeta}{}}} +\subsection{\code{TTDriver$mget_keymeta()}}{ + Get multiple key-namespace metadata. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TTDriver$mget_keymeta(key, namespace, nomatch = NULL)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{key}}{A character vector of keys.} + \item{\code{namespace}}{A character vector of namespaces.} + \item{\code{nomatch}}{Value to fill in case of no match.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + A list with key metadata for each key-namespace +pair. For not found pairs will return the nomatch value. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TTDriver-exists_hash}{}}} +\subsection{\code{TTDriver$exists_hash()}}{ + Check a key-namespace pair exists. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TTDriver$exists_hash(key, namespace)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{key}}{A character vector of keys.} + \item{\code{namespace}}{A character vector of namespaces.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + A logical vector. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TTDriver-exists_object}{}}} +\subsection{\code{TTDriver$exists_object()}}{ + Check a serialised object exists. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TTDriver$exists_object(hash)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{hash}}{A vector of hash values.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + A logical vector. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TTDriver-list_hashes}{}}} +\subsection{\code{TTDriver$list_hashes()}}{ + List all hash values. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TTDriver$list_hashes()} + \if{html}{\out{
}} + } + \subsection{Returns}{ + A vector of hash values. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TTDriver-list_namespaces}{}}} +\subsection{\code{TTDriver$list_namespaces()}}{ + List all namespace values. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TTDriver$list_namespaces()} + \if{html}{\out{
}} + } + \subsection{Returns}{ + A vector of namespace values. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TTDriver-list_keys}{}}} +\subsection{\code{TTDriver$list_keys()}}{ + List keys given a namespace. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TTDriver$list_keys(namespace)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{namespace}}{A single character namespace.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + A vector of key values. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TTDriver-list_unused_hashes}{}}} +\subsection{\code{TTDriver$list_unused_hashes()}}{ + List unused hashes. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TTDriver$list_unused_hashes()} + \if{html}{\out{
}} + } + \subsection{Returns}{ + A vector of hash values. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TTDriver-keys_with_expiration}{}}} +\subsection{\code{TTDriver$keys_with_expiration()}}{ + Get the key-namespace pairs with expiration timestamps. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TTDriver$keys_with_expiration(namespace, datetimes = TRUE)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{namespace}}{A character vector of namespaces or \code{NULL} for all namespaces.} + \item{\code{datetimes}}{Should the \code{expires_at} column be returned? +Default is \code{TRUE}.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + An \code{ArrowObject} object. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TTDriver-keys_without_expiration}{}}} +\subsection{\code{TTDriver$keys_without_expiration()}}{ + Get the key-namespace pairs without expiration timestamps. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TTDriver$keys_without_expiration(namespace, datetimes = TRUE)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{namespace}}{A character vector of namespaces or \code{NULL} for all namespaces.} + \item{\code{datetimes}}{Should the \code{expires_at} column be returned? +Default is \code{TRUE}.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + An \code{ArrowObject} object. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TTDriver-expired_keys}{}}} +\subsection{\code{TTDriver$expired_keys()}}{ + Get the expired key-namespace pairs. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TTDriver$expired_keys(namespace, datetimes = TRUE)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{namespace}}{A character vector of namespaces or \code{NULL} for all namespaces.} + \item{\code{datetimes}}{Should the \code{expires_at} column be returned? +Default is \code{TRUE}.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + An \code{ArrowObject} object. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TTDriver-unexpired_keys}{}}} +\subsection{\code{TTDriver$unexpired_keys()}}{ + Get the unexpired key-namespace pairs. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TTDriver$unexpired_keys(namespace, datetimes = TRUE)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{namespace}}{A character vector of namespaces or \code{NULL} for all namespaces.} + \item{\code{datetimes}}{Should the \code{expires_at} column be returned? +Default is \code{TRUE}.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + An \code{ArrowObject} object. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TTDriver-num_expired_keys}{}}} +\subsection{\code{TTDriver$num_expired_keys()}}{ + Get the number of expired key-namespace pairs. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TTDriver$num_expired_keys(namespace)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{namespace}}{A character vector of namespaces or \code{NULL} for all namespaces.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + A numeric value. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TTDriver-num_unexpired_keys}{}}} +\subsection{\code{TTDriver$num_unexpired_keys()}}{ + Get the number of unexpired key-namespace pairs. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TTDriver$num_unexpired_keys(namespace)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{namespace}}{A character vector of namespaces or \code{NULL} for all namespaces.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + A numeric value. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TTDriver-has_expired_keys}{}}} +\subsection{\code{TTDriver$has_expired_keys()}}{ + Check for expired key-namespace pairs. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TTDriver$has_expired_keys(namespace)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{namespace}}{A character vector of namespaces or \code{NULL} for all namespaces.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + \code{TRUE} for expired keys, \code{FALSE} otherwise. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TTDriver-has_unexpired_keys}{}}} +\subsection{\code{TTDriver$has_unexpired_keys()}}{ + Check for unexpired key-namespace pairs. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TTDriver$has_unexpired_keys(namespace)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{namespace}}{A character vector of namespaces or \code{NULL} for all namespaces.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + \code{TRUE} for unexpired keys, \code{FALSE} otherwise. + } +} + +} From d371b2e3980b97bc38c9b96fb51318e8fb8f6d3b Mon Sep 17 00:00:00 2001 From: Constantinos Giachalis Date: Tue, 19 May 2026 09:48:29 +0300 Subject: [PATCH 03/24] `StorrTimeTravel` - a `TileDBStorr` variant with time-travel support --- R/StorrTimeTravel.R | 474 ++++++++++++++++++++++++++++++++++++++ man/StorrTimeTravel.Rd | 504 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 978 insertions(+) create mode 100644 R/StorrTimeTravel.R create mode 100644 man/StorrTimeTravel.Rd diff --git a/R/StorrTimeTravel.R b/R/StorrTimeTravel.R new file mode 100644 index 0000000..a85ab8e --- /dev/null +++ b/R/StorrTimeTravel.R @@ -0,0 +1,474 @@ +#' @title Generate a `StorrTimeTravel` Object +#' +#' @description A [TileDBStorr] variant with read only class methods and +#' time-travel support. +#' +#' This class is not intended to be used directly and the preferred +#' usage is through [storr_timetravel()]. +#' +#' @returns A `StorrTimeTravel`, `R6` object. +#' +#' @export +#' +#' @keywords internal +#' +StorrTimeTravel <- R6::R6Class( + classname = "StorrTimeTravel", + cloneable = FALSE, + + public = list( + + #' @field default_namespace The default namespace. + #' + default_namespace = NULL, + + #' @field traits Driver traits. + #' + traits = NULL, + + #' @description Initialise `StorrTimeTravel`. + #' + #' @param driver A [TTDriver] object. + #' @param default_namespace The default namespace. + #' + initialize = function(driver, default_namespace) { + + if (!inherits(driver, "TTDriver")) { + stop("Not a valid Time-Travel 'driver'. Please use a 'TTDriver' object.", + call. = FALSE) + } + + private$check_input(default_namespace, n = 1, type = "character") + + # We need the member's object to be available + # e.g., driver$members$tbl_keys$object + if (!driver$is_open() ) { + # Ensure the members are instantiated + driver$open(instantiate = TRUE) + } + + if (driver$is_open() && !driver$members_instantiated) { + driver$close() + driver$open(instantiate = TRUE) + } + + private$DRIVER <- driver + + + self$default_namespace <- default_namespace + self$traits <- storr_traits(driver$traits) + + }, + + #' @description Get an object given a key-namespace pair. + #' + #' @param key `r sto_key()` + #' @param namespace `r sto_namespace()` + #' + #' @return The `R` object if available. + #' + get = function(key, namespace = self$default_namespace) { + private$check_input(key, n = 1, type = "character") + private$check_input(namespace, n = 1, type = "character") + self$get_value(self$get_hash(key, namespace)) + + }, + + #' @description Get multiple objects. + #' + #' `r sto_recycle_note` + #' + #' @param key `r sto_key(1)` + #' @param namespace `r sto_namespace(1)` + #' @param missing Value to use for missing elements. + #' + #' @return A list of `R` objects. + #' + mget = function(key, namespace = self$default_namespace, missing = NULL) { + + # NB: storr::join_key_namespace check is performed inside $query_keys0 + self$mget_value(self$mget_hash(key, namespace), missing) + }, + + #' @description Get hash value. + #' + #' + #' @param key `r sto_key()` + #' @param namespace `r sto_namespace()` + #' + #' @return The hash value. + #' + get_hash = function(key, namespace = self$default_namespace) { + + private$check_input(key, n = 1, type = "character") + private$check_input(namespace, n = 1, type = "character") + + if (self$traits$throw_missing) { + tryCatch(private$DRIVER$get_hash(key, namespace), error = function(e) stop(KeyError(key, + namespace))) + } + else { + if (self$exists(key, namespace)) { + private$DRIVER$get_hash(key, namespace) + } + else { + stop(KeyError(key, namespace)) + } + } + }, + + #' @description Get hash values. + #' + #' `r sto_recycle_note` + #' + #' @param key `r sto_key(1)` + #' @param namespace `r sto_namespace(1)` + #' + #' @return A vector of hashes. + #' + mget_hash = function(key, namespace = self$default_namespace) { + + private$DRIVER$mget_hash(key, namespace) + }, + + + #' @description Get an object given its hash. + #' + #' + #' @param hash The hash value of the object. + #' + #' @return The `R` object if available. + #' + get_value = function(hash) { + + # TODO: no need for traits + if (self$traits$throw_missing) { + value <- tryCatch( + private$DRIVER$get_object(hash), + error = function(e) + stop(HashError(hash)) + ) + } else { + if (!private$DRIVER$exists_object(hash)) { + stop(HashError(hash)) + } + value <- private$DRIVER$get_object(hash) + } + + value + }, + + #' @description Get multiple objects given their hashes. + #' + #' + #' @param hash A vector of hash values." + #' @param missing Value to use for missing elements. + #' + #' @return A list of `R` objects. + #' + mget_value = function(hash, missing = NULL) { + + value <- vector("list", length(hash)) + cached <- logical(length(hash)) + is_missing <- is.na(hash) + + cached[is_missing] <- TRUE + value[is_missing] <- list(missing) + + if (any(!cached)) { + value[!cached] <- private$DRIVER$mget_object(hash[!cached]) + } + + if (any(is_missing)) { + attr(value, "missing") <- which(is_missing) + } + value + }, + + #' @description Get key's metadata. + #' + #' + #' @param key The key name to get metadata values from. + #' @param namespace The namespace to look the key within. + #' + #' @return A named list with the key-metadata: `"expires_at"` + #' and `"notes".` + #' + get_keymeta = function(key, namespace = self$default_namespace) { + + private$check_input(key, n = 1, type = "character") + private$check_input(namespace, n = 1, type = "character") + + keyns <- paste(key, namespace, sep = ":") + + value <- private$DRIVER$get_keymeta(key, namespace) + + value + }, + + #' @description Get multiple key metadata. + #' + #' `r sto_recycle_note` + #' + #' @param key A character vector with keys to get metadata values from. + #' @param namespace A character vector of namespaces to look the keys within. + #' @param missing Fill value for missing keys. Default is `NULL`. + #' + #' @return A list with key metadata for each key-namespace + #' pair. For not found pairs will return the `missing` value. + #' + mget_keymeta = function(key, + namespace = self$default_namespace, + missing = NULL) { + + p <- storr::join_key_namespace(key, namespace) + n <- p$n + + key <- p$key + namespace <- p$namespace + keyns <- paste(key, namespace, sep = ":") + + value <- vector("list", n) + cached <- logical(n) + + # Everything is TRUE, so go to find them in DB + not_cached <- !cached + status_not_cached <- TRUE + num_cached <- 0L + + is_missing <- FALSE + + if (status_not_cached) { + + # From not_cached find also which are truly missing + cc <- private$DRIVER$mget_keymeta(key[not_cached], + namespace[not_cached], + nomatch = missing) + + value[not_cached] <- cc + keyns_not_cached <- keyns[not_cached] + + # not_cached and not found + keyns_missing <- keyns_not_cached[attr(cc, "missing")] + + # Truly missing key-namespace pairs + is_missing <- keyns %in% keyns_missing + } + + + if (any(is_missing)) { + attr(value, "missing") <- which(is_missing) #+ num_cached + } + value + }, + + #' @description Check a key-namespace pair exists. + #' + #' `r sto_recycle_note` + #' + #' @param key `r sto_key(1)` + #' @param namespace `r sto_namespace(1)` + #' + #' @return A logical vector indicating which key-namespace pair exists. + #' + exists = function(key, namespace = self$default_namespace) { + private$DRIVER$exists_hash(key, namespace) + }, + + #' @description Check a serialised object exists given a hash. + #' + #' @param hash `r roxy_hash` + #' + #' @return A logical vector indicating which object exists. + #' + exists_object = function(hash) { + private$DRIVER$exists_object(hash) + }, + + #' @description Get the key-namespace pairs with expiration timestamps. + #' + #' @param namespace `r sto_namespaces_or_null` + #' @param datetimes Should the `expires_at` column be returned? + #' Default is `TRUE`. + #' + #' @return An object of class `data.table`. + #' + keys_with_expiration = function(namespace = self$default_namespace, datetimes = TRUE) { + out <- private$DRIVER$keys_with_expiration(namespace, datetimes = datetimes) + data.table::as.data.table(out) + }, + + #' @description Get the expired key-namespace pairs. + #' + #' @param namespace `r sto_namespaces_or_null` + #' @param datetimes Should the `expires_at` column be returned? + #' Default is `TRUE`. + #' + #' @return An object of class `data.table`. + #' + expired_keys = function(namespace = self$default_namespace, datetimes = TRUE) { + out <- private$DRIVER$expired_keys(namespace, datetimes = datetimes) + data.table::as.data.table(out) + }, + + #' @description Check for expired key-namespace pairs. + #' + #' @param namespace `r sto_namespaces_or_null` + #' + #' @return `TRUE` for expired keys, `FALSE` otherwise. + #' + has_expired_keys = function(namespace = self$default_namespace) { + + private$DRIVER$has_expired_keys(namespace) + + }, + + #' @description List all keys stored in a namespace. + #' + #' @param namespace `r sto_namespace()` + #' + #' @return A sorted character vector with keys. + #' + list = function(namespace = self$default_namespace) { + + sort(private$DRIVER$list_keys(namespace)) + }, + + #' @description List all hashes stored in the storr. + #' + #' + #' @return A sorted character vector with hashes. + #' + list_hashes = function() { + + sort(private$DRIVER$list_hashes()) + }, + + #' @description List all namespaces in the storr. + #' + #' + #' @return A sorted character vector with namespaces. + #' + list_namespaces = function() { + + sort(private$DRIVER$list_namespaces()) + }, + + #' @description Export objects from storr. + #' + #' Use list() to export to a brand new list, or use as.list(object) for a shorthand. + #' + #' @param dest A destination to export objects to. It can be a storr, list, or environment. + #' @param list Names of objects to import (or `NULL` for all objects) . If given it must be a character vector. + #' If named, the names of the character vector will be the names of the objects as created in the storr. + #' @param namespace Namespace to get objects from, and to put objects into. If `NULL`, + #' then this will export namespaces from this (source) storr into the destination; + #' if there is more than one namespace, this is only possible if `dest` + #' is a storr (otherwise there will be an error). + #' @param skip_missing Logical, indicating if missing keys (specified in `list`) + #' should be skipped over, rather than being treated as an error (the default). + #' + #' + #' @return `dest` object, invisibly. + #' + export = function(dest, list = NULL, namespace = self$default_namespace, + skip_missing = FALSE) { + + if (is.null(namespace)) { + namespace <- self$list_namespaces() + } + + invisible(.base_export(dest, self, list, namespace, skip_missing)$dest) + }, + + #' @description Generate a `data.table` with an index of objects + #' present in a storr. + #' + #' + #' @param namespace `r sto_namespaces_or_null` + #' + #' @return An object of class `data.table`. + #' + index_export = function(namespace = NULL) { + + out <- private$DRIVER$filter_keys(character(), namespace = namespace)[] + + if (nrow(out) == 0) { + + d <- data.frame( + namespace = character(0), + key = character(0), + hash = character(0), + expires_at = as.POSIXct(double()), + notes = character(0) + ) + + out <- data.table::as.data.table(d) + } + + out + } + + ), + + active = list( + + #'@field timestamp Set or retrieve a `TileDB` timestamp range that + #' the resource will be opened at. Effective in `"READ"` mode only. + #' + timestamp = function(value) { + + if (!missing(value)) { + private$DRIVER$tiledb_timestamp <- value + } else { + private$DRIVER$tiledb_timestamp + } + + } + ), + + private = list( + + # @field driver The TileDB driver. + # + DRIVER = NULL, + + # NOTE: extracted from storr:::check_length + check_length = function(key, namespace) { + + n_key <- length(key) + n_namespace <- length(namespace) + if (n_key == n_namespace || n_namespace == 1) { + n_key + } + else if (n_key == 1) { + n_namespace + } + else { + stop("Incompatible lengths for key and namespace", call. = FALSE) + } + }, + + check_input = function(x, n, type = NULL) { + name <- deparse(substitute(x)) + + switch (type, 'character' = { + if (isFALSE(.is_character(x))) { + stop(sprintf("'%s' should be a character string, not %s", name, class(x)), + call. = FALSE) + } + }, 'datetime' = { + if (isFALSE(inherits(x, "POSIXct"))) { + stop(sprintf("'%s' should be a date-time object, not %s", name, class(x)), + call. = FALSE) + } + }) + + if (length(x) != n) { + stop(sprintf("'%s' must have %d elements (recieved %d)", name, n, length(x)), + call. = FALSE) + } + } + + ) +) diff --git a/man/StorrTimeTravel.Rd b/man/StorrTimeTravel.Rd new file mode 100644 index 0000000..3ccfb7d --- /dev/null +++ b/man/StorrTimeTravel.Rd @@ -0,0 +1,504 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/StorrTimeTravel.R +\name{StorrTimeTravel} +\alias{StorrTimeTravel} +\title{Generate a \code{StorrTimeTravel} Object} +\value{ +A \code{StorrTimeTravel}, \code{R6} object. +} +\description{ +A \link{TileDBStorr} variant with read only class methods and +time-travel support. + +This class is not intended to be used directly and the preferred +usage is through \code{\link[=storr_timetravel]{storr_timetravel()}}. +} +\keyword{internal} +\section{Public fields}{ + \if{html}{\out{
}} + \describe{ + \item{\code{default_namespace}}{The default namespace.} + + \item{\code{traits}}{Driver traits.} + } + \if{html}{\out{
}} +} +\section{Active bindings}{ + \if{html}{\out{
}} + \describe{ + \item{\code{timestamp}}{Set or retrieve a \code{TileDB} timestamp range that +the resource will be opened at. Effective in \code{"READ"} mode only.} + } + \if{html}{\out{
}} +} +\section{Methods}{ +\subsection{Public methods}{ + \itemize{ + \item \href{#method-StorrTimeTravel-initialize}{\code{StorrTimeTravel$new()}} + \item \href{#method-StorrTimeTravel-get}{\code{StorrTimeTravel$get()}} + \item \href{#method-StorrTimeTravel-mget}{\code{StorrTimeTravel$mget()}} + \item \href{#method-StorrTimeTravel-get_hash}{\code{StorrTimeTravel$get_hash()}} + \item \href{#method-StorrTimeTravel-mget_hash}{\code{StorrTimeTravel$mget_hash()}} + \item \href{#method-StorrTimeTravel-get_value}{\code{StorrTimeTravel$get_value()}} + \item \href{#method-StorrTimeTravel-mget_value}{\code{StorrTimeTravel$mget_value()}} + \item \href{#method-StorrTimeTravel-get_keymeta}{\code{StorrTimeTravel$get_keymeta()}} + \item \href{#method-StorrTimeTravel-mget_keymeta}{\code{StorrTimeTravel$mget_keymeta()}} + \item \href{#method-StorrTimeTravel-exists}{\code{StorrTimeTravel$exists()}} + \item \href{#method-StorrTimeTravel-exists_object}{\code{StorrTimeTravel$exists_object()}} + \item \href{#method-StorrTimeTravel-keys_with_expiration}{\code{StorrTimeTravel$keys_with_expiration()}} + \item \href{#method-StorrTimeTravel-expired_keys}{\code{StorrTimeTravel$expired_keys()}} + \item \href{#method-StorrTimeTravel-has_expired_keys}{\code{StorrTimeTravel$has_expired_keys()}} + \item \href{#method-StorrTimeTravel-list}{\code{StorrTimeTravel$list()}} + \item \href{#method-StorrTimeTravel-list_hashes}{\code{StorrTimeTravel$list_hashes()}} + \item \href{#method-StorrTimeTravel-list_namespaces}{\code{StorrTimeTravel$list_namespaces()}} + \item \href{#method-StorrTimeTravel-export}{\code{StorrTimeTravel$export()}} + \item \href{#method-StorrTimeTravel-index_export}{\code{StorrTimeTravel$index_export()}} + } +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-StorrTimeTravel-initialize}{}}} +\subsection{\code{StorrTimeTravel$new()}}{ + Initialise \code{StorrTimeTravel}. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{StorrTimeTravel$new(driver, default_namespace)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{driver}}{A \link{TTDriver} object.} + \item{\code{default_namespace}}{The default namespace.} + } + \if{html}{\out{
}} + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-StorrTimeTravel-get}{}}} +\subsection{\code{StorrTimeTravel$get()}}{ + Get an object given a key-namespace pair. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{StorrTimeTravel$get(key, namespace = self$default_namespace)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{key}}{A scalar character of key name.} + \item{\code{namespace}}{A scalar character of namespace name.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + The \code{R} object if available. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-StorrTimeTravel-mget}{}}} +\subsection{\code{StorrTimeTravel$mget()}}{ + Get multiple objects. + +The arguments \code{key} and \code{namespace} can be recycled if any of them is a +scalar character and the other is a vector. No other recycling rule is permitted. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{StorrTimeTravel$mget(key, namespace = self$default_namespace, + missing = NULL)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{key}}{A character vector of key names.} + \item{\code{namespace}}{A character vector of namespaces.} + \item{\code{missing}}{Value to use for missing elements.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + A list of \code{R} objects. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-StorrTimeTravel-get_hash}{}}} +\subsection{\code{StorrTimeTravel$get_hash()}}{ + Get hash value. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{StorrTimeTravel$get_hash(key, namespace = self$default_namespace)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{key}}{A scalar character of key name.} + \item{\code{namespace}}{A scalar character of namespace name.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + The hash value. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-StorrTimeTravel-mget_hash}{}}} +\subsection{\code{StorrTimeTravel$mget_hash()}}{ + Get hash values. + +The arguments \code{key} and \code{namespace} can be recycled if any of them is a +scalar character and the other is a vector. No other recycling rule is permitted. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{StorrTimeTravel$mget_hash(key, namespace = self$default_namespace)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{key}}{A character vector of key names.} + \item{\code{namespace}}{A character vector of namespaces.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + A vector of hashes. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-StorrTimeTravel-get_value}{}}} +\subsection{\code{StorrTimeTravel$get_value()}}{ + Get an object given its hash. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{StorrTimeTravel$get_value(hash)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{hash}}{The hash value of the object.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + The \code{R} object if available. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-StorrTimeTravel-mget_value}{}}} +\subsection{\code{StorrTimeTravel$mget_value()}}{ + Get multiple objects given their hashes. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{StorrTimeTravel$mget_value(hash, missing = NULL)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{hash}}{A vector of hash values."} + \item{\code{missing}}{Value to use for missing elements.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + A list of \code{R} objects. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-StorrTimeTravel-get_keymeta}{}}} +\subsection{\code{StorrTimeTravel$get_keymeta()}}{ + Get key's metadata. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{StorrTimeTravel$get_keymeta(key, namespace = self$default_namespace)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{key}}{The key name to get metadata values from.} + \item{\code{namespace}}{The namespace to look the key within.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + A named list with the key-metadata: \code{"expires_at"} +and \verb{"notes".} + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-StorrTimeTravel-mget_keymeta}{}}} +\subsection{\code{StorrTimeTravel$mget_keymeta()}}{ + Get multiple key metadata. + +The arguments \code{key} and \code{namespace} can be recycled if any of them is a +scalar character and the other is a vector. No other recycling rule is permitted. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{StorrTimeTravel$mget_keymeta(key, namespace = self$default_namespace, + missing = NULL)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{key}}{A character vector with keys to get metadata values from.} + \item{\code{namespace}}{A character vector of namespaces to look the keys within.} + \item{\code{missing}}{Fill value for missing keys. Default is \code{NULL}.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + A list with key metadata for each key-namespace +pair. For not found pairs will return the \code{missing} value. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-StorrTimeTravel-exists}{}}} +\subsection{\code{StorrTimeTravel$exists()}}{ + Check a key-namespace pair exists. + +The arguments \code{key} and \code{namespace} can be recycled if any of them is a +scalar character and the other is a vector. No other recycling rule is permitted. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{StorrTimeTravel$exists(key, namespace = self$default_namespace)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{key}}{A character vector of key names.} + \item{\code{namespace}}{A character vector of namespaces.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + A logical vector indicating which key-namespace pair exists. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-StorrTimeTravel-exists_object}{}}} +\subsection{\code{StorrTimeTravel$exists_object()}}{ + Check a serialised object exists given a hash. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{StorrTimeTravel$exists_object(hash)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{hash}}{A vector of hash values.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + A logical vector indicating which object exists. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-StorrTimeTravel-keys_with_expiration}{}}} +\subsection{\code{StorrTimeTravel$keys_with_expiration()}}{ + Get the key-namespace pairs with expiration timestamps. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{StorrTimeTravel$keys_with_expiration(namespace = self$default_namespace, + datetimes = TRUE)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{namespace}}{A character vector of namespaces or \code{NULL} for all namespaces.} + \item{\code{datetimes}}{Should the \code{expires_at} column be returned? +Default is \code{TRUE}.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + An object of class \code{data.table}. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-StorrTimeTravel-expired_keys}{}}} +\subsection{\code{StorrTimeTravel$expired_keys()}}{ + Get the expired key-namespace pairs. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{StorrTimeTravel$expired_keys(namespace = self$default_namespace, + datetimes = TRUE)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{namespace}}{A character vector of namespaces or \code{NULL} for all namespaces.} + \item{\code{datetimes}}{Should the \code{expires_at} column be returned? +Default is \code{TRUE}.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + An object of class \code{data.table}. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-StorrTimeTravel-has_expired_keys}{}}} +\subsection{\code{StorrTimeTravel$has_expired_keys()}}{ + Check for expired key-namespace pairs. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{StorrTimeTravel$has_expired_keys(namespace = self$default_namespace)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{namespace}}{A character vector of namespaces or \code{NULL} for all namespaces.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + \code{TRUE} for expired keys, \code{FALSE} otherwise. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-StorrTimeTravel-list}{}}} +\subsection{\code{StorrTimeTravel$list()}}{ + List all keys stored in a namespace. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{StorrTimeTravel$list(namespace = self$default_namespace)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{namespace}}{A scalar character of namespace name.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + A sorted character vector with keys. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-StorrTimeTravel-list_hashes}{}}} +\subsection{\code{StorrTimeTravel$list_hashes()}}{ + List all hashes stored in the storr. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{StorrTimeTravel$list_hashes()} + \if{html}{\out{
}} + } + \subsection{Returns}{ + A sorted character vector with hashes. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-StorrTimeTravel-list_namespaces}{}}} +\subsection{\code{StorrTimeTravel$list_namespaces()}}{ + List all namespaces in the storr. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{StorrTimeTravel$list_namespaces()} + \if{html}{\out{
}} + } + \subsection{Returns}{ + A sorted character vector with namespaces. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-StorrTimeTravel-export}{}}} +\subsection{\code{StorrTimeTravel$export()}}{ + Export objects from storr. + +Use list() to export to a brand new list, or use as.list(object) for a shorthand. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{StorrTimeTravel$export(dest, list = NULL, + namespace = self$default_namespace, skip_missing = FALSE)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{dest}}{A destination to export objects to. It can be a storr, list, or environment.} + \item{\code{list}}{Names of objects to import (or \code{NULL} for all objects) . If given it must be a character vector. +If named, the names of the character vector will be the names of the objects as created in the storr.} + \item{\code{namespace}}{Namespace to get objects from, and to put objects into. If \code{NULL}, +then this will export namespaces from this (source) storr into the destination; +if there is more than one namespace, this is only possible if \code{dest} +is a storr (otherwise there will be an error).} + \item{\code{skip_missing}}{Logical, indicating if missing keys (specified in \code{list}) +should be skipped over, rather than being treated as an error (the default).} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + \code{dest} object, invisibly. + } +} + +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-StorrTimeTravel-index_export}{}}} +\subsection{\code{StorrTimeTravel$index_export()}}{ + Generate a \code{data.table} with an index of objects +present in a storr. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{StorrTimeTravel$index_export(namespace = NULL)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{namespace}}{A character vector of namespaces or \code{NULL} for all namespaces.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + An object of class \code{data.table}. + } +} + +} From 4ce2f53b9f2b467c47e6765087f7513618604513 Mon Sep 17 00:00:00 2001 From: Constantinos Giachalis Date: Tue, 19 May 2026 09:59:52 +0300 Subject: [PATCH 04/24] Rename TTDriver -> TimeDriver --- R/StorrTimeTravel.R | 4 +- R/{TTDriver.R => TimeDriver.R} | 10 +- man/StorrTimeTravel.Rd | 2 +- man/{TTDriver.Rd => TimeDriver.Rd} | 264 ++++++++++++++--------------- 4 files changed, 140 insertions(+), 140 deletions(-) rename R/{TTDriver.R => TimeDriver.R} (99%) rename man/{TTDriver.Rd => TimeDriver.Rd} (66%) diff --git a/R/StorrTimeTravel.R b/R/StorrTimeTravel.R index a85ab8e..c1b90e4 100644 --- a/R/StorrTimeTravel.R +++ b/R/StorrTimeTravel.R @@ -28,12 +28,12 @@ StorrTimeTravel <- R6::R6Class( #' @description Initialise `StorrTimeTravel`. #' - #' @param driver A [TTDriver] object. + #' @param driver A [TimeDriver] object. #' @param default_namespace The default namespace. #' initialize = function(driver, default_namespace) { - if (!inherits(driver, "TTDriver")) { + if (!inherits(driver, "TimeDriver")) { stop("Not a valid Time-Travel 'driver'. Please use a 'TTDriver' object.", call. = FALSE) } diff --git a/R/TTDriver.R b/R/TimeDriver.R similarity index 99% rename from R/TTDriver.R rename to R/TimeDriver.R index 3c2a505..e0f8355 100644 --- a/R/TTDriver.R +++ b/R/TimeDriver.R @@ -1,9 +1,9 @@ -#' @title Generate a `TTDriver` Object +#' @title Generate a `TimeDriver` Object #' #' @description A [TileDBDriver] variant with read only class methods and #' time-travel support. #' -#' This class is intended for usage in [StorrTimeTravel]. +#' This class is intended for usage into [StorrTimeTravel]. #' #' @returns A `TTDriver`, `R6` object. #' @@ -11,10 +11,10 @@ #' #' @keywords internal #' -TTDriver <- R6::R6Class( +TimeDriver <- R6::R6Class( inherit = TileDBGroup, cloneable = FALSE, - classname = "TTDriver", + classname = "TimeDriver", public = list( @@ -24,7 +24,7 @@ TTDriver <- R6::R6Class( #' @description Instantiate a new `TTDriver` object. #' - #' @param uri URI path for the `TTDBDriver` object. + #' @param uri URI path for the `TimeBDriver` object. #' @param ctx Optional [tiledb::tiledb_ctx()] object. #' @param timestamp Set a `TileDB` timestamp range that #' the resource will be opened at. Effective in `"READ"` mode only. diff --git a/man/StorrTimeTravel.Rd b/man/StorrTimeTravel.Rd index 3ccfb7d..0b6d73e 100644 --- a/man/StorrTimeTravel.Rd +++ b/man/StorrTimeTravel.Rd @@ -68,7 +68,7 @@ the resource will be opened at. Effective in \code{"READ"} mode only.} \subsection{Arguments}{ \if{html}{\out{
}} \describe{ - \item{\code{driver}}{A \link{TTDriver} object.} + \item{\code{driver}}{A \link{TimeDriver} object.} \item{\code{default_namespace}}{The default namespace.} } \if{html}{\out{
}} diff --git a/man/TTDriver.Rd b/man/TimeDriver.Rd similarity index 66% rename from man/TTDriver.Rd rename to man/TimeDriver.Rd index 12a0d0c..927d7ae 100644 --- a/man/TTDriver.Rd +++ b/man/TimeDriver.Rd @@ -1,8 +1,8 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/TTDriver.R -\name{TTDriver} -\alias{TTDriver} -\title{Generate a \code{TTDriver} Object} +% Please edit documentation in R/TimeDriver.R +\name{TimeDriver} +\alias{TimeDriver} +\title{Generate a \code{TimeDriver} Object} \value{ A \code{TTDriver}, \code{R6} object. } @@ -10,11 +10,11 @@ A \code{TTDriver}, \code{R6} object. A \link{TileDBDriver} variant with read only class methods and time-travel support. -This class is intended for usage in \link{StorrTimeTravel}. +This class is intended for usage into \link{StorrTimeTravel}. } \keyword{internal} \section{Super classes}{ -\code{\link[R6.tiledb:TileDBObject]{R6.tiledb::TileDBObject}} -> \code{\link[R6.tiledb:TileDBGroup]{R6.tiledb::TileDBGroup}} -> \code{TTDriver} +\code{\link[R6.tiledb:TileDBObject]{R6.tiledb::TileDBObject}} -> \code{\link[R6.tiledb:TileDBGroup]{R6.tiledb::TileDBGroup}} -> \code{TimeDriver} } \section{Public fields}{ \if{html}{\out{
}} @@ -36,31 +36,31 @@ the resource will be opened at. Effective in \code{"READ"} mode only.} \section{Methods}{ \subsection{Public methods}{ \itemize{ - \item \href{#method-TTDriver-initialize}{\code{TTDriver$new()}} - \item \href{#method-TTDriver-type}{\code{TTDriver$type()}} - \item \href{#method-TTDriver-open}{\code{TTDriver$open()}} - \item \href{#method-TTDriver-close}{\code{TTDriver$close()}} - \item \href{#method-TTDriver-filter_keys}{\code{TTDriver$filter_keys()}} - \item \href{#method-TTDriver-get_hash}{\code{TTDriver$get_hash()}} - \item \href{#method-TTDriver-mget_hash}{\code{TTDriver$mget_hash()}} - \item \href{#method-TTDriver-get_object}{\code{TTDriver$get_object()}} - \item \href{#method-TTDriver-mget_object}{\code{TTDriver$mget_object()}} - \item \href{#method-TTDriver-get_keymeta}{\code{TTDriver$get_keymeta()}} - \item \href{#method-TTDriver-mget_keymeta}{\code{TTDriver$mget_keymeta()}} - \item \href{#method-TTDriver-exists_hash}{\code{TTDriver$exists_hash()}} - \item \href{#method-TTDriver-exists_object}{\code{TTDriver$exists_object()}} - \item \href{#method-TTDriver-list_hashes}{\code{TTDriver$list_hashes()}} - \item \href{#method-TTDriver-list_namespaces}{\code{TTDriver$list_namespaces()}} - \item \href{#method-TTDriver-list_keys}{\code{TTDriver$list_keys()}} - \item \href{#method-TTDriver-list_unused_hashes}{\code{TTDriver$list_unused_hashes()}} - \item \href{#method-TTDriver-keys_with_expiration}{\code{TTDriver$keys_with_expiration()}} - \item \href{#method-TTDriver-keys_without_expiration}{\code{TTDriver$keys_without_expiration()}} - \item \href{#method-TTDriver-expired_keys}{\code{TTDriver$expired_keys()}} - \item \href{#method-TTDriver-unexpired_keys}{\code{TTDriver$unexpired_keys()}} - \item \href{#method-TTDriver-num_expired_keys}{\code{TTDriver$num_expired_keys()}} - \item \href{#method-TTDriver-num_unexpired_keys}{\code{TTDriver$num_unexpired_keys()}} - \item \href{#method-TTDriver-has_expired_keys}{\code{TTDriver$has_expired_keys()}} - \item \href{#method-TTDriver-has_unexpired_keys}{\code{TTDriver$has_unexpired_keys()}} + \item \href{#method-TimeDriver-initialize}{\code{TimeDriver$new()}} + \item \href{#method-TimeDriver-type}{\code{TimeDriver$type()}} + \item \href{#method-TimeDriver-open}{\code{TimeDriver$open()}} + \item \href{#method-TimeDriver-close}{\code{TimeDriver$close()}} + \item \href{#method-TimeDriver-filter_keys}{\code{TimeDriver$filter_keys()}} + \item \href{#method-TimeDriver-get_hash}{\code{TimeDriver$get_hash()}} + \item \href{#method-TimeDriver-mget_hash}{\code{TimeDriver$mget_hash()}} + \item \href{#method-TimeDriver-get_object}{\code{TimeDriver$get_object()}} + \item \href{#method-TimeDriver-mget_object}{\code{TimeDriver$mget_object()}} + \item \href{#method-TimeDriver-get_keymeta}{\code{TimeDriver$get_keymeta()}} + \item \href{#method-TimeDriver-mget_keymeta}{\code{TimeDriver$mget_keymeta()}} + \item \href{#method-TimeDriver-exists_hash}{\code{TimeDriver$exists_hash()}} + \item \href{#method-TimeDriver-exists_object}{\code{TimeDriver$exists_object()}} + \item \href{#method-TimeDriver-list_hashes}{\code{TimeDriver$list_hashes()}} + \item \href{#method-TimeDriver-list_namespaces}{\code{TimeDriver$list_namespaces()}} + \item \href{#method-TimeDriver-list_keys}{\code{TimeDriver$list_keys()}} + \item \href{#method-TimeDriver-list_unused_hashes}{\code{TimeDriver$list_unused_hashes()}} + \item \href{#method-TimeDriver-keys_with_expiration}{\code{TimeDriver$keys_with_expiration()}} + \item \href{#method-TimeDriver-keys_without_expiration}{\code{TimeDriver$keys_without_expiration()}} + \item \href{#method-TimeDriver-expired_keys}{\code{TimeDriver$expired_keys()}} + \item \href{#method-TimeDriver-unexpired_keys}{\code{TimeDriver$unexpired_keys()}} + \item \href{#method-TimeDriver-num_expired_keys}{\code{TimeDriver$num_expired_keys()}} + \item \href{#method-TimeDriver-num_unexpired_keys}{\code{TimeDriver$num_unexpired_keys()}} + \item \href{#method-TimeDriver-has_expired_keys}{\code{TimeDriver$has_expired_keys()}} + \item \href{#method-TimeDriver-has_unexpired_keys}{\code{TimeDriver$has_unexpired_keys()}} } } \if{html}{\out{
Inherited methods @@ -85,19 +85,19 @@ the resource will be opened at. Effective in \code{"READ"} mode only.}
}} \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TTDriver-initialize}{}}} -\subsection{\code{TTDriver$new()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeDriver-initialize}{}}} +\subsection{\code{TimeDriver$new()}}{ Instantiate a new \code{TTDriver} object. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TTDriver$new(uri, ctx = NULL, timestamp = NULL)} + \preformatted{TimeDriver$new(uri, ctx = NULL, timestamp = NULL)} \if{html}{\out{
}} } \subsection{Arguments}{ \if{html}{\out{
}} \describe{ - \item{\code{uri}}{URI path for the \code{TTDBDriver} object.} + \item{\code{uri}}{URI path for the \code{TimeBDriver} object.} \item{\code{ctx}}{Optional \code{\link[tiledb:tiledb_ctx]{tiledb::tiledb_ctx()}} object.} \item{\code{timestamp}}{Set a \code{TileDB} timestamp range that the resource will be opened at. Effective in \code{"READ"} mode only. @@ -114,13 +114,13 @@ or length 2 with start, end timestamps } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TTDriver-type}{}}} -\subsection{\code{TTDriver$type()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeDriver-type}{}}} +\subsection{\code{TimeDriver$type()}}{ Driver type. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TTDriver$type()} + \preformatted{TimeDriver$type()} \if{html}{\out{
}} } \subsection{Returns}{ @@ -129,9 +129,9 @@ or length 2 with start, end timestamps } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TTDriver-open}{}}} -\subsection{\code{TTDriver$open()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeDriver-open}{}}} +\subsection{\code{TimeDriver$open()}}{ Open \code{TTDriver} object for read or write. Setting\code{instantiate} argument to \code{TRUE}, all members will be instantiated @@ -139,7 +139,7 @@ and cached on opening. They can be accessed via \code{members} active field, i.e \verb{$object} element. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TTDriver$open(mode = c("READ", "WRITE"), instantiate = FALSE)} + \preformatted{TimeDriver$open(mode = c("READ", "WRITE"), instantiate = FALSE)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -157,16 +157,16 @@ Default is \code{FALSE}.} } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TTDriver-close}{}}} -\subsection{\code{TTDriver$close()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeDriver-close}{}}} +\subsection{\code{TimeDriver$close()}}{ Close the group object. All instantiated group members will be closed if opened, and before closing the group object. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TTDriver$close()} + \preformatted{TimeDriver$close()} \if{html}{\out{
}} } \subsection{Returns}{ @@ -175,13 +175,13 @@ closing the group object. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TTDriver-filter_keys}{}}} -\subsection{\code{TTDriver$filter_keys()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeDriver-filter_keys}{}}} +\subsection{\code{TimeDriver$filter_keys()}}{ Filter \code{tbl_keys} by key and namespace \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TTDriver$filter_keys(key, namespace, attrnames = character())} + \preformatted{TimeDriver$filter_keys(key, namespace, attrnames = character())} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -199,13 +199,13 @@ closing the group object. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TTDriver-get_hash}{}}} -\subsection{\code{TTDriver$get_hash()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeDriver-get_hash}{}}} +\subsection{\code{TimeDriver$get_hash()}}{ Get hash values. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TTDriver$get_hash(key, namespace)} + \preformatted{TimeDriver$get_hash(key, namespace)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -222,13 +222,13 @@ closing the group object. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TTDriver-mget_hash}{}}} -\subsection{\code{TTDriver$mget_hash()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeDriver-mget_hash}{}}} +\subsection{\code{TimeDriver$mget_hash()}}{ Get hash values. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TTDriver$mget_hash(key, namespace)} + \preformatted{TimeDriver$mget_hash(key, namespace)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -245,13 +245,13 @@ closing the group object. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TTDriver-get_object}{}}} -\subsection{\code{TTDriver$get_object()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeDriver-get_object}{}}} +\subsection{\code{TimeDriver$get_object()}}{ Get R object given a hash. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TTDriver$get_object(hash)} + \preformatted{TimeDriver$get_object(hash)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -267,13 +267,13 @@ closing the group object. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TTDriver-mget_object}{}}} -\subsection{\code{TTDriver$mget_object()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeDriver-mget_object}{}}} +\subsection{\code{TimeDriver$mget_object()}}{ Get a list R objects given a hash vector. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TTDriver$mget_object(hash)} + \preformatted{TimeDriver$mget_object(hash)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -289,13 +289,13 @@ closing the group object. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TTDriver-get_keymeta}{}}} -\subsection{\code{TTDriver$get_keymeta()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeDriver-get_keymeta}{}}} +\subsection{\code{TimeDriver$get_keymeta()}}{ Get key-namespace metadata. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TTDriver$get_keymeta(key, namespace)} + \preformatted{TimeDriver$get_keymeta(key, namespace)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -313,13 +313,13 @@ and \verb{"notes".} } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TTDriver-mget_keymeta}{}}} -\subsection{\code{TTDriver$mget_keymeta()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeDriver-mget_keymeta}{}}} +\subsection{\code{TimeDriver$mget_keymeta()}}{ Get multiple key-namespace metadata. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TTDriver$mget_keymeta(key, namespace, nomatch = NULL)} + \preformatted{TimeDriver$mget_keymeta(key, namespace, nomatch = NULL)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -338,13 +338,13 @@ pair. For not found pairs will return the nomatch value. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TTDriver-exists_hash}{}}} -\subsection{\code{TTDriver$exists_hash()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeDriver-exists_hash}{}}} +\subsection{\code{TimeDriver$exists_hash()}}{ Check a key-namespace pair exists. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TTDriver$exists_hash(key, namespace)} + \preformatted{TimeDriver$exists_hash(key, namespace)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -361,13 +361,13 @@ pair. For not found pairs will return the nomatch value. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TTDriver-exists_object}{}}} -\subsection{\code{TTDriver$exists_object()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeDriver-exists_object}{}}} +\subsection{\code{TimeDriver$exists_object()}}{ Check a serialised object exists. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TTDriver$exists_object(hash)} + \preformatted{TimeDriver$exists_object(hash)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -383,13 +383,13 @@ pair. For not found pairs will return the nomatch value. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TTDriver-list_hashes}{}}} -\subsection{\code{TTDriver$list_hashes()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeDriver-list_hashes}{}}} +\subsection{\code{TimeDriver$list_hashes()}}{ List all hash values. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TTDriver$list_hashes()} + \preformatted{TimeDriver$list_hashes()} \if{html}{\out{
}} } \subsection{Returns}{ @@ -398,13 +398,13 @@ pair. For not found pairs will return the nomatch value. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TTDriver-list_namespaces}{}}} -\subsection{\code{TTDriver$list_namespaces()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeDriver-list_namespaces}{}}} +\subsection{\code{TimeDriver$list_namespaces()}}{ List all namespace values. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TTDriver$list_namespaces()} + \preformatted{TimeDriver$list_namespaces()} \if{html}{\out{
}} } \subsection{Returns}{ @@ -413,13 +413,13 @@ pair. For not found pairs will return the nomatch value. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TTDriver-list_keys}{}}} -\subsection{\code{TTDriver$list_keys()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeDriver-list_keys}{}}} +\subsection{\code{TimeDriver$list_keys()}}{ List keys given a namespace. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TTDriver$list_keys(namespace)} + \preformatted{TimeDriver$list_keys(namespace)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -435,13 +435,13 @@ pair. For not found pairs will return the nomatch value. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TTDriver-list_unused_hashes}{}}} -\subsection{\code{TTDriver$list_unused_hashes()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeDriver-list_unused_hashes}{}}} +\subsection{\code{TimeDriver$list_unused_hashes()}}{ List unused hashes. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TTDriver$list_unused_hashes()} + \preformatted{TimeDriver$list_unused_hashes()} \if{html}{\out{
}} } \subsection{Returns}{ @@ -450,13 +450,13 @@ pair. For not found pairs will return the nomatch value. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TTDriver-keys_with_expiration}{}}} -\subsection{\code{TTDriver$keys_with_expiration()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeDriver-keys_with_expiration}{}}} +\subsection{\code{TimeDriver$keys_with_expiration()}}{ Get the key-namespace pairs with expiration timestamps. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TTDriver$keys_with_expiration(namespace, datetimes = TRUE)} + \preformatted{TimeDriver$keys_with_expiration(namespace, datetimes = TRUE)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -474,13 +474,13 @@ Default is \code{TRUE}.} } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TTDriver-keys_without_expiration}{}}} -\subsection{\code{TTDriver$keys_without_expiration()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeDriver-keys_without_expiration}{}}} +\subsection{\code{TimeDriver$keys_without_expiration()}}{ Get the key-namespace pairs without expiration timestamps. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TTDriver$keys_without_expiration(namespace, datetimes = TRUE)} + \preformatted{TimeDriver$keys_without_expiration(namespace, datetimes = TRUE)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -498,13 +498,13 @@ Default is \code{TRUE}.} } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TTDriver-expired_keys}{}}} -\subsection{\code{TTDriver$expired_keys()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeDriver-expired_keys}{}}} +\subsection{\code{TimeDriver$expired_keys()}}{ Get the expired key-namespace pairs. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TTDriver$expired_keys(namespace, datetimes = TRUE)} + \preformatted{TimeDriver$expired_keys(namespace, datetimes = TRUE)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -522,13 +522,13 @@ Default is \code{TRUE}.} } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TTDriver-unexpired_keys}{}}} -\subsection{\code{TTDriver$unexpired_keys()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeDriver-unexpired_keys}{}}} +\subsection{\code{TimeDriver$unexpired_keys()}}{ Get the unexpired key-namespace pairs. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TTDriver$unexpired_keys(namespace, datetimes = TRUE)} + \preformatted{TimeDriver$unexpired_keys(namespace, datetimes = TRUE)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -546,13 +546,13 @@ Default is \code{TRUE}.} } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TTDriver-num_expired_keys}{}}} -\subsection{\code{TTDriver$num_expired_keys()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeDriver-num_expired_keys}{}}} +\subsection{\code{TimeDriver$num_expired_keys()}}{ Get the number of expired key-namespace pairs. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TTDriver$num_expired_keys(namespace)} + \preformatted{TimeDriver$num_expired_keys(namespace)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -568,13 +568,13 @@ Default is \code{TRUE}.} } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TTDriver-num_unexpired_keys}{}}} -\subsection{\code{TTDriver$num_unexpired_keys()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeDriver-num_unexpired_keys}{}}} +\subsection{\code{TimeDriver$num_unexpired_keys()}}{ Get the number of unexpired key-namespace pairs. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TTDriver$num_unexpired_keys(namespace)} + \preformatted{TimeDriver$num_unexpired_keys(namespace)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -590,13 +590,13 @@ Default is \code{TRUE}.} } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TTDriver-has_expired_keys}{}}} -\subsection{\code{TTDriver$has_expired_keys()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeDriver-has_expired_keys}{}}} +\subsection{\code{TimeDriver$has_expired_keys()}}{ Check for expired key-namespace pairs. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TTDriver$has_expired_keys(namespace)} + \preformatted{TimeDriver$has_expired_keys(namespace)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -612,13 +612,13 @@ Default is \code{TRUE}.} } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TTDriver-has_unexpired_keys}{}}} -\subsection{\code{TTDriver$has_unexpired_keys()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeDriver-has_unexpired_keys}{}}} +\subsection{\code{TimeDriver$has_unexpired_keys()}}{ Check for unexpired key-namespace pairs. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TTDriver$has_unexpired_keys(namespace)} + \preformatted{TimeDriver$has_unexpired_keys(namespace)} \if{html}{\out{
}} } \subsection{Arguments}{ From 76ea83666615bdfd71e4646a506b69090a817746 Mon Sep 17 00:00:00 2001 From: Constantinos Giachalis Date: Tue, 19 May 2026 10:36:19 +0300 Subject: [PATCH 05/24] Fix timestamp in active field; code tweaks --- R/StorrTimeTravel.R | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/R/StorrTimeTravel.R b/R/StorrTimeTravel.R index c1b90e4..0784314 100644 --- a/R/StorrTimeTravel.R +++ b/R/StorrTimeTravel.R @@ -70,8 +70,8 @@ StorrTimeTravel <- R6::R6Class( get = function(key, namespace = self$default_namespace) { private$check_input(key, n = 1, type = "character") private$check_input(namespace, n = 1, type = "character") - self$get_value(self$get_hash(key, namespace)) - + hash <- self$get_hash(key, namespace) + self$get_value(hash) }, #' @description Get multiple objects. @@ -87,7 +87,8 @@ StorrTimeTravel <- R6::R6Class( mget = function(key, namespace = self$default_namespace, missing = NULL) { # NB: storr::join_key_namespace check is performed inside $query_keys0 - self$mget_value(self$mget_hash(key, namespace), missing) + hash <- self$mget_hash(key, namespace) + self$mget_value(hash, missing) }, #' @description Get hash value. @@ -104,8 +105,9 @@ StorrTimeTravel <- R6::R6Class( private$check_input(namespace, n = 1, type = "character") if (self$traits$throw_missing) { - tryCatch(private$DRIVER$get_hash(key, namespace), error = function(e) stop(KeyError(key, - namespace))) + tryCatch(private$DRIVER$get_hash(key, namespace), error = function(e) { + stop(KeyError(key,namespace)) + }) } else { if (self$exists(key, namespace)) { @@ -419,9 +421,9 @@ StorrTimeTravel <- R6::R6Class( timestamp = function(value) { if (!missing(value)) { - private$DRIVER$tiledb_timestamp <- value + private$DRIVER$timestamp <- value } else { - private$DRIVER$tiledb_timestamp + private$DRIVER$timestamp } } From 68a4f20eee7fa23e28d553199134c118d65ee803 Mon Sep 17 00:00:00 2001 From: Constantinos Giachalis Date: Tue, 19 May 2026 10:52:32 +0300 Subject: [PATCH 06/24] Add `storr_timetravel` --- R/storr_timetravel.R | 63 ++++++++++++++++++++++++++++++++++++++ man/storr_timetravel.Rd | 68 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 R/storr_timetravel.R create mode 100644 man/storr_timetravel.Rd diff --git a/R/storr_timetravel.R b/R/storr_timetravel.R new file mode 100644 index 0000000..9555571 --- /dev/null +++ b/R/storr_timetravel.R @@ -0,0 +1,63 @@ +#' A Storr with Time-Travel +#' +#' A `'storr'` with read-only class methods and time-travel support. +#' +#' @inheritParams driver_tiledb +#' @param default_namespace The default namespace: `"objects"`. +#' @param timestamp Set a `TileDB` timestamp range that +#' the resource will be opened at. Effective only for `"READ"` mode. +#' Valid options: +#' - A `NULL` value (default) +#' - An `R` object coercible to `POSIXct` with length 1 which used for end timestamp, +#' or length 2 with start, end timestamps +#' - An object of class `tiledb_timestamp`. See [R6.tiledb::set_tiledb_timestamp()] +#' +#' Also, it can be set through active field `$timestamp`. +#' +#' @returns An object of class [StorrTimeTravel], R6. +#' +#' @export +#' +#' @examples +#' \dontrun{ +#' # URI path +#' uri <- tempfile() +#' sto <- storr_tiledb(uri, init = TRUE) +#' +#' # set key-values +#' t0 <- Sys.time() +#' sto$set("a", 1) +#' +#' t1 <- Sys.time() +#' sto$set("b", 2) +#' +#' t2 <- Sys.time() +#' +#' # Open storr with travel-support at t0 +#' stor <- storr_timetravel(uri, timestamp = t0) +#' +#' # Read at t0 +#' stor$get("a") # key 'a' ('objects') not found +#' +#' # Read at t1 +#' stor$timestamp <- t1 +#' stor$get("a") # 1 +#' stor$get("b") # key 'b' ('objects') not found +#' +#' # Read at t2 +#' stor$timestamp <- t2 +#' sto$get("b") # 2 +#' +#'} +#' +#' +storr_timetravel <- function(uri, + default_namespace = "objects", + context = NULL, + timestamp = NULL) { + + # check scalar namespace + dr <- TimeDriver$new(uri, ctx = context, timestamp = timestamp) + StorrTimeTravel$new(dr, default_namespace = default_namespace) + +} diff --git a/man/storr_timetravel.Rd b/man/storr_timetravel.Rd new file mode 100644 index 0000000..c40221c --- /dev/null +++ b/man/storr_timetravel.Rd @@ -0,0 +1,68 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/storr_timetravel.R +\name{storr_timetravel} +\alias{storr_timetravel} +\title{A Storr with Time-Travel} +\usage{ +storr_timetravel(uri, default_namespace = "objects", context = NULL, + timestamp = NULL) +} +\arguments{ +\item{uri}{The URI path of storr.} + +\item{default_namespace}{The default namespace: \code{"objects"}.} + +\item{context}{Optional \link[tiledb:tiledb_ctx]{tiledb_ctx} object.} + +\item{timestamp}{Set a \code{TileDB} timestamp range that +the resource will be opened at. Effective only for \code{"READ"} mode. +Valid options: +\itemize{ +\item A \code{NULL} value (default) +\item An \code{R} object coercible to \code{POSIXct} with length 1 which used for end timestamp, +or length 2 with start, end timestamps +\item An object of class \code{tiledb_timestamp}. See \code{\link[R6.tiledb:set_tiledb_timestamp]{R6.tiledb::set_tiledb_timestamp()}} +} + +Also, it can be set through active field \verb{$timestamp}.} +} +\value{ +An object of class \link{StorrTimeTravel}, R6. +} +\description{ +A \code{'storr'} with read-only class methods and time-travel support. +} +\examples{ +\dontrun{ +# URI path +uri <- tempfile() +sto <- storr_tiledb(uri, init = TRUE) + +# set key-values +t0 <- Sys.time() +sto$set("a", 1) + +t1 <- Sys.time() +sto$set("b", 2) + +t2 <- Sys.time() + +# Open storr with travel-support at t0 +stor <- storr_timetravel(uri, timestamp = t0) + +# Read at t0 +stor$get("a") # key 'a' ('objects') not found + +# Read at t1 +stor$timestamp <- t1 +stor$get("a") # 1 +stor$get("b") # key 'b' ('objects') not found + +# Read at t2 +stor$timestamp <- t2 +sto$get("b") # 2 + +} + + +} From f0a5e96cae80917898ac4df9acb46d4617e1eccd Mon Sep 17 00:00:00 2001 From: Constantinos Giachalis Date: Tue, 19 May 2026 10:53:19 +0300 Subject: [PATCH 07/24] Update NAMESPACE and pkgdown.yaml --- NAMESPACE | 3 +++ _pkgdown.yml | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/NAMESPACE b/NAMESPACE index 8a5e6df..73b6605 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -2,8 +2,10 @@ export(CAS) export(StorrFragments) +export(StorrTimeTravel) export(TileDBDriver) export(TileDBStorr) +export(TimeDriver) export(driver_tiledb) export(driver_tiledb_create) export(get_allocation_size_preference) @@ -15,6 +17,7 @@ export(storr_fragments) export(storr_move) export(storr_rename) export(storr_tiledb) +export(storr_timetravel) export(storr_vacuum) export(tiledb_config) export(tiledb_ctx) diff --git a/_pkgdown.yml b/_pkgdown.yml index 9311f13..d73d795 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -64,6 +64,7 @@ reference: Key functions to work with a 'storr' or creating a TileDB driver. contents: - storr_tiledb + - storr_timetravel - driver_tiledb - subtitle: Storr Management desc: | @@ -92,5 +93,6 @@ reference: - CAS - TileDBDriver - TileDBStorr + - TimeDriver - StorrFragments - + - StorrTimeTravel From 46920952738661becc665058ea9bff9ff3b37a9e Mon Sep 17 00:00:00 2001 From: Constantinos Giachalis Date: Tue, 19 May 2026 12:12:43 +0300 Subject: [PATCH 08/24] Polish documentation for storr_timetravel --- R/storr_timetravel.R | 8 +++++--- man/storr_timetravel.Rd | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/R/storr_timetravel.R b/R/storr_timetravel.R index 9555571..e142276 100644 --- a/R/storr_timetravel.R +++ b/R/storr_timetravel.R @@ -1,6 +1,6 @@ #' A Storr with Time-Travel #' -#' A `'storr'` with read-only class methods and time-travel support. +#' A `'storr'` variant with read-only class methods and time-travel support. #' #' @inheritParams driver_tiledb #' @param default_namespace The default namespace: `"objects"`. @@ -12,7 +12,7 @@ #' or length 2 with start, end timestamps #' - An object of class `tiledb_timestamp`. See [R6.tiledb::set_tiledb_timestamp()] #' -#' Also, it can be set through active field `$timestamp`. +#' Set a new timestamp with active field `$timestamp`, see examples. #' #' @returns An object of class [StorrTimeTravel], R6. #' @@ -33,10 +33,12 @@ #' #' t2 <- Sys.time() #' -#' # Open storr with travel-support at t0 +#' # Open storr with time-travel support at t0 #' stor <- storr_timetravel(uri, timestamp = t0) #' #' # Read at t0 +#' stor$list_hashes() # character(0), no hashes at t0 +#' #' stor$get("a") # key 'a' ('objects') not found #' #' # Read at t1 diff --git a/man/storr_timetravel.Rd b/man/storr_timetravel.Rd index c40221c..f380b38 100644 --- a/man/storr_timetravel.Rd +++ b/man/storr_timetravel.Rd @@ -24,13 +24,13 @@ or length 2 with start, end timestamps \item An object of class \code{tiledb_timestamp}. See \code{\link[R6.tiledb:set_tiledb_timestamp]{R6.tiledb::set_tiledb_timestamp()}} } -Also, it can be set through active field \verb{$timestamp}.} +Set a new timestamp with active field \verb{$timestamp}, see examples.} } \value{ An object of class \link{StorrTimeTravel}, R6. } \description{ -A \code{'storr'} with read-only class methods and time-travel support. +A \code{'storr'} variant with read-only class methods and time-travel support. } \examples{ \dontrun{ @@ -47,10 +47,12 @@ sto$set("b", 2) t2 <- Sys.time() -# Open storr with travel-support at t0 +# Open storr with time-travel support at t0 stor <- storr_timetravel(uri, timestamp = t0) # Read at t0 +stor$list_hashes() # character(0), no hashes at t0 + stor$get("a") # key 'a' ('objects') not found # Read at t1 From 2539caa534b5885b583e3f21bfda2a3e1ccc7178 Mon Sep 17 00:00:00 2001 From: Constantinos Giachalis Date: Tue, 19 May 2026 12:51:12 +0300 Subject: [PATCH 09/24] Correct documentation --- R/TimeDriver.R | 6 +++--- man/TimeDriver.Rd | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/R/TimeDriver.R b/R/TimeDriver.R index e0f8355..2a139ad 100644 --- a/R/TimeDriver.R +++ b/R/TimeDriver.R @@ -5,7 +5,7 @@ #' #' This class is intended for usage into [StorrTimeTravel]. #' -#' @returns A `TTDriver`, `R6` object. +#' @returns A `TimeDriver`, `R6` object. #' #' @export #' @@ -22,7 +22,7 @@ TimeDriver <- R6::R6Class( #' traits = NULL, - #' @description Instantiate a new `TTDriver` object. + #' @description Instantiate a new `TimeDriver` object. #' #' @param uri URI path for the `TimeBDriver` object. #' @param ctx Optional [tiledb::tiledb_ctx()] object. @@ -57,7 +57,7 @@ TimeDriver <- R6::R6Class( "tiledb" }, - #' @description Open `TTDriver` object for read or write. + #' @description Open `TimeDriver` object for read or write. #' #' Setting`instantiate` argument to `TRUE`, all members will be instantiated #' and cached on opening. They can be accessed via `members` active field, i.e., using diff --git a/man/TimeDriver.Rd b/man/TimeDriver.Rd index 927d7ae..971c344 100644 --- a/man/TimeDriver.Rd +++ b/man/TimeDriver.Rd @@ -4,7 +4,7 @@ \alias{TimeDriver} \title{Generate a \code{TimeDriver} Object} \value{ -A \code{TTDriver}, \code{R6} object. +A \code{TimeDriver}, \code{R6} object. } \description{ A \link{TileDBDriver} variant with read only class methods and @@ -88,7 +88,7 @@ the resource will be opened at. Effective in \code{"READ"} mode only.} \if{html}{\out{}} \if{latex}{\out{\hypertarget{method-TimeDriver-initialize}{}}} \subsection{\code{TimeDriver$new()}}{ - Instantiate a new \code{TTDriver} object. + Instantiate a new \code{TimeDriver} object. \subsection{Usage}{ \if{html}{\out{
}} \preformatted{TimeDriver$new(uri, ctx = NULL, timestamp = NULL)} @@ -132,7 +132,7 @@ or length 2 with start, end timestamps \if{html}{\out{}} \if{latex}{\out{\hypertarget{method-TimeDriver-open}{}}} \subsection{\code{TimeDriver$open()}}{ - Open \code{TTDriver} object for read or write. + Open \code{TimeDriver} object for read or write. Setting\code{instantiate} argument to \code{TRUE}, all members will be instantiated and cached on opening. They can be accessed via \code{members} active field, i.e., using From b6ffb8e4fd4132d6c84073dbb8091753e8addd28 Mon Sep 17 00:00:00 2001 From: Constantinos Giachalis Date: Tue, 19 May 2026 12:51:48 +0300 Subject: [PATCH 10/24] Change code-color inline with 'R6.tiledb' package --- _pkgdown.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_pkgdown.yml b/_pkgdown.yml index d73d795..378ab98 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -9,7 +9,7 @@ template: google: Roboto Slab primary: '#090D14' link-color: '#1C4BC4ED' - code-color: '#725c30' + code-color: '#5D4311' text-decoration-color: '#151B21' body-color: '#1B222B' home: From a3785b9626a518d9938da52ea610b01bd0ee18bc Mon Sep 17 00:00:00 2001 From: Constantinos Giachalis Date: Tue, 19 May 2026 15:54:23 +0300 Subject: [PATCH 11/24] `TimeDriver` -> `TimeTravelDriver` --- NAMESPACE | 2 +- R/StorrTimeTravel.R | 4 +- R/{TimeDriver.R => TimeTravelDriver.R} | 12 +- _pkgdown.yml | 2 +- man/StorrTimeTravel.Rd | 2 +- man/{TimeDriver.Rd => TimeTravelDriver.Rd} | 266 ++++++++++----------- 6 files changed, 144 insertions(+), 144 deletions(-) rename R/{TimeDriver.R => TimeTravelDriver.R} (98%) rename man/{TimeDriver.Rd => TimeTravelDriver.Rd} (64%) diff --git a/NAMESPACE b/NAMESPACE index 73b6605..eb1451d 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -5,7 +5,7 @@ export(StorrFragments) export(StorrTimeTravel) export(TileDBDriver) export(TileDBStorr) -export(TimeDriver) +export(TimeTravelDriver) export(driver_tiledb) export(driver_tiledb_create) export(get_allocation_size_preference) diff --git a/R/StorrTimeTravel.R b/R/StorrTimeTravel.R index 0784314..90a428a 100644 --- a/R/StorrTimeTravel.R +++ b/R/StorrTimeTravel.R @@ -28,12 +28,12 @@ StorrTimeTravel <- R6::R6Class( #' @description Initialise `StorrTimeTravel`. #' - #' @param driver A [TimeDriver] object. + #' @param driver A [TimeTravelDriver] object. #' @param default_namespace The default namespace. #' initialize = function(driver, default_namespace) { - if (!inherits(driver, "TimeDriver")) { + if (!inherits(driver, "TimeTravelDriver")) { stop("Not a valid Time-Travel 'driver'. Please use a 'TTDriver' object.", call. = FALSE) } diff --git a/R/TimeDriver.R b/R/TimeTravelDriver.R similarity index 98% rename from R/TimeDriver.R rename to R/TimeTravelDriver.R index 2a139ad..430d1d2 100644 --- a/R/TimeDriver.R +++ b/R/TimeTravelDriver.R @@ -1,20 +1,20 @@ -#' @title Generate a `TimeDriver` Object +#' @title Generate a `TimeTravelDriver` Object #' #' @description A [TileDBDriver] variant with read only class methods and #' time-travel support. #' #' This class is intended for usage into [StorrTimeTravel]. #' -#' @returns A `TimeDriver`, `R6` object. +#' @returns A `TimeTravelDriver`, `R6` object. #' #' @export #' #' @keywords internal #' -TimeDriver <- R6::R6Class( +TimeTravelDriver <- R6::R6Class( inherit = TileDBGroup, cloneable = FALSE, - classname = "TimeDriver", + classname = "TimeTravelDriver", public = list( @@ -22,7 +22,7 @@ TimeDriver <- R6::R6Class( #' traits = NULL, - #' @description Instantiate a new `TimeDriver` object. + #' @description Instantiate a new `TimeTravelDriver` object. #' #' @param uri URI path for the `TimeBDriver` object. #' @param ctx Optional [tiledb::tiledb_ctx()] object. @@ -57,7 +57,7 @@ TimeDriver <- R6::R6Class( "tiledb" }, - #' @description Open `TimeDriver` object for read or write. + #' @description Open `TimeTravelDriver` object for read or write. #' #' Setting`instantiate` argument to `TRUE`, all members will be instantiated #' and cached on opening. They can be accessed via `members` active field, i.e., using diff --git a/_pkgdown.yml b/_pkgdown.yml index 378ab98..59e9b6c 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -93,6 +93,6 @@ reference: - CAS - TileDBDriver - TileDBStorr - - TimeDriver + - TimeTravelDriver - StorrFragments - StorrTimeTravel diff --git a/man/StorrTimeTravel.Rd b/man/StorrTimeTravel.Rd index 0b6d73e..d19d65c 100644 --- a/man/StorrTimeTravel.Rd +++ b/man/StorrTimeTravel.Rd @@ -68,7 +68,7 @@ the resource will be opened at. Effective in \code{"READ"} mode only.} \subsection{Arguments}{ \if{html}{\out{
}} \describe{ - \item{\code{driver}}{A \link{TimeDriver} object.} + \item{\code{driver}}{A \link{TimeTravelDriver} object.} \item{\code{default_namespace}}{The default namespace.} } \if{html}{\out{
}} diff --git a/man/TimeDriver.Rd b/man/TimeTravelDriver.Rd similarity index 64% rename from man/TimeDriver.Rd rename to man/TimeTravelDriver.Rd index 971c344..4844511 100644 --- a/man/TimeDriver.Rd +++ b/man/TimeTravelDriver.Rd @@ -1,10 +1,10 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/TimeDriver.R -\name{TimeDriver} -\alias{TimeDriver} -\title{Generate a \code{TimeDriver} Object} +% Please edit documentation in R/TimeTravelDriver.R +\name{TimeTravelDriver} +\alias{TimeTravelDriver} +\title{Generate a \code{TimeTravelDriver} Object} \value{ -A \code{TimeDriver}, \code{R6} object. +A \code{TimeTravelDriver}, \code{R6} object. } \description{ A \link{TileDBDriver} variant with read only class methods and @@ -14,7 +14,7 @@ This class is intended for usage into \link{StorrTimeTravel}. } \keyword{internal} \section{Super classes}{ -\code{\link[R6.tiledb:TileDBObject]{R6.tiledb::TileDBObject}} -> \code{\link[R6.tiledb:TileDBGroup]{R6.tiledb::TileDBGroup}} -> \code{TimeDriver} +\code{\link[R6.tiledb:TileDBObject]{R6.tiledb::TileDBObject}} -> \code{\link[R6.tiledb:TileDBGroup]{R6.tiledb::TileDBGroup}} -> \code{TimeTravelDriver} } \section{Public fields}{ \if{html}{\out{
}} @@ -36,31 +36,31 @@ the resource will be opened at. Effective in \code{"READ"} mode only.} \section{Methods}{ \subsection{Public methods}{ \itemize{ - \item \href{#method-TimeDriver-initialize}{\code{TimeDriver$new()}} - \item \href{#method-TimeDriver-type}{\code{TimeDriver$type()}} - \item \href{#method-TimeDriver-open}{\code{TimeDriver$open()}} - \item \href{#method-TimeDriver-close}{\code{TimeDriver$close()}} - \item \href{#method-TimeDriver-filter_keys}{\code{TimeDriver$filter_keys()}} - \item \href{#method-TimeDriver-get_hash}{\code{TimeDriver$get_hash()}} - \item \href{#method-TimeDriver-mget_hash}{\code{TimeDriver$mget_hash()}} - \item \href{#method-TimeDriver-get_object}{\code{TimeDriver$get_object()}} - \item \href{#method-TimeDriver-mget_object}{\code{TimeDriver$mget_object()}} - \item \href{#method-TimeDriver-get_keymeta}{\code{TimeDriver$get_keymeta()}} - \item \href{#method-TimeDriver-mget_keymeta}{\code{TimeDriver$mget_keymeta()}} - \item \href{#method-TimeDriver-exists_hash}{\code{TimeDriver$exists_hash()}} - \item \href{#method-TimeDriver-exists_object}{\code{TimeDriver$exists_object()}} - \item \href{#method-TimeDriver-list_hashes}{\code{TimeDriver$list_hashes()}} - \item \href{#method-TimeDriver-list_namespaces}{\code{TimeDriver$list_namespaces()}} - \item \href{#method-TimeDriver-list_keys}{\code{TimeDriver$list_keys()}} - \item \href{#method-TimeDriver-list_unused_hashes}{\code{TimeDriver$list_unused_hashes()}} - \item \href{#method-TimeDriver-keys_with_expiration}{\code{TimeDriver$keys_with_expiration()}} - \item \href{#method-TimeDriver-keys_without_expiration}{\code{TimeDriver$keys_without_expiration()}} - \item \href{#method-TimeDriver-expired_keys}{\code{TimeDriver$expired_keys()}} - \item \href{#method-TimeDriver-unexpired_keys}{\code{TimeDriver$unexpired_keys()}} - \item \href{#method-TimeDriver-num_expired_keys}{\code{TimeDriver$num_expired_keys()}} - \item \href{#method-TimeDriver-num_unexpired_keys}{\code{TimeDriver$num_unexpired_keys()}} - \item \href{#method-TimeDriver-has_expired_keys}{\code{TimeDriver$has_expired_keys()}} - \item \href{#method-TimeDriver-has_unexpired_keys}{\code{TimeDriver$has_unexpired_keys()}} + \item \href{#method-TimeTravelDriver-initialize}{\code{TimeTravelDriver$new()}} + \item \href{#method-TimeTravelDriver-type}{\code{TimeTravelDriver$type()}} + \item \href{#method-TimeTravelDriver-open}{\code{TimeTravelDriver$open()}} + \item \href{#method-TimeTravelDriver-close}{\code{TimeTravelDriver$close()}} + \item \href{#method-TimeTravelDriver-filter_keys}{\code{TimeTravelDriver$filter_keys()}} + \item \href{#method-TimeTravelDriver-get_hash}{\code{TimeTravelDriver$get_hash()}} + \item \href{#method-TimeTravelDriver-mget_hash}{\code{TimeTravelDriver$mget_hash()}} + \item \href{#method-TimeTravelDriver-get_object}{\code{TimeTravelDriver$get_object()}} + \item \href{#method-TimeTravelDriver-mget_object}{\code{TimeTravelDriver$mget_object()}} + \item \href{#method-TimeTravelDriver-get_keymeta}{\code{TimeTravelDriver$get_keymeta()}} + \item \href{#method-TimeTravelDriver-mget_keymeta}{\code{TimeTravelDriver$mget_keymeta()}} + \item \href{#method-TimeTravelDriver-exists_hash}{\code{TimeTravelDriver$exists_hash()}} + \item \href{#method-TimeTravelDriver-exists_object}{\code{TimeTravelDriver$exists_object()}} + \item \href{#method-TimeTravelDriver-list_hashes}{\code{TimeTravelDriver$list_hashes()}} + \item \href{#method-TimeTravelDriver-list_namespaces}{\code{TimeTravelDriver$list_namespaces()}} + \item \href{#method-TimeTravelDriver-list_keys}{\code{TimeTravelDriver$list_keys()}} + \item \href{#method-TimeTravelDriver-list_unused_hashes}{\code{TimeTravelDriver$list_unused_hashes()}} + \item \href{#method-TimeTravelDriver-keys_with_expiration}{\code{TimeTravelDriver$keys_with_expiration()}} + \item \href{#method-TimeTravelDriver-keys_without_expiration}{\code{TimeTravelDriver$keys_without_expiration()}} + \item \href{#method-TimeTravelDriver-expired_keys}{\code{TimeTravelDriver$expired_keys()}} + \item \href{#method-TimeTravelDriver-unexpired_keys}{\code{TimeTravelDriver$unexpired_keys()}} + \item \href{#method-TimeTravelDriver-num_expired_keys}{\code{TimeTravelDriver$num_expired_keys()}} + \item \href{#method-TimeTravelDriver-num_unexpired_keys}{\code{TimeTravelDriver$num_unexpired_keys()}} + \item \href{#method-TimeTravelDriver-has_expired_keys}{\code{TimeTravelDriver$has_expired_keys()}} + \item \href{#method-TimeTravelDriver-has_unexpired_keys}{\code{TimeTravelDriver$has_unexpired_keys()}} } } \if{html}{\out{
Inherited methods @@ -85,13 +85,13 @@ the resource will be opened at. Effective in \code{"READ"} mode only.}
}} \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TimeDriver-initialize}{}}} -\subsection{\code{TimeDriver$new()}}{ - Instantiate a new \code{TimeDriver} object. +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-initialize}{}}} +\subsection{\code{TimeTravelDriver$new()}}{ + Instantiate a new \code{TimeTravelDriver} object. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TimeDriver$new(uri, ctx = NULL, timestamp = NULL)} + \preformatted{TimeTravelDriver$new(uri, ctx = NULL, timestamp = NULL)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -114,13 +114,13 @@ or length 2 with start, end timestamps } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TimeDriver-type}{}}} -\subsection{\code{TimeDriver$type()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-type}{}}} +\subsection{\code{TimeTravelDriver$type()}}{ Driver type. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TimeDriver$type()} + \preformatted{TimeTravelDriver$type()} \if{html}{\out{
}} } \subsection{Returns}{ @@ -129,17 +129,17 @@ or length 2 with start, end timestamps } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TimeDriver-open}{}}} -\subsection{\code{TimeDriver$open()}}{ - Open \code{TimeDriver} object for read or write. +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-open}{}}} +\subsection{\code{TimeTravelDriver$open()}}{ + Open \code{TimeTravelDriver} object for read or write. Setting\code{instantiate} argument to \code{TRUE}, all members will be instantiated and cached on opening. They can be accessed via \code{members} active field, i.e., using \verb{$object} element. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TimeDriver$open(mode = c("READ", "WRITE"), instantiate = FALSE)} + \preformatted{TimeTravelDriver$open(mode = c("READ", "WRITE"), instantiate = FALSE)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -157,16 +157,16 @@ Default is \code{FALSE}.} } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TimeDriver-close}{}}} -\subsection{\code{TimeDriver$close()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-close}{}}} +\subsection{\code{TimeTravelDriver$close()}}{ Close the group object. All instantiated group members will be closed if opened, and before closing the group object. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TimeDriver$close()} + \preformatted{TimeTravelDriver$close()} \if{html}{\out{
}} } \subsection{Returns}{ @@ -175,13 +175,13 @@ closing the group object. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TimeDriver-filter_keys}{}}} -\subsection{\code{TimeDriver$filter_keys()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-filter_keys}{}}} +\subsection{\code{TimeTravelDriver$filter_keys()}}{ Filter \code{tbl_keys} by key and namespace \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TimeDriver$filter_keys(key, namespace, attrnames = character())} + \preformatted{TimeTravelDriver$filter_keys(key, namespace, attrnames = character())} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -199,13 +199,13 @@ closing the group object. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TimeDriver-get_hash}{}}} -\subsection{\code{TimeDriver$get_hash()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-get_hash}{}}} +\subsection{\code{TimeTravelDriver$get_hash()}}{ Get hash values. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TimeDriver$get_hash(key, namespace)} + \preformatted{TimeTravelDriver$get_hash(key, namespace)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -222,13 +222,13 @@ closing the group object. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TimeDriver-mget_hash}{}}} -\subsection{\code{TimeDriver$mget_hash()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-mget_hash}{}}} +\subsection{\code{TimeTravelDriver$mget_hash()}}{ Get hash values. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TimeDriver$mget_hash(key, namespace)} + \preformatted{TimeTravelDriver$mget_hash(key, namespace)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -245,13 +245,13 @@ closing the group object. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TimeDriver-get_object}{}}} -\subsection{\code{TimeDriver$get_object()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-get_object}{}}} +\subsection{\code{TimeTravelDriver$get_object()}}{ Get R object given a hash. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TimeDriver$get_object(hash)} + \preformatted{TimeTravelDriver$get_object(hash)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -267,13 +267,13 @@ closing the group object. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TimeDriver-mget_object}{}}} -\subsection{\code{TimeDriver$mget_object()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-mget_object}{}}} +\subsection{\code{TimeTravelDriver$mget_object()}}{ Get a list R objects given a hash vector. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TimeDriver$mget_object(hash)} + \preformatted{TimeTravelDriver$mget_object(hash)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -289,13 +289,13 @@ closing the group object. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TimeDriver-get_keymeta}{}}} -\subsection{\code{TimeDriver$get_keymeta()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-get_keymeta}{}}} +\subsection{\code{TimeTravelDriver$get_keymeta()}}{ Get key-namespace metadata. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TimeDriver$get_keymeta(key, namespace)} + \preformatted{TimeTravelDriver$get_keymeta(key, namespace)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -313,13 +313,13 @@ and \verb{"notes".} } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TimeDriver-mget_keymeta}{}}} -\subsection{\code{TimeDriver$mget_keymeta()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-mget_keymeta}{}}} +\subsection{\code{TimeTravelDriver$mget_keymeta()}}{ Get multiple key-namespace metadata. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TimeDriver$mget_keymeta(key, namespace, nomatch = NULL)} + \preformatted{TimeTravelDriver$mget_keymeta(key, namespace, nomatch = NULL)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -338,13 +338,13 @@ pair. For not found pairs will return the nomatch value. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TimeDriver-exists_hash}{}}} -\subsection{\code{TimeDriver$exists_hash()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-exists_hash}{}}} +\subsection{\code{TimeTravelDriver$exists_hash()}}{ Check a key-namespace pair exists. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TimeDriver$exists_hash(key, namespace)} + \preformatted{TimeTravelDriver$exists_hash(key, namespace)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -361,13 +361,13 @@ pair. For not found pairs will return the nomatch value. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TimeDriver-exists_object}{}}} -\subsection{\code{TimeDriver$exists_object()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-exists_object}{}}} +\subsection{\code{TimeTravelDriver$exists_object()}}{ Check a serialised object exists. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TimeDriver$exists_object(hash)} + \preformatted{TimeTravelDriver$exists_object(hash)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -383,13 +383,13 @@ pair. For not found pairs will return the nomatch value. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TimeDriver-list_hashes}{}}} -\subsection{\code{TimeDriver$list_hashes()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-list_hashes}{}}} +\subsection{\code{TimeTravelDriver$list_hashes()}}{ List all hash values. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TimeDriver$list_hashes()} + \preformatted{TimeTravelDriver$list_hashes()} \if{html}{\out{
}} } \subsection{Returns}{ @@ -398,13 +398,13 @@ pair. For not found pairs will return the nomatch value. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TimeDriver-list_namespaces}{}}} -\subsection{\code{TimeDriver$list_namespaces()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-list_namespaces}{}}} +\subsection{\code{TimeTravelDriver$list_namespaces()}}{ List all namespace values. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TimeDriver$list_namespaces()} + \preformatted{TimeTravelDriver$list_namespaces()} \if{html}{\out{
}} } \subsection{Returns}{ @@ -413,13 +413,13 @@ pair. For not found pairs will return the nomatch value. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TimeDriver-list_keys}{}}} -\subsection{\code{TimeDriver$list_keys()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-list_keys}{}}} +\subsection{\code{TimeTravelDriver$list_keys()}}{ List keys given a namespace. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TimeDriver$list_keys(namespace)} + \preformatted{TimeTravelDriver$list_keys(namespace)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -435,13 +435,13 @@ pair. For not found pairs will return the nomatch value. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TimeDriver-list_unused_hashes}{}}} -\subsection{\code{TimeDriver$list_unused_hashes()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-list_unused_hashes}{}}} +\subsection{\code{TimeTravelDriver$list_unused_hashes()}}{ List unused hashes. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TimeDriver$list_unused_hashes()} + \preformatted{TimeTravelDriver$list_unused_hashes()} \if{html}{\out{
}} } \subsection{Returns}{ @@ -450,13 +450,13 @@ pair. For not found pairs will return the nomatch value. } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TimeDriver-keys_with_expiration}{}}} -\subsection{\code{TimeDriver$keys_with_expiration()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-keys_with_expiration}{}}} +\subsection{\code{TimeTravelDriver$keys_with_expiration()}}{ Get the key-namespace pairs with expiration timestamps. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TimeDriver$keys_with_expiration(namespace, datetimes = TRUE)} + \preformatted{TimeTravelDriver$keys_with_expiration(namespace, datetimes = TRUE)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -474,13 +474,13 @@ Default is \code{TRUE}.} } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TimeDriver-keys_without_expiration}{}}} -\subsection{\code{TimeDriver$keys_without_expiration()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-keys_without_expiration}{}}} +\subsection{\code{TimeTravelDriver$keys_without_expiration()}}{ Get the key-namespace pairs without expiration timestamps. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TimeDriver$keys_without_expiration(namespace, datetimes = TRUE)} + \preformatted{TimeTravelDriver$keys_without_expiration(namespace, datetimes = TRUE)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -498,13 +498,13 @@ Default is \code{TRUE}.} } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TimeDriver-expired_keys}{}}} -\subsection{\code{TimeDriver$expired_keys()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-expired_keys}{}}} +\subsection{\code{TimeTravelDriver$expired_keys()}}{ Get the expired key-namespace pairs. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TimeDriver$expired_keys(namespace, datetimes = TRUE)} + \preformatted{TimeTravelDriver$expired_keys(namespace, datetimes = TRUE)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -522,13 +522,13 @@ Default is \code{TRUE}.} } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TimeDriver-unexpired_keys}{}}} -\subsection{\code{TimeDriver$unexpired_keys()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-unexpired_keys}{}}} +\subsection{\code{TimeTravelDriver$unexpired_keys()}}{ Get the unexpired key-namespace pairs. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TimeDriver$unexpired_keys(namespace, datetimes = TRUE)} + \preformatted{TimeTravelDriver$unexpired_keys(namespace, datetimes = TRUE)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -546,13 +546,13 @@ Default is \code{TRUE}.} } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TimeDriver-num_expired_keys}{}}} -\subsection{\code{TimeDriver$num_expired_keys()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-num_expired_keys}{}}} +\subsection{\code{TimeTravelDriver$num_expired_keys()}}{ Get the number of expired key-namespace pairs. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TimeDriver$num_expired_keys(namespace)} + \preformatted{TimeTravelDriver$num_expired_keys(namespace)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -568,13 +568,13 @@ Default is \code{TRUE}.} } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TimeDriver-num_unexpired_keys}{}}} -\subsection{\code{TimeDriver$num_unexpired_keys()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-num_unexpired_keys}{}}} +\subsection{\code{TimeTravelDriver$num_unexpired_keys()}}{ Get the number of unexpired key-namespace pairs. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TimeDriver$num_unexpired_keys(namespace)} + \preformatted{TimeTravelDriver$num_unexpired_keys(namespace)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -590,13 +590,13 @@ Default is \code{TRUE}.} } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TimeDriver-has_expired_keys}{}}} -\subsection{\code{TimeDriver$has_expired_keys()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-has_expired_keys}{}}} +\subsection{\code{TimeTravelDriver$has_expired_keys()}}{ Check for expired key-namespace pairs. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TimeDriver$has_expired_keys(namespace)} + \preformatted{TimeTravelDriver$has_expired_keys(namespace)} \if{html}{\out{
}} } \subsection{Arguments}{ @@ -612,13 +612,13 @@ Default is \code{TRUE}.} } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TimeDriver-has_unexpired_keys}{}}} -\subsection{\code{TimeDriver$has_unexpired_keys()}}{ +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-has_unexpired_keys}{}}} +\subsection{\code{TimeTravelDriver$has_unexpired_keys()}}{ Check for unexpired key-namespace pairs. \subsection{Usage}{ \if{html}{\out{
}} - \preformatted{TimeDriver$has_unexpired_keys(namespace)} + \preformatted{TimeTravelDriver$has_unexpired_keys(namespace)} \if{html}{\out{
}} } \subsection{Arguments}{ From 0bcfd511643f90662b938a64cc6b21c6163ec324 Mon Sep 17 00:00:00 2001 From: Constantinos Giachalis Date: Wed, 20 May 2026 09:55:14 +0300 Subject: [PATCH 12/24] Unit tests for 'TimeTravelDriver' --- tests/testthat/test-TimeTravelDriver.R | 102 +++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 tests/testthat/test-TimeTravelDriver.R diff --git a/tests/testthat/test-TimeTravelDriver.R b/tests/testthat/test-TimeTravelDriver.R new file mode 100644 index 0000000..478e465 --- /dev/null +++ b/tests/testthat/test-TimeTravelDriver.R @@ -0,0 +1,102 @@ +test_that("'TimeTravelBDriver'", { + + uri <- file.path(withr::local_tempdir(), "test-driver") + expect_no_error(dr <- TimeTravelDriver$new(uri)) + + expect_r6_class(dr, "TimeTravelDriver") + expect_false(dr$exists()) + expect_equal(dr$mode, "CLOSED") + expect_equal(dr$type(), "tiledb") + + # public fields + expect_equal(dr$traits, list(accept = "string", + throw_missing = TRUE)) + # public fields are locked + expect_error(dr$traits <- "boo") + + # Nothing to retrieve - object does not exist + expect_error(dr$tiledb_timestamp) + expect_error(dr$members_instantiated) + +}) + +# NB: 'TimeTravelBDriver' is a subset (copy) of 'TileDBDriver'. Here, we're +# performing basic testing in order catch / isolate any issue early. +# Time-travel testing will be carried out with 'StorrTimeTravel' class. + +test_that("'get_hash'/'mget_hash'", { + uri <- file.path(withr::local_tempdir(), "test-storr") + sto <- storr_tiledb(uri, init = TRUE, default_namespace = "ns1") + sto$mset(c("a", "b"), c("a", "b")) + hashes <- sto$mget_hash(c("a", "b")) + + dr <- TimeTravelDriver$new(uri) + + expect_equal(dr$mget_hash(c("a", "b"), "ns1"), hashes) + expect_equal(dr$get_hash("a", "ns1"), hashes[1]) + + # exists_hash + expect_true(dr$exists_hash("a", "ns1")) + expect_equal(dr$exists_hash(c("a", "c"), "ns1"), c(TRUE, FALSE)) + + # listing methods + expect_equal(dr$list_hashes(), hashes) + expect_equal(dr$list_keys("ns1"), c("a", "b")) + expect_equal(dr$list_namespaces(), "ns1") + expect_equal(dr$list_unused_hashes(), character(0)) + +}) + +test_that("'get_object'/'mget_object'", { + uri <- file.path(withr::local_tempdir(), "test-storr") + sto <- storr_tiledb(uri, init = TRUE, default_namespace = "ns1") + sto$mset(c("a", "b"), c("a", "b")) + hashes <- sto$mget_hash(c("a", "b")) + + dr <- TimeTravelDriver$new(uri) + + expect_equal(dr$mget_object(hashes), list("a", "b")) + expect_equal(dr$mget_object(c(hashes, "no-hash")), list("a", "b", NULL)) + expect_equal(dr$get_object(hashes[1]), "a") + + # exists_object + expect_all_true(dr$exists_object(hashes)) + expect_equal(dr$exists_object(c(hashes, "no-hash")), c(TRUE, TRUE, FALSE)) + +}) + + +test_that("'get_keymeta'/'mget_keymeta' and friends", { + + uri <- file.path(withr::local_tempdir(), "test-storr") + sto <- storr_tiledb(uri, init = TRUE, default_namespace = "ns1") + sto$mset(c("a", "b"), c("a", "b"), + notes = c("notes-a", "notes-b"), + expires_at = c(as.POSIXct(NA), as.POSIXct("1990-01-01"))) + + dr <- TimeTravelDriver$new(uri) + + trg <- list(list(as.POSIXct(NA), "notes-a"), + list(as.POSIXct("1990-01-01"), "notes-b")) + expect_equal(dr$mget_keymeta(c("a", "b"), "ns1"), trg, ignore_attr = TRUE) + + trg <- list(list(as.POSIXct(NA), "notes-a"), + list(NULL)) + expect_equal(dr$mget_keymeta(c("a", "c"), "ns1"), trg, ignore_attr = TRUE) + + + expect_equal(dr$get_keymeta("a", "ns1"), trg[[1]], ignore_attr = TRUE) + + expect_equal(dr$keys_with_expiration("ns1")[][["key"]]$as_vector(), "b") + expect_equal(dr$keys_without_expiration("ns1")[][["key"]]$as_vector(), "a") + + expect_equal(dr$expired_keys("ns1")[][["key"]]$as_vector(), "b") + expect_equal(dr$unexpired_keys("ns1")[][["key"]]$as_vector(), character(0)) + + expect_equal(dr$num_expired_keys("ns1"), 1) + expect_equal(dr$num_unexpired_keys("ns1"), 0) + + expect_true(dr$has_expired_keys("ns1")) + expect_false(dr$has_unexpired_keys("ns1")) + +}) From 65501403931cd4189782f02fbf555b729701acda Mon Sep 17 00:00:00 2001 From: Constantinos Giachalis Date: Wed, 20 May 2026 15:51:00 +0300 Subject: [PATCH 13/24] Correct class name in `storr_timetravel()` --- R/storr_timetravel.R | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/R/storr_timetravel.R b/R/storr_timetravel.R index e142276..72bc565 100644 --- a/R/storr_timetravel.R +++ b/R/storr_timetravel.R @@ -54,12 +54,11 @@ #' #' storr_timetravel <- function(uri, - default_namespace = "objects", - context = NULL, - timestamp = NULL) { - + default_namespace = "objects", + context = NULL, + timestamp = NULL) { # check scalar namespace - dr <- TimeDriver$new(uri, ctx = context, timestamp = timestamp) + dr <- TimeTravelDriver$new(uri, ctx = context, timestamp = timestamp) StorrTimeTravel$new(dr, default_namespace = default_namespace) } From b18aaade8939f439a7e5eaab6fd43cede3080db8 Mon Sep 17 00:00:00 2001 From: Constantinos Giachalis Date: Wed, 20 May 2026 15:51:23 +0300 Subject: [PATCH 14/24] `StorrTimeTravel` unit tests --- tests/testthat/test-StorrTimeTravel.R | 189 ++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 tests/testthat/test-StorrTimeTravel.R diff --git a/tests/testthat/test-StorrTimeTravel.R b/tests/testthat/test-StorrTimeTravel.R new file mode 100644 index 0000000..9931a4d --- /dev/null +++ b/tests/testthat/test-StorrTimeTravel.R @@ -0,0 +1,189 @@ +test_that("'storr_timetravel()' and 'StorrTimeTravel'", { + + uri <- file.path(withr::local_tempdir(), "test-driver") + dr <- TimeTravelDriver$new(uri) + + # R6Class: object does not exist. + expect_error(StorrTimeTravel$new(dr, "ns1")) + + # Set up 'storr' + driver_tiledb_create(uri) + dr <- TimeTravelDriver$new(uri) + + # 'StorrTimeTravel' + expect_no_error(sto <- StorrTimeTravel$new(dr, "ns1")) + expect_r6_class(sto, "StorrTimeTravel") + + # 'storr_timetravel' wrapper + expect_no_error(sto <- storr_timetravel(uri)) + expect_r6_class(sto, "StorrTimeTravel") + + # Test active field 'timestamp' + expect_s3_class(sto$timestamp, "tiledb_timestamp") + + t1 <- Sys.time() + expect_no_error(sto$timestamp <- t1) + expect_equal(sto$timestamp$timestamp_end, t1, ignore_attr = TRUE) + + # Error: 'storr' didn't exist at 1970-01-01 + expect_error(sto$timestamp <- 0) + +}) + +test_that("'get'/'mget' with time-travel", { + + uri <- file.path(withr::local_tempdir(), "test-storr") + sto <- storr_tiledb(uri, init = TRUE, default_namespace = "ns1") + + t0 <- Sys.time() + sto$set("a", 1) + t1 <- Sys.time() + sto$set("a", 2) + sto$set("b", 3, namespace = "ns2") + t2 <- Sys.time() + + hashes <- sto$list_hashes() + + # Open at t0 --- + stott <- storr_timetravel(uri, timestamp = t0, default_namespace = "ns1") + + # Expect nothing at t0 + expect_error(stott$get("a"), class = "error", "key 'a' ('ns1') not found", fixed = TRUE) + expect_equal(stott$mget(c("a", "b")), structure(list(NULL, NULL), missing = 1:2)) + + expect_all_false(stott$exists(c("a", "b"))) + expect_equal(stott$list(), character()) + expect_equal(stott$list_hashes(), character()) + expect_equal(stott$list_namespaces(), character()) + + # Open at t1 + stott$timestamp <- t1 + expect_equal(stott$get("a"), 1) + expect_equal(stott$mget(c("a", "b")), structure(list(1, NULL), missing = 2L)) + + expect_equal(stott$exists(c("a", "b")), c(TRUE, FALSE)) + expect_equal(stott$list(), "a") + expect_equal(stott$list_hashes(), "38e42db36c4414f7bbc19d750f71a721") + expect_equal(stott$list_namespaces(), "ns1") + + # Open at t2 + stott$timestamp <- t2 + expect_equal(stott$get("a"), 2) + expect_equal(stott$mget(c("a", "b"), namespace = c("ns1", "ns2")), list(2, 3)) + + expect_all_true(stott$exists(c("a", "b"), namespace = c("ns1", "ns2"))) + expect_equal(stott$list("ns2"), "b") + expect_equal(stott$list_hashes(), hashes) + expect_equal(stott$list_namespaces(), c("ns1", "ns2")) + +}) + +test_that("'get_keymeta'/'mget_keymeta' and friends with time-travel", { + + uri <- file.path(withr::local_tempdir(), "test-storr") + sto <- storr_tiledb(uri, init = TRUE, default_namespace = "ns1") + + t0 <- Sys.time() + sto$set("a", 1, notes = "a1") + t1 <- Sys.time() + sto$set_keymeta("a", notes = "a2", expires_at = as.POSIXct(t1)) + sto$set("b", 3, namespace = "ns2", notes = "b3") + t2 <- Sys.time() + + hashes <- sto$list_hashes() + + # Open at t0 --- + stott <- storr_timetravel(uri, timestamp = t0, default_namespace = "ns1") + + # Expect nothing at t0 + expect_error(stott$get_keymeta("a"), class = "error", "key 'a' ('ns1') not found", fixed = TRUE) + expect_equal(stott$mget_keymeta(c("a", "b")), structure(list(list(NULL), list(NULL)), missing = 1:2)) + + expect_all_false(stott$exists(c("a", "b"), namespace = c("ns1", "ns2"))) + + df_trg <- structure(list(namespace = character(0), key = character(0), + expires_at = structure(numeric(0), class = c("POSIXct", "POSIXt" + ))), row.names = integer(0), class = c("data.table", "data.frame" + )) + expect_equal(stott$keys_with_expiration(), df_trg) + expect_equal(stott$expired_keys(), df_trg) + expect_false(stott$has_expired_keys()) + + # Open at t1 + stott$timestamp <- t1 + expect_equal(stott$get_keymeta("a"), list(expires_at = as.POSIXct(NA), notes = "a1")) + expect_equal(stott$mget_keymeta(c("a", "b")), structure(list( + list( + expires_at = structure( + NA_real_, + class = c("POSIXct", "POSIXt"), + tzone = "" + ), + notes = "a1" + ), list(NULL) + ), missing = 2L)) + + expect_equal(stott$exists(c("a", "b"), namespace = c("ns1", "ns2")), c(TRUE, FALSE)) + + expect_equal(stott$keys_with_expiration(), df_trg) + expect_equal(stott$expired_keys(), df_trg) + expect_false(stott$has_expired_keys()) + + + # Open at t2 + stott$timestamp <- t2 + expect_equal(stott$get_keymeta("a"), list(expires_at = as.POSIXct(t1), notes = "a2")) + expect_equal(stott$get_keymeta("b", namespace = "ns2"), list(expires_at = as.POSIXct(NA), notes = "b3")) + expect_equal(stott$mget_keymeta(c("a", "b"), namespace = c("ns1", "ns2")), list(list(expires_at = as.POSIXct(t1), notes = "a2"), + list(expires_at = as.POSIXct(NA), notes = "b3")), ignore_attr = TRUE) + + expect_all_true(stott$exists(c("a", "b"), namespace = c("ns1", "ns2"))) + + df <- data.frame(namespace = "ns1", key = "a", expires_at = t1) + df_trg <- data.table::as.data.table(df) + + expect_equal(stott$keys_with_expiration(), df_trg) + expect_equal(stott$expired_keys(), df_trg) + expect_true(stott$has_expired_keys()) +}) + +test_that("'index_export' with time-travel", { + + uri <- file.path(withr::local_tempdir(), "test-storr") + sto <- storr_tiledb(uri, init = TRUE, default_namespace = "ns1") + + t0 <- Sys.time() + sto$set("a", 1) + t1 <- Sys.time() + sto$set("a", 2) + sto$set("b", 3, namespace = "ns2") + t2 <- Sys.time() + + hashes <- sto$list_hashes() + + # Open at t0 --- + stott <- storr_timetravel(uri, timestamp = t0, default_namespace = "ns1") + + df_trg <- structure(list(namespace = character(0), + key = character(0), + hash = character(0), + expires_at = structure(numeric(0), class = c("POSIXct", "POSIXt" + )), + notes = character(0)), row.names = integer(0), class = c("data.table", "data.frame" + )) + # Expect nothing at t0 + expect_equal(stott$index_export(), df_trg, ignore_attr = TRUE) + + # Open at t1 + stott$timestamp <- t1 + expect_equal(nrow(res1 <- stott$index_export()), 1) + expect_equal(res1$hash, "38e42db36c4414f7bbc19d750f71a721") + + # Open at t2 + stott$timestamp <- t2 + expect_equal(nrow(res1 <- stott$index_export()), 2) + expect_equal(res1$hash, c("87494137ffd66807c0c5c877856799cc", "02c87a685a6264c39c65c94a51de14b8" + )) + expect_equal(res1$key, c("a", "b")) + +}) From 3f708939eb900943aa50fa8743a459ce23c20cfd Mon Sep 17 00:00:00 2001 From: Constantinos Giachalis Date: Wed, 20 May 2026 15:53:54 +0300 Subject: [PATCH 15/24] Minor code, misc improvements --- R/TileDBDriver.R | 2 +- R/TileDBStorr.R | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/R/TileDBDriver.R b/R/TileDBDriver.R index 2f11c46..211f838 100644 --- a/R/TileDBDriver.R +++ b/R/TileDBDriver.R @@ -1107,7 +1107,7 @@ TileDBDriver <- R6::R6Class( # Copy keys to destination storr # NB: We can not do it with arrow because of: # https://github.com/TileDB-Inc/TileDB-R/issues/847 - arr <- dest_driver$get_member("tbl_keys")$tiledb_array() + arr <- dest_driver$get_member("tbl_keys")$tiledb_array() arr[] <- idx } else { # Diff hash algos diff --git a/R/TileDBStorr.R b/R/TileDBStorr.R index c42c137..1cb4545 100644 --- a/R/TileDBStorr.R +++ b/R/TileDBStorr.R @@ -941,7 +941,8 @@ TileDBStorr <- R6::R6Class( get = function(key, namespace = self$default_namespace, use_cache = getOption("storr.tiledb.cache", TRUE)) { private$check_input(key, n = 1, type = "character") private$check_input(namespace, n = 1, type = "character") - self$get_value(self$get_hash(key, namespace), use_cache) + hash <- self$get_hash(key, namespace) + self$get_value(hash, use_cache) }, @@ -960,7 +961,8 @@ TileDBStorr <- R6::R6Class( missing = NULL) { # NB: storr::join_key_namespace check is performed inside $query_keys0 - self$mget_value(self$mget_hash(key, namespace), use_cache, missing) + hash <- self$mget_hash(key, namespace) + self$mget_value(hash, use_cache, missing) }, #' @description Get hash value. @@ -977,8 +979,9 @@ TileDBStorr <- R6::R6Class( private$check_input(namespace, n = 1, type = "character") if (self$traits$throw_missing) { - tryCatch(private$DRIVER$get_hash(key, namespace), error = function(e) stop(KeyError(key, - namespace))) + tryCatch(private$DRIVER$get_hash(key, namespace), error = function(e) { + stop(KeyError(key, namespace)) + }) } else { if (self$exists(key, namespace)) { From b08566d08705be684f50bb6e0d1f0e74ead74f15 Mon Sep 17 00:00:00 2001 From: Constantinos Giachalis Date: Thu, 21 May 2026 09:41:23 +0300 Subject: [PATCH 16/24] Expose `export_tdb()` --- R/StorrTimeTravel.R | 20 +++++ R/TimeTravelDriver.R | 157 ++++++++++++++++++++++++++++++++++++++++ man/StorrTimeTravel.Rd | 28 +++++++ man/TimeTravelDriver.Rd | 27 +++++++ 4 files changed, 232 insertions(+) diff --git a/R/StorrTimeTravel.R b/R/StorrTimeTravel.R index 90a428a..79b8ac4 100644 --- a/R/StorrTimeTravel.R +++ b/R/StorrTimeTravel.R @@ -409,6 +409,26 @@ StorrTimeTravel <- R6::R6Class( } out + }, + + #' @description Export objects from storr to another TileDB storr. + #' + #' @param key A character vector of source keys. + #' @param namespace `r sto_namespaces_or_null` + #' @param uri_dest The URI path of destination storr. + #' @param context_dest Optional \link[tiledb:tiledb_ctx]{tiledb_ctx} object + #' for destination storr. + #' + #' @return A logical `TRUE` indicating successful export, invisibly. + #' + export_tdb = function(key = character(0), + namespace = self$default_namespace, + uri_dest, + context_dest = NULL) { + + dest_driver <- driver_tiledb(uri_dest, context = context_dest) + + private$DRIVER$export_tdb(key, namespace = namespace, dest_driver = dest_driver) } ), diff --git a/R/TimeTravelDriver.R b/R/TimeTravelDriver.R index 430d1d2..c8dcba7 100644 --- a/R/TimeTravelDriver.R +++ b/R/TimeTravelDriver.R @@ -81,6 +81,17 @@ TimeTravelDriver <- R6::R6Class( } + algo <- self$get_metadata("hash_algo") + + # Case where 'hash_algo' key is not present + # + if (is.null(algo)) { + + stop("Hash algorithm not found, defaulting to 'md5'") + } + + private$.hash_algo <- algo + if (instantiate) { private$instantiate_members() private$.members_instantiated <- TRUE @@ -755,6 +766,135 @@ TimeTravelDriver <- R6::R6Class( arr <- self$unexpired_keys(namespace, datetimes = FALSE) arr[]$num_rows != 0 + }, + + #' @description Export objects from storr to another TileDB storr. + #' + #' @param key A character vector of source keys. + #' @param namespace `r sto_namespaces_or_null` + #' @param dest_driver The destination TileDB driver, See [driver_tiledb()]. + #' + #' @return A logical `TRUE` indicating successful export, invisibly. + #' + export_tdb = function(key, + namespace, + dest_driver) { + + + if (self$uri == dest_driver$uri) { + cli::cli_abort("Destination URI can not be the same as source.", + call = NULL) + } + + # Two cases: + # 1. Storrs with identical hash algorithms + # 2. Storrs with different hash algorithms + + # Get index data.frame (tbl_keys) + idx <- self$filter_keys(key, namespace = namespace)[] + + if (nrow(idx) == 0) { + cli::cli_warn("Nothing to export for the selected key-namespace.") + return(invisible(NULL)) + } + + hashes <- unique(idx$hash) + + if (self$hash_algorithm == dest_driver$hash_algorithm) { + + # Check hashes exists in destination + exist_hash_in_dest <- dest_driver$exists_object(hashes) + + # Hashes to be copied over to destination + new_hash <- hashes[!exist_hash_in_dest] + + # Export new data only + if (length(new_hash) != 0) { + + # Get data from source + arrobj <- private$data_array() + sp <- list(hash = new_hash) + # arr_data_src <- arrobj$tiledb_array(selected_points = sp, return_as = "arrow") + arr_data_src <- arrobj$object + tiledb::selected_points(arr_data_src) <- sp + tiledb::return_as(arr_data_src) <- "arrow" + + # Copy data to destination storr + arr_data_dest <- dest_driver$get_member("tbl_data")$tiledb_array() + arr_data_dest[] <- arr_data_src[] + + # TODO: Use arrow the arrow buffer is fixed + # qry <- tiledb::tiledb_query(arr_data_dest, "WRITE") + # + # naHash <- nanoarrow::as_nanoarrow_array(arr_data_src[][["hash"]]) + # naValue <- nanoarrow::as_nanoarrow_array(arr_data_src[][["value"]]) + # + # qry <- tiledb::tiledb_query_import_buffer(qry, "hash", naHash, ctx = dest_driver$ctx) + # qry <- tiledb::tiledb_query_import_buffer(qry, "value", naValue, ctx = dest_driver$ctx) + # + # tiledb::tiledb_query_set_layout(qry, "UNORDERED") + # tiledb::tiledb_query_submit(qry) + # tiledb::tiledb_query_finalize(qry) + + } + + # Copy keys to destination storr + # NB: We can not do it with arrow because of: + # https://github.com/TileDB-Inc/TileDB-R/issues/847 + arr <- dest_driver$get_member("tbl_keys")$tiledb_array() + arr[] <- idx + + } else { # Diff hash algos + + # Fetch objects, re-hash, check exist in dest and then + # save them in dest + + # Inline helpers + .traits <- storr_traits(dest_driver$traits) + .hash_raw <- make_hash_serialized_object(dest_driver$hash_algorithm, !.traits$drop_r_version) + + # Get data from source + arrobj <- private$data_array() + sp <- list(hash = hashes) + # arr_data_src <- arrobj$tiledb_array(selected_points = sp, return_as = "arrow") + arr_data_src <- arrobj$object + tiledb::selected_points(arr_data_src) <- sp + tiledb::return_as(arr_data_src) <- "arrow" + + dta <- data.table::as.data.table(arr_data_src[], key = "hash") + + # Get them in order we requested + dta <- dta[.(hash), env = list(hash = I(hashes))] + + # Re-hash serialised objects + dta[, `:=` (new_hashes = vcapply(value, .hash_raw))] + + # out <<- dta + # print(dta[, "new_hashes"]) + + # Find hashes to send over + upload <- !dest_driver$exists_object(dta$new_hashes) + + # Copy data to destination storr + if (any(upload)) { + arr_data_dest <- dest_driver$get_member("tbl_data")$tiledb_array() + rehashed_objects <- data.frame(hash = dta$new_hashes[upload], value = dta$value[upload]) + arr_data_dest[] <- rehashed_objects + } + + # Replace index with new hashes and copy + new_hashes <- dta$new_hashes + names(new_hashes) <- dta$hash + idx$hash <- new_hashes[idx$hash] # map to new hashes + + # Copy keys to destination storr + # NB: We can not do it with arrow because of: + # https://github.com/TileDB-Inc/TileDB-R/issues/847 + arr <- dest_driver$get_member("tbl_keys")$tiledb_array() + arr[] <- idx + } + + invisible(TRUE) } ), @@ -777,6 +917,19 @@ TimeTravelDriver <- R6::R6Class( }, + #' @field hash_algorithm Hash algorithm + #' + hash_algorithm = function(value) { + + private$check_object_exists() + + if (!missing(value)) { + private$check_read_only("hash_algorithm") + } + + private$.hash_algo + }, + #' @field members_instantiated Have the members been instantiated? #' members_instantiated = function(value) { @@ -802,6 +955,10 @@ TimeTravelDriver <- R6::R6Class( # .members_instantiated = NULL, + # @field Hash algorithm to be used + # + .hash_algo = NULL, + # @description Instantiate group members. # instantiate_members = function() { diff --git a/man/StorrTimeTravel.Rd b/man/StorrTimeTravel.Rd index d19d65c..0ef1e53 100644 --- a/man/StorrTimeTravel.Rd +++ b/man/StorrTimeTravel.Rd @@ -53,6 +53,7 @@ the resource will be opened at. Effective in \code{"READ"} mode only.} \item \href{#method-StorrTimeTravel-list_namespaces}{\code{StorrTimeTravel$list_namespaces()}} \item \href{#method-StorrTimeTravel-export}{\code{StorrTimeTravel$export()}} \item \href{#method-StorrTimeTravel-index_export}{\code{StorrTimeTravel$index_export()}} + \item \href{#method-StorrTimeTravel-export_tdb}{\code{StorrTimeTravel$export_tdb()}} } } \if{html}{\out{
}} @@ -501,4 +502,31 @@ present in a storr. } } +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-StorrTimeTravel-export_tdb}{}}} +\subsection{\code{StorrTimeTravel$export_tdb()}}{ + Export objects from storr to another TileDB storr. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{StorrTimeTravel$export_tdb(key = character(0), + namespace = self$default_namespace, uri_dest, context_dest = NULL)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{key}}{A character vector of source keys.} + \item{\code{namespace}}{A character vector of namespaces or \code{NULL} for all namespaces.} + \item{\code{uri_dest}}{The URI path of destination storr.} + \item{\code{context_dest}}{Optional \link[tiledb:tiledb_ctx]{tiledb_ctx} object +for destination storr.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + A logical \code{TRUE} indicating successful export, invisibly. + } +} + } diff --git a/man/TimeTravelDriver.Rd b/man/TimeTravelDriver.Rd index 4844511..e7f69b1 100644 --- a/man/TimeTravelDriver.Rd +++ b/man/TimeTravelDriver.Rd @@ -29,6 +29,8 @@ This class is intended for usage into \link{StorrTimeTravel}. \item{\code{timestamp}}{Set or retrieve a \code{TileDB} timestamp range that the resource will be opened at. Effective in \code{"READ"} mode only.} + \item{\code{hash_algorithm}}{Hash algorithm} + \item{\code{members_instantiated}}{Have the members been instantiated?} } \if{html}{\out{
}} @@ -61,6 +63,7 @@ the resource will be opened at. Effective in \code{"READ"} mode only.} \item \href{#method-TimeTravelDriver-num_unexpired_keys}{\code{TimeTravelDriver$num_unexpired_keys()}} \item \href{#method-TimeTravelDriver-has_expired_keys}{\code{TimeTravelDriver$has_expired_keys()}} \item \href{#method-TimeTravelDriver-has_unexpired_keys}{\code{TimeTravelDriver$has_unexpired_keys()}} + \item \href{#method-TimeTravelDriver-export_tdb}{\code{TimeTravelDriver$export_tdb()}} } } \if{html}{\out{
Inherited methods @@ -633,4 +636,28 @@ Default is \code{TRUE}.} } } +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TimeTravelDriver-export_tdb}{}}} +\subsection{\code{TimeTravelDriver$export_tdb()}}{ + Export objects from storr to another TileDB storr. + \subsection{Usage}{ + \if{html}{\out{
}} + \preformatted{TimeTravelDriver$export_tdb(key, namespace, dest_driver)} + \if{html}{\out{
}} + } + \subsection{Arguments}{ + \if{html}{\out{
}} + \describe{ + \item{\code{key}}{A character vector of source keys.} + \item{\code{namespace}}{A character vector of namespaces or \code{NULL} for all namespaces.} + \item{\code{dest_driver}}{The destination TileDB driver, See \code{\link[=driver_tiledb]{driver_tiledb()}}.} + } + \if{html}{\out{
}} + } + \subsection{Returns}{ + A logical \code{TRUE} indicating successful export, invisibly. + } +} + } From 4c9e35bc5dda9a5dab587f64c5cbd41fbb666f23 Mon Sep 17 00:00:00 2001 From: Constantinos Giachalis Date: Thu, 21 May 2026 09:57:55 +0300 Subject: [PATCH 17/24] Fix documentation --- R/TileDBStorr.R | 2 +- man/TileDBStorr.Rd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/R/TileDBStorr.R b/R/TileDBStorr.R index 1cb4545..e3c72fb 100644 --- a/R/TileDBStorr.R +++ b/R/TileDBStorr.R @@ -1932,7 +1932,7 @@ TileDBStorr <- R6::R6Class( #' Use list() to export to a brand new list, or use as.list(object) for a shorthand. #' #' @param dest A destination to export objects to. It can be a storr, list, or environment. - #' @param list Names of objects to import (or `NULL` for all objects) . If given it must be a character vector. + #' @param list Names of objects to export (or `NULL` for all objects) . If given it must be a character vector. #' If named, the names of the character vector will be the names of the objects as created in the storr. #' @param namespace Namespace to get objects from, and to put objects into. If `NULL`, #' then this will export namespaces from this (source) storr into the destination; diff --git a/man/TileDBStorr.Rd b/man/TileDBStorr.Rd index 337ec23..ce297a8 100644 --- a/man/TileDBStorr.Rd +++ b/man/TileDBStorr.Rd @@ -1317,7 +1317,7 @@ Use list() to export to a brand new list, or use as.list(object) for a shorthand \if{html}{\out{
}} \describe{ \item{\code{dest}}{A destination to export objects to. It can be a storr, list, or environment.} - \item{\code{list}}{Names of objects to import (or \code{NULL} for all objects) . If given it must be a character vector. + \item{\code{list}}{Names of objects to export (or \code{NULL} for all objects) . If given it must be a character vector. If named, the names of the character vector will be the names of the objects as created in the storr.} \item{\code{namespace}}{Namespace to get objects from, and to put objects into. If \code{NULL}, then this will export namespaces from this (source) storr into the destination; From b1476905fee22c4b36a60f591b6f653a2e3b5181 Mon Sep 17 00:00:00 2001 From: Constantinos Giachalis Date: Thu, 21 May 2026 10:20:51 +0300 Subject: [PATCH 18/24] Unit tests for `export()` and `export_tdb()` --- tests/testthat/test-StorrTimeTravel.R | 75 +++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/tests/testthat/test-StorrTimeTravel.R b/tests/testthat/test-StorrTimeTravel.R index 9931a4d..4b55f19 100644 --- a/tests/testthat/test-StorrTimeTravel.R +++ b/tests/testthat/test-StorrTimeTravel.R @@ -187,3 +187,78 @@ test_that("'index_export' with time-travel", { expect_equal(res1$key, c("a", "b")) }) + + +test_that("'export' with time-travel", { + + uri <- file.path(withr::local_tempdir(), "test-storr") + sto <- storr_tiledb(uri, init = TRUE, default_namespace = "ns1") + + t0 <- Sys.time() + sto$set("a", 1) + t1 <- Sys.time() + sto$set("a", 2) + sto$set("b", 3, namespace = "ns2") + t2 <- Sys.time() + + # Open at t0 --- + stott <- storr_timetravel(uri, timestamp = t0, default_namespace = "ns1") + + # Expect nothing at t0 + expect_no_error(dest_t0 <- stott$export(list())) + expect_error(dest_t0$get("a"), class = "error", "key 'a' ('ns1') not found", fixed = TRUE) + expect_equal(dest_t0$list(namespace = "ns1"), character(0)) + + # Open at t1 + stott$timestamp <- t1 + expect_no_error(dest_t1 <- stott$export(list())) + expect_equal(dest_t1$get("a"), 1) + expect_equal(dest_t1$list(namespace = "ns1"), "a") + + # Open at t2 + stott$timestamp <- t2 + expect_no_error(dest_t2 <- stott$export(list())) + expect_equal(dest_t2$mget(c("a", "b"), namespace = c("ns1", "ns2")), list(2, 3)) + expect_equal(dest_t2$list_namespaces(), c("ns1", "ns2")) + +}) + + +test_that("'export_tdb' with time-travel", { + + uri <- file.path(withr::local_tempdir(), "test-storr") + sto <- storr_tiledb(uri, init = TRUE, default_namespace = "ns1") + + uri2 <- file.path(withr::local_tempdir(), "test-storr2") + sto2 <- storr_tiledb(uri2, init = TRUE, default_namespace = "ns1") + + t0 <- Sys.time() + sto$set("a", 1) + t1 <- Sys.time() + sto$set("a", 2) + sto$set("b", 3, namespace = "ns2") + t2 <- Sys.time() + + # Open at t0 --- + stott <- storr_timetravel(uri, timestamp = t0, default_namespace = "ns1") + + # Expect nothing at t0 + expect_warning(stott$export_tdb(uri_dest = uri2), class = "warning", + "Nothing to export for the selected key-namespace.") + + + # Open at t1 + stott$timestamp <- t1 + expect_no_error(stott$export_tdb(uri_dest = uri2)) + expect_equal(sto2$get("a"), 1) + expect_equal(sto2$list(namespace = "ns1"), "a") + + # Open at t2 + stott$timestamp <- t2 + expect_no_error(stott$export_tdb(uri_dest = uri2, namespace = NULL)) # all namespaces + expect_equal(sto2$get("a"), 2) + expect_equal(sto2$mget(c("a", "b"), namespace = c("ns1", "ns2")), list(2, 3)) + expect_equal(sto2$list_namespaces(), c("ns1", "ns2")) + +}) + From f0b2ae20ce40eb457dd4d524bdc752a6b03fea66 Mon Sep 17 00:00:00 2001 From: Constantinos Giachalis Date: Thu, 21 May 2026 10:55:20 +0300 Subject: [PATCH 19/24] Update documentation --- R/StorrTimeTravel.R | 5 +-- R/storr_timetravel.R | 60 ++++++++++++++++++++++++++++++++++- man/StorrTimeTravel.Rd | 5 +-- man/storr_timetravel.Rd | 69 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 133 insertions(+), 6 deletions(-) diff --git a/R/StorrTimeTravel.R b/R/StorrTimeTravel.R index 79b8ac4..959e366 100644 --- a/R/StorrTimeTravel.R +++ b/R/StorrTimeTravel.R @@ -1,7 +1,8 @@ #' @title Generate a `StorrTimeTravel` Object #' -#' @description A [TileDBStorr] variant with read only class methods and -#' time-travel support. +#' @description A [TileDBStorr] is a time-travel variant of `TileDBStorr` designed +#' to query data at specific points in time and in read-only mode with no write +#' capabilities. #' #' This class is not intended to be used directly and the preferred #' usage is through [storr_timetravel()]. diff --git a/R/storr_timetravel.R b/R/storr_timetravel.R index 72bc565..d21cba4 100644 --- a/R/storr_timetravel.R +++ b/R/storr_timetravel.R @@ -1,6 +1,64 @@ #' A Storr with Time-Travel #' -#' A `'storr'` variant with read-only class methods and time-travel support. +#' Generate an instance of [StorrTimeTravel], a variant of [TileDBStorr] designed +#' to query key-value data at specific points in time and in read-only mode with +#' no write capabilities. +#' +#' # Class Methods Summary +#' +#' For complete definitions, see **Methods** section in [StorrTimeTravel]. +#' +#' **Active Fields** +#' +#' - **`timestamp`** - Get or set a TileDB timestamp range that the 'storr' will be opened at. +#' +#' **Initialisation & Lifecycle** +#' +#' - **`new()`** - Initialise a StorrTimeTravel object with a TileDB driver, default namespace, and optional timestamp +#' +#' +#' **Single Key-Value Operations** +#' +#' - **`get()`** - Retrieve an object by key-namespace pair +#' - **`get_value()`** - Retrieve an object given its hash +#' +#' **Multiple Key-Value Operations** +#' +#' - **`mget()`** - Get multiple objects by keys +#' - **`mget_value()`** - Get multiple objects by their hashes +#' +#' **Metadata Operations** +#' +#' - **`get_keymeta()`** - Retrieve metadata for a key +#' - **`mget_keymeta()`** - Retrieve metadata for multiple keys +#' +#' **Object Hash Management** +#' +#' - **`get_hash()`** - Get hash value for a key-namespace pair +#' - **`mget_hash()`** - Get hash values for multiple keys +#' +#' **Key Management** +#' +#' - **`exists()`** - Check if key-namespace pair(s) exist +#' - **`exists_object()`** - Check if object(s) with given hash(es) exist +#' +#' **Expiration Management** +#' +#' - **`keys_with_expiration()`** - List keys that have expiration timestamps +#' - **`expired_keys()`** - Get keys that have already expired +#' - **`has_expired_keys()`** - Check if any keys are expired +#' +#' **Listing** +#' +#' - **`list()`** - List all keys in a namespace +#' - **`list_hashes()`** - List all stored object hashes +#' - **`list_namespaces()`** - List all namespaces +#' +#' **Storage Management** +#' +#' - **`index_export()`** - Export object index as data.table +#' - **`export()`** - Export objects to another storr/list/environment +#' - **`export_tdb()`** - Export objects to another TileDB storr #' #' @inheritParams driver_tiledb #' @param default_namespace The default namespace: `"objects"`. diff --git a/man/StorrTimeTravel.Rd b/man/StorrTimeTravel.Rd index 0ef1e53..f5bda4b 100644 --- a/man/StorrTimeTravel.Rd +++ b/man/StorrTimeTravel.Rd @@ -7,8 +7,9 @@ A \code{StorrTimeTravel}, \code{R6} object. } \description{ -A \link{TileDBStorr} variant with read only class methods and -time-travel support. +A \link{TileDBStorr} is a time-travel variant of \code{TileDBStorr} designed +to query data at specific points in time and in read-only mode with no write +capabilities. This class is not intended to be used directly and the preferred usage is through \code{\link[=storr_timetravel]{storr_timetravel()}}. diff --git a/man/storr_timetravel.Rd b/man/storr_timetravel.Rd index f380b38..601c7e8 100644 --- a/man/storr_timetravel.Rd +++ b/man/storr_timetravel.Rd @@ -30,8 +30,75 @@ Set a new timestamp with active field \verb{$timestamp}, see examples.} An object of class \link{StorrTimeTravel}, R6. } \description{ -A \code{'storr'} variant with read-only class methods and time-travel support. +Generate an instance of \link{StorrTimeTravel}, a variant of \link{TileDBStorr} designed +to query key-value data at specific points in time and in read-only mode with +no write capabilities. } +\section{Class Methods Summary}{ +For complete definitions, see \strong{Methods} section in \link{StorrTimeTravel}. + +\strong{Active Fields} +\itemize{ +\item \strong{\code{timestamp}} - Get or set a TileDB timestamp range that the 'storr' will be opened at. +} + +\strong{Initialisation & Lifecycle} +\itemize{ +\item \strong{\code{new()}} - Initialise a StorrTimeTravel object with a TileDB driver, default namespace, and optional timestamp +} + +\strong{Single Key-Value Operations} +\itemize{ +\item \strong{\code{get()}} - Retrieve an object by key-namespace pair +\item \strong{\code{get_value()}} - Retrieve an object given its hash +} + +\strong{Multiple Key-Value Operations} +\itemize{ +\item \strong{\code{mget()}} - Get multiple objects by keys +\item \strong{\code{mget_value()}} - Get multiple objects by their hashes +} + +\strong{Metadata Operations} +\itemize{ +\item \strong{\code{get_keymeta()}} - Retrieve metadata for a key +\item \strong{\code{mget_keymeta()}} - Retrieve metadata for multiple keys +} + +\strong{Object Hash Management} +\itemize{ +\item \strong{\code{get_hash()}} - Get hash value for a key-namespace pair +\item \strong{\code{mget_hash()}} - Get hash values for multiple keys +} + +\strong{Key Management} +\itemize{ +\item \strong{\code{exists()}} - Check if key-namespace pair(s) exist +\item \strong{\code{exists_object()}} - Check if object(s) with given hash(es) exist +} + +\strong{Expiration Management} +\itemize{ +\item \strong{\code{keys_with_expiration()}} - List keys that have expiration timestamps +\item \strong{\code{expired_keys()}} - Get keys that have already expired +\item \strong{\code{has_expired_keys()}} - Check if any keys are expired +} + +\strong{Listing} +\itemize{ +\item \strong{\code{list()}} - List all keys in a namespace +\item \strong{\code{list_hashes()}} - List all stored object hashes +\item \strong{\code{list_namespaces()}} - List all namespaces +} + +\strong{Storage Management} +\itemize{ +\item \strong{\code{index_export()}} - Export object index as data.table +\item \strong{\code{export()}} - Export objects to another storr/list/environment +\item \strong{\code{export_tdb()}} - Export objects to another TileDB storr +} +} + \examples{ \dontrun{ # URI path From 99b7ae8c2ee5809b1416105917d78ab81f4cbad3 Mon Sep 17 00:00:00 2001 From: Constantinos Giachalis Date: Thu, 21 May 2026 10:55:53 +0300 Subject: [PATCH 20/24] Update NEWS.md and DESCRIPTION --- DESCRIPTION | 4 ++-- NEWS.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 009ba75..2a38519 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: storr.tiledb Title: A TileDB Storage Driver for Storr -Version: 0.0.38 -Date: 2026-05-18 +Version: 0.0.39 +Date: 2026-05-21 Authors@R: person("Constantinos", "Giachalis", , "xx@github.com", role = c("aut", "cre")) Maintainer: Constantinos Giachalis diff --git a/NEWS.md b/NEWS.md index cb29f4d..b9ac05f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,3 @@ -# storr.tiledb 0.0.38 +# storr.tiledb 0.0.39 * Initial GitHub release. From a13cd88f2ad7068c9f705a29b59f7f956f45d665 Mon Sep 17 00:00:00 2001 From: Constantinos Giachalis Date: Thu, 21 May 2026 11:19:33 +0300 Subject: [PATCH 21/24] Default testthat cpus --- tests/testthat/setup.R | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 tests/testthat/setup.R diff --git a/tests/testthat/setup.R b/tests/testthat/setup.R new file mode 100644 index 0000000..0df721c --- /dev/null +++ b/tests/testthat/setup.R @@ -0,0 +1,3 @@ +Sys.setenv(TESTTHAT_PARALLEL = "true") +Sys.setenv(TESTTHAT_CPUS=4) + From e633fa73e632e4c52a78a4fd9638d7daa82487e5 Mon Sep 17 00:00:00 2001 From: Constantinos Giachalis Date: Thu, 21 May 2026 11:38:40 +0300 Subject: [PATCH 22/24] Test a fix for winCI --- tests/testthat/test-storr_tiledb-async.R | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/testthat/test-storr_tiledb-async.R b/tests/testthat/test-storr_tiledb-async.R index c122361..8eead3d 100644 --- a/tests/testthat/test-storr_tiledb-async.R +++ b/tests/testthat/test-storr_tiledb-async.R @@ -131,12 +131,13 @@ test_that("mset_async", { # fixed = TRUE, # class = "error") - disable_mirai() + # disable_mirai() }) test_that("set_by_value_async", { + Sys.sleep(1) uri <- file.path(withr::local_tempdir(), "test-driver") sto <- storr_tiledb(uri, init = TRUE, async = TRUE) From 3f49bc694890a151ac6929723378fe1d4b153f54 Mon Sep 17 00:00:00 2001 From: Constantinos Giachalis Date: Thu, 21 May 2026 11:48:10 +0300 Subject: [PATCH 23/24] Another try for winCI --- tests/testthat/test-storr_tiledb-async.R | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/testthat/test-storr_tiledb-async.R b/tests/testthat/test-storr_tiledb-async.R index 8eead3d..3b74888 100644 --- a/tests/testthat/test-storr_tiledb-async.R +++ b/tests/testthat/test-storr_tiledb-async.R @@ -131,13 +131,12 @@ test_that("mset_async", { # fixed = TRUE, # class = "error") - # disable_mirai() + disable_mirai() }) test_that("set_by_value_async", { - Sys.sleep(1) uri <- file.path(withr::local_tempdir(), "test-driver") sto <- storr_tiledb(uri, init = TRUE, async = TRUE) @@ -162,7 +161,7 @@ test_that("set_by_value_async", { m2$mirai$obj[] m2$mirai$key[] - # Sys.sleep(1) + Sys.sleep(1) # expect_equal(sto$get("a"), 1) # expect_equal(sto$get("b", "ns2"), 2) From 3d461d0fec316bc5b70817bf99295ab7d5af760e Mon Sep 17 00:00:00 2001 From: Constantinos Giachalis Date: Thu, 21 May 2026 11:56:23 +0300 Subject: [PATCH 24/24] Wait to resolve --- tests/testthat/test-storr_tiledb-async.R | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tests/testthat/test-storr_tiledb-async.R b/tests/testthat/test-storr_tiledb-async.R index 3b74888..1c4d9a0 100644 --- a/tests/testthat/test-storr_tiledb-async.R +++ b/tests/testthat/test-storr_tiledb-async.R @@ -152,9 +152,6 @@ test_that("set_by_value_async", { list(expires_at = as.POSIXct(NA), notes = NA_character_)) - h <- c(m1$hash, m2$hash) - expect_equal(sto$mget_keymeta(h, c("objects", "ns2")), trg) - # wait mirai elements to be resolved m1$mirai$obj[] m1$mirai$key[] @@ -162,6 +159,10 @@ test_that("set_by_value_async", { m2$mirai$key[] Sys.sleep(1) + + h <- c(m1$hash, m2$hash) + expect_equal(sto$mget_keymeta(h, c("objects", "ns2")), trg) + # expect_equal(sto$get("a"), 1) # expect_equal(sto$get("b", "ns2"), 2) @@ -358,15 +359,17 @@ test_that("mset_keymeta_async", { as.POSIXct(NA)), notes = c("😀", NA_character_))) + # wait mirai elements to be resolved + miall <- m1$mirai[] + + Sys.sleep(1) + expect_named(m1, c("mirai", "keyns")) expect_true( mirai::is_mirai(m1$mirai)) expect_equal(m1$keyns, c("x:objects", "y:objects")) expect_equal(sto$mget_keymeta(c("x", "y")), trgval) - # wait mirai elements to be resolved - miall <- m1$mirai[] - expect_equal(sto$mget_keymeta(c("x", "y"), use_cache = FALSE), trgval, ignore_attr = TRUE)