R/disk-cache.R

#' @title Create disk cache
#' @description A DiskCache object is a handle for key/value disk caching.
DiskCache <- R6Class(
  classname = "DiskCache",
  inherit = Cache,

  public = list(
    initialize = function(dir = tempfile()) {
      if (!dir.exists(dir))
        dir.create(dir)

      private$disk <- Disk$new(dir)
      private$db <- Database$new(dir)

      # run initialization sql query
      private$db$execute(private$sql$init)
    },

    # disk and db handles destroyed using their respecive functions
    destroy = function() {},

    get = function(key, default = NULL) {
      key_hash <- private$hash(key)
      row <- private$db$fetch(private$sql$get, list(key_hash = key_hash))

      if (private$is_empty(row)) {
        return(default)
      }

      if (private$is_expired(row)) {
        self$delete(key)
        return(default)
      }

      return(private$disk$read(key_hash))
    },

    exists = function(key) {
      key_hash <- private$hash(key)
      private$disk$exists(key_hash)
    },

    # TODO: move params part to private
    set = function(key, value, expire_in = NULL) {
      key_hash <- private$hash(key)
      time_now <- time_now()

      private$db$execute(
        private$sql$insert,
        params =
          list(
            key_hash = key_hash,
            store_time = time_now,
            expire_time = ifelse(is.null(expire_in), NA, time_now + expire_in),
            access_time = time_now,
            access_count = 0
          )
      )

      private$disk$write(file_name = key_hash, value)
    },

    # delete key from cache
    delete = function(key) {
      key_hash <- private$hash(key)

      private$db$execute(
        "delete from cache where key_hash = :key_hash",
        params = list(key_hash = key_hash)
      )

      private$disk$delete(key_hash)
    },

    # TODO: implement
    trim = function() {}
  ),

  private = list(
    disk = NULL,
    db = NULL,

    # TODO: rethink these static lists of statements
    sql = list(
      init =
        "CREATE TABLE IF NOT EXISTS cache (
            key_hash TEXT PRIMARY KEY,
            store_time REAL,
            expire_time REAL,
            access_time REAL,
            access_count INTEGER DEFAULT 0
          );
        CREATE INDEX IF NOT EXISTS cache_key_hash ON cache(key_hash);
      ",
      get =
        "select key_hash, store_time, expire_time, access_time, access_count
        from cache where key_hash = :key_hash
      ",
      insert =
        "INSERT INTO cache VALUES (:key_hash, :store_time, :expire_time, :access_time, :access_count)"
    )
  )
)
skubicius/cashmere documentation built on May 22, 2019, 2:46 p.m.