179 lines
4.8 KiB
Elixir
179 lines
4.8 KiB
Elixir
defmodule Bright.Cache do
|
|
@moduledoc """
|
|
A simple caching module that saves files to the `/tmp` directory.
|
|
"""
|
|
|
|
require Logger
|
|
|
|
# def cache_dir do
|
|
# case Application.get_env(:bright, :cache_dir) do
|
|
# {:ok, dir} when is_binary(dir) and dir != "" ->
|
|
# Logger.debug("cache_dir is #{dir}")
|
|
# dir
|
|
|
|
# {:ok, nil} ->
|
|
# raise """
|
|
# Configuration :cache_dir for application :bright is set to nil.
|
|
# Please provide a valid directory path, e.g.:
|
|
|
|
# config :bright, cache_dir: "/path/to/cache"
|
|
# """
|
|
|
|
# {:ok, ""} ->
|
|
# raise """
|
|
# Configuration :cache_dir for application :bright is set to an empty string.
|
|
# Please provide a valid directory path, e.g.:
|
|
|
|
# config :bright, cache_dir: "/path/to/cache"
|
|
# """
|
|
|
|
# :error ->
|
|
# raise """
|
|
# Configuration :cache_dir for application :bright is not set.
|
|
# Please ensure it is defined in your config files, e.g.:
|
|
|
|
# config :bright, cache_dir: "/path/to/cache"
|
|
# """
|
|
# end
|
|
# end
|
|
|
|
def generate_basename(input) do
|
|
if is_nil(input), do: raise("generate_basename was called with nil argument")
|
|
|
|
prefix =
|
|
:crypto.strong_rand_bytes(6)
|
|
|> Base.encode64(padding: false)
|
|
|> String.replace(~r/[^a-zA-Z0-9]/, "")
|
|
|
|
base = Path.basename(input)
|
|
output = "#{prefix}/#{base}"
|
|
Logger.debug("generate_basename called with input=#{input} output=#{output}")
|
|
output
|
|
end
|
|
|
|
# @doc """
|
|
# get a filename in the cache directory.
|
|
# the path contains a sha256 hash of the file basename.
|
|
# thus for any given input, output filename will always be the same.
|
|
# """
|
|
# def deterministic_filename(input) do
|
|
# input
|
|
# |> Path.basename()
|
|
# |> sha256sum_truncate()
|
|
# end
|
|
|
|
def generate_basename(input, ext) do
|
|
if is_nil(input), do: raise("generate_basename was called with nil argument")
|
|
|
|
input
|
|
|> generate_basename
|
|
|> Path.rootname()
|
|
|> Kernel.<>(".#{ext}")
|
|
end
|
|
|
|
def generate_filename(input) do
|
|
Logger.debug("generate_filename called with input=#{input}, cache_dir=#{get_cache_dir()}")
|
|
filename = Path.join(get_cache_dir(), generate_basename(input))
|
|
File.mkdir_p!(Path.dirname(filename))
|
|
Logger.debug("generate_filename filename=#{filename}")
|
|
Logger.debug("generate_filename filename=#{filename}")
|
|
Logger.debug("generate_filename filename=#{filename}")
|
|
filename
|
|
end
|
|
|
|
def generate_filename(input, ext) do
|
|
filename = Path.join(get_cache_dir(), generate_basename(input, ext))
|
|
File.mkdir_p!(Path.dirname(filename))
|
|
filename
|
|
end
|
|
|
|
def get_cache_dir do
|
|
case Application.fetch_env(:bright, :cache_dir) do
|
|
{:ok, dir} when is_binary(dir) and dir != "" ->
|
|
Logger.debug("cache_dir is #{dir}")
|
|
dir
|
|
|
|
{:ok, ""} ->
|
|
raise """
|
|
Configuration :cache_dir for application :bright is set to an empty string.
|
|
Please provide a valid directory path, e.g.:
|
|
|
|
config :bright, cache_dir: "/path/to/cache"
|
|
"""
|
|
|
|
{:ok, nil} ->
|
|
raise """
|
|
Configuration :cache_dir for application :bright is set to nil.
|
|
Please provide a valid directory path, e.g.:
|
|
|
|
config :bright, cache_dir: "/path/to/cache"
|
|
"""
|
|
|
|
:error ->
|
|
raise """
|
|
Configuration :cache_dir for application :bright is not set.
|
|
Please ensure it is defined in your config files, e.g.:
|
|
|
|
config :bright, cache_dir: "/path/to/cache"
|
|
"""
|
|
end
|
|
end
|
|
|
|
# Ensure the cache directory exists
|
|
def ensure_cache_dir! do
|
|
unless File.exists?(get_cache_dir()) do
|
|
File.mkdir_p!(get_cache_dir())
|
|
end
|
|
end
|
|
|
|
@doc """
|
|
Delete a cached item by its key.
|
|
|
|
## Examples
|
|
|
|
iex> Bright.Cache.delete("example_key")
|
|
:ok
|
|
|
|
iex> Bright.Cache.delete("nonexistent_key")
|
|
:ok
|
|
"""
|
|
def delete(key) do
|
|
ensure_cache_dir!()
|
|
|
|
file_path = generate_filename(key)
|
|
|
|
case File.rm(file_path) do
|
|
:ok ->
|
|
Logger.debug("[Cache] Deleted key #{key} from #{file_path}")
|
|
:ok
|
|
|
|
{:error, :enoent} ->
|
|
Logger.debug("[Cache] Key #{key} not found for deletion")
|
|
:ok
|
|
|
|
{:error, reason} ->
|
|
Logger.error("[Cache] Failed to delete key #{key}: #{reason}")
|
|
{:error, reason}
|
|
end
|
|
end
|
|
|
|
# @doc """
|
|
# Generates a SHA-256 hash of the input string and truncates it to 10 characters.
|
|
|
|
# ## Parameters
|
|
# - `input`: A string to be hashed.
|
|
|
|
# ## Returns
|
|
# A string representing the first 10 characters of the SHA-256 hash in hexadecimal format.
|
|
|
|
# ## Examples
|
|
# iex> Cache.sha256sum_truncate("hello world")
|
|
# "2cf24dba5f"
|
|
# """
|
|
# defp sha256sum_truncate(input) do
|
|
# hash = :crypto.hash(:sha256, input) |> Base.encode16(case: :lower)
|
|
|
|
# String.slice(hash, 0..9)
|
|
# end
|
|
end
|