module Aspire::Caching::Util

Cache utility methods

Constants

CACHEABLE

Rules for determining whether an object URL is cacheable Each rule is a Proc which accepts a parsed URL from parse_url and the CacheEntry instance, and returns true if the object is cacheable or false if not. Rules are applied in the order specified and all rules must return true for an object to be cacheable.

Public Instance Methods

add_filename_prefix(filename, prefix) click to toggle source

Adds a prefix to a filename @param filename [String] the filename @param prefix [String] the prefix @return [String] the filename with prefix

# File lib/aspire/caching/util.rb, line 39
def add_filename_prefix(filename, prefix)
  filename = filename.rpartition(File.basename(filename))
  filename[1] = "#{prefix}#{filename[1]}"
  filename.join
end
add_filename_suffix(filename, suffix) click to toggle source

Adds a suffix to a filename preserving any file extension e.g. add_filename_suffix(‘file.txt’, ‘-suffix’) == ‘file-suffix.txt’ @param filename [String] the filename @param suffix [String] the suffix @return [String] the filename with suffix

# File lib/aspire/caching/util.rb, line 50
def add_filename_suffix(filename, suffix)
  f = filename.split(File::SEPARATOR)
  # If the filename is '.' or '..' add the suffix to the parent path,
  # otherwise add it to the basename
  i = %w[. ..].include?(f[-1]) ? -2 : -1
  # Split the basename around the file extension and prepend the suffix
  # to the extension
  if f[i]
    file_ext = f[i].rpartition(File.extname(f[i]))
    file_ext[1] = "#{suffix}#{file_ext[1]}"
    f[i] = file_ext.join
  end
  # Reconstruct the filename, preserving any trailing path separator
  f.push('') if filename.end_with?(File::SEPARATOR)
  File.join(f)
end
cacheable_url(u) click to toggle source

Parses the URL and checks that it is cacheable @param u [String] the URL of the API object @return [MarchData] the parsed URL @raise [Aspire::Exceptions::NotCacheable] if the URL is not

cacheable
# File lib/aspire/caching/util.rb, line 72
def cacheable_url(u)
  # All rules must return true for the URL to be cacheable
  u = parse_url(u)
  CACHEABLE.each do |r|
    raise Aspire::Exceptions::NotCacheable unless r.call(u, self)
  end
  # Return the parsed URL
  u
end
end_of_path?(dir, root = nil) click to toggle source

Returns true if the directory path has no more parents, false otherwise @param dir [String] the directory path @param root [String] the directory root - paths above this are ignored @return [Boolean] true if there are no more parents, false otherwise

# File lib/aspire/caching/util.rb, line 86
def end_of_path?(dir, root = nil)
  dir.nil? || dir.empty? || dir == '.' || dir == root
end
mkdir(dir, logger = nil, success = nil, failure = nil) click to toggle source

Creates a directory and its parents, logs errors @param dir [String] the directory name @param logger [Aspire::Caching::CacheLogger] the logger for messages @param failure [String] the error message on failure @return [void] @raise [ArgumentError] if the directory is not specified @raise [Aspire::Cache::Exceptions::WriteError] if the operation fails

# File lib/aspire/caching/util.rb, line 97
def mkdir(dir, logger = nil, success = nil, failure = nil)
  raise ArgumentError, 'Directory expected' if dir.nil? || dir.empty?
  FileUtils.mkdir_p(dir, mode: mode)
  return if logger.nil? || success.nil? || success.empty?
  logger.log(Logger::DEBUG, success)
rescue SystemCallError => e
  failure ||= "Create directory #{dir} failed"
  message = "#{failure}: #{e}"
  raise WriteError, message if logger.nil?
  logger.log_exception(message, WriteError)
end
references(url, data = nil) click to toggle source

Returns the list of URI references from a linked data API object @param url [String] the URL of the API object @param data [Hash] the parsed JSON data for the object @return [Array<String>] the list of URIs referenced by the object

# File lib/aspire/caching/util.rb, line 113
def references(url, data = nil)
  return [] if data.nil? || data.empty?
  # Enumerate the URIs and add them as keys of a hash to de-duplicate
  enum = Aspire::Enumerator::LinkedDataURIEnumerator.new.enumerator(url, data)
  uris = {}
  enum.each { |_k, hash, _i| uris[hash['value']] = true }
  # Return the list of URIs
  uris.keys
end
rm(glob, logger = nil, success = nil, failure = nil) click to toggle source

Removes the specified files @param glob [String] the file pattern to be removed @param logger [Aspire::Caching::CacheLogger] the logger for messages @param success [String] the text for success log messages @param failure [String] the text for failure exception/log messages @return [void] @raise [Aspire::Cache::Exceptions::RemoveError] if the removal fails

# File lib/aspire/caching/util.rb, line 130
def rm(glob, logger = nil, success = nil, failure = nil)
  raise ArgumentError, 'file path required' if glob.nil? || glob.empty?
  FileUtils.rm_rf(Dir.glob(glob), secure: true)
  return if logger.nil? || success.nil? || success.empty?
  logger.log(Logger::INFO, success)
rescue SystemCallError => e
  failure ||= "Remove #{glob} failed"
  message = "#{failure}: #{e}"
  raise RemoveError, message if logger.nil?
  logger.log_exception("#{failure}: #{e}", RemoveError)
end
rmdir_empty(path, root) click to toggle source

Remove empty directories in a directory path @param path [String] the starting file or directory @param root @return [void] @raise [Aspire::Exceptions::RemoveError] if the operation fails

# File lib/aspire/caching/util.rb, line 147
def rmdir_empty(path, root)
  # The starting path is assumed to be a filename, so we append a dummy
  # filename if it's a directory
  path = File.directory?(path) ? File.join(path, '.') : path
  loop do
    # Get the parent of the current directory/file
    path = File.dirname(path)
    # Stop at the end of the directory path or a non-empty directory
    break if end_of_path?(path, root) || !Dir.empty?(path)
    # Remove the directory
    Dir.rmdir(path)
  end
rescue Errno::ENOTEMPTY, Errno::ENOTDIR
  # Stop without error if the directory is not empty or not a directory
  nil
rescue SystemCallError => e
  raise RemoveError, "Rmdir #{dir} failed: #{e}"
end
strip_ext(path) click to toggle source

Removes the file extension from a path @param path [String] the file path @return [String] the file path with any extension removed

# File lib/aspire/caching/util.rb, line 169
def strip_ext(path)
  path.rpartition(File.extname(path))[0]
end
strip_filename_prefix(filename, prefix) click to toggle source

Removes a prefix from a filename @param filename [String] the filename @param prefix [String] the prefix @return [String] the filename without prefix

# File lib/aspire/caching/util.rb, line 177
def strip_filename_prefix(filename, prefix)
  f = filename.rpartition(File.basename(filename))
  f[1] = strip_prefix(f[1], prefix)
  f.join
end
strip_filename_suffix(filename, suffix) click to toggle source

Removes a suffix from a filename @param filename [String] the filename @param suffix [String] the suffix @return [String] the filename without suffix

# File lib/aspire/caching/util.rb, line 187
def strip_filename_suffix(filename, suffix)
  f = filename.rpartition(File.extname(filename))
  f[0] = strip_suffix(f[0], suffix)
  f.join
end
strip_prefix(str, prefix) click to toggle source

Removes a prefix from a string @param str [String] the string to remove the prefix from @param prefix [String] the prefix to remove @return [String] the string with the prefix removed

# File lib/aspire/caching/util.rb, line 197
def strip_prefix(str, prefix)
  str.start_with?(prefix) ? str.slice(prefix.length..-1) : str
end
strip_suffix(str, suffix) click to toggle source

Removes a suffix from a string @param str [String] the string to remove the suffix from @param suffix [String] the suffix to remove @return [String] the string with the suffix removed

# File lib/aspire/caching/util.rb, line 205
def strip_suffix(str, suffix)
  str.end_with?(suffix) ? str.slice(0...-suffix.length) : str
end