Twm.Cache (Twm v0.1.0)

View Source

LRU (Least Recently Used) cache implementation for Twm.

This module provides caching capabilities for Tailwind class merging operations to improve performance by avoiding redundant operations on the same class combinations. It also stores configuration and class group utilities in ETS tables for efficient access.

This module can be used in two ways:

  1. As a global cache for the main Twm functionality:
defmodule Twm.Application do
  @moduledoc false

  use Application

  @impl true
  def start(_type, _args) do
    children = [
      # Start the Twm.Cache with default configuration
      {Twm.Cache, []}
    ]

    opts = [strategy: :one_for_one, name: Twm.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

You can also pass a custom cache name and configuration:

defmodule Twm.Application do
  @moduledoc false

  use Application

  @impl true
  def start(_type, _args) do
    # Custom configuration
    custom_config = Twm.Config.extend(cache_size: 1000)

    children = [
      # Start the Twm.Cache with custom name and configuration
      {Twm.Cache, [name: :my_twm_cache, config: custom_config]}
    ]

    opts = [strategy: :one_for_one, name: Twm.Supervisor]
    Supervisor.start_link(children, opts)
  end
end
  1. As custom cache instances for custom merge functions:
# Create a custom cache with a specific size
cache_pid = Twm.Cache.ensure_started(20, :cache_23231)

# Use the cache directly
Twm.Cache.put(cache_pid, "key", "value")

Summary

Functions

Returns a specification to start this module under a supervisor.

Clears all entries from the cache.

Ensures a cache server is started with the given size.

Retrieves a value from the cache by key.

Retrieves a value from the cache by key. If it is not present creates one, stores it and returns it.

Stores a key-value pair in the cache.

Changes the maximum capacity of the cache.

Returns the current size of the cache.

Starts the cache server.

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

clear(server \\ __MODULE__)

@spec clear(GenServer.server()) :: :ok

Clears all entries from the cache.

Examples

# Start a cache server for doctest
iex> unique_number = Integer.to_string(:erlang.unique_integer([:positive]))
iex> cache_pid = Twm.Cache.ensure_started(10, String.to_atom("cache" <> unique_number))
iex> Twm.Cache.put(cache_pid, "key1", "value1")
:ok
iex> Twm.Cache.clear(cache_pid)
:ok
iex> Twm.Cache.get(cache_pid, "key1")
:error

ensure_started(cache_size, name \\ __MODULE__)

@spec ensure_started(pos_integer(), atom() | nil) :: pid()

Ensures a cache server is started with the given size.

If a server with the provided name already exists, it returns its pid. Otherwise, it starts a new server with the given cache size.

Examples

iex> unique_number = Integer.to_string(:erlang.unique_integer([:positive]))
iex> cache_pid = Twm.Cache.ensure_started(100, String.to_atom("cache" <> unique_number))
iex> Twm.Cache.put(cache_pid, "key", "value")
:ok
iex> Twm.Cache.get(cache_pid, "key")
{:ok, "value"}

get(server \\ __MODULE__, key)

@spec get(GenServer.server(), any()) :: {:ok, any()} | :error

Retrieves a value from the cache by key.

Returns {:ok, value} if the key exists, or :error if it doesn't.

Examples

# Start a cache server for doctest
iex> unique_number = Integer.to_string(:erlang.unique_integer([:positive]))
iex> cache_pid = Twm.Cache.ensure_started(10, String.to_atom("cache" <> unique_number))
iex> Twm.Cache.put(cache_pid, "key1", "value1")
:ok
iex> Twm.Cache.get(cache_pid, "key1")
{:ok, "value1"}
iex> Twm.Cache.get(cache_pid, "nonexistent_key")
:error

get_or_create(server \\ __MODULE__, key)

@spec get_or_create(GenServer.server(), any()) :: {:ok, any()} | :error

Retrieves a value from the cache by key. If it is not present creates one, stores it and returns it.

Returns {:ok, value} or :error if the cache doesn't exist.

Examples

# Start a cache server for doctest
iex> unique_number = Integer.to_string(:erlang.unique_integer([:positive]))
iex> cache_pid = Twm.Cache.ensure_started(10, String.to_atom("cache" <> unique_number))
iex> Twm.Cache.put(cache_pid, "key1", "value1")
:ok
iex> Twm.Cache.get(cache_pid, "key1")
{:ok, "value1"}
iex> Twm.Cache.get(cache_pid, "nonexistent_key")
:error

put(server \\ __MODULE__, key, value)

@spec put(GenServer.server(), any(), any()) :: :ok

Stores a key-value pair in the cache.

If the key already exists, its value is updated and it becomes the most recently used. If the cache is full, the least recently used entry is removed.

Examples

# Start a cache server for doctest
iex> unique_number = Integer.to_string(:erlang.unique_integer([:positive]))
iex> cache_pid = Twm.Cache.ensure_started(10, String.to_atom("cache" <> unique_number))
iex> Twm.Cache.put(cache_pid, "key1", "value1")
:ok
iex> Twm.Cache.get(cache_pid, "key1")
{:ok, "value1"}

resize(server \\ __MODULE__, new_size)

@spec resize(GenServer.server(), pos_integer()) :: :ok

Changes the maximum capacity of the cache.

If the new size is smaller than the current number of entries, the least recently used entries are removed until the cache fits the new size.

Examples

# Start a cache server for doctest
iex> unique_number = Integer.to_string(:erlang.unique_integer([:positive]))
iex> cache_pid = Twm.Cache.ensure_started(100, String.to_atom("cache" <> unique_number))
iex> # Fill cache with a few entries
iex> Twm.Cache.put(cache_pid, "key1", "value1")
:ok
iex> Twm.Cache.put(cache_pid, "key2", "value2")
:ok
iex> Twm.Cache.resize(cache_pid, 1)
:ok
iex> Twm.Cache.size(cache_pid)
1

size(server \\ __MODULE__)

@spec size(GenServer.server()) :: non_neg_integer()

Returns the current size of the cache.

Examples

# Start a cache server for doctest
iex> unique_number = Integer.to_string(:erlang.unique_integer([:positive]))
iex> cache_pid = Twm.Cache.ensure_started(10, String.to_atom("cache" <> unique_number))
iex> Twm.Cache.put(cache_pid, "key1", "value1")
:ok
iex> Twm.Cache.put(cache_pid, "key2", "value2")
:ok
iex> Twm.Cache.size(cache_pid)
2

start_link(opts \\ [])

@spec start_link(keyword()) :: GenServer.on_start()

Starts the cache server.

Options

  • :name - The name to register the cache process with. Defaults to Twm.Cache.
  • :cache_size - The maximum number of entries in the cache. Defaults to 500.