NanoGlobalCache

🔒 Lightweight global cache for Elixir with expiration support and intelligent failure handling.

Perfect for caching OAuth tokens, API keys, and other time-sensitive data that shouldn't be repeatedly refreshed.

Why NanoGlobalCache?

Installation

def deps do
  [{:nano_global_cache, "~> 0.2.1"}]
end

Quick Example

defmodule MyApp.TokenCache do
  use NanoGlobalCache

  # Regular OAuth token - calculate expiration yourself
  cache :github do
    fetch fn ->
      case GitHub.refresh_token() do
        {:ok, token} ->
          expires_at = System.system_time(:millisecond) + :timer.hours(1)
          {:ok, token, expires_at}
        :error ->
          :error
      end
    end
  end

  # JWT token - use expiration time from the token itself
  cache :auth0 do
    fetch fn ->
      case Auth0.get_access_token() do
        {:ok, jwt} ->
          # JWT exp claim is in seconds, convert to milliseconds
          %{"exp" => exp_seconds} = JOSE.JWT.peek_payload(jwt)
          expires_at = exp_seconds * 1000
          {:ok, jwt, expires_at}
        :error ->
          :error
      end
    end
  end

  # Generated functions: fetch/1, fetch!/1, clear/1, clear_all/0
end

Usage

# Pattern match on result with expiration time
{:ok, token, expires_at} = MyApp.TokenCache.fetch(:github)

# Or use bang version (no expiration time)
token = MyApp.TokenCache.fetch!(:github)

# Clear cache
MyApp.TokenCache.clear(:github)
MyApp.TokenCache.clear_all()

How It Works

When to Use

This library is optimized for lightweight data like:

NOT recommended for:

NanoGlobalCache uses :global and Agent for simplicity and minimal overhead. Each cache lives on a single node without replication - other nodes access it remotely. It's designed for scenarios where performance impact is negligible and simplicity is valued over throughput.

For more demanding use cases, consider Cachex or Nebulex.

API Reference

Define Caches

cache :cache_name do
  fetch fn ->
    # Your fetch logic here
    # Must return {:ok, value, expires_at} or :error
    # expires_at is Unix timestamp in milliseconds
    {:ok, value, System.system_time(:millisecond) + ttl_milliseconds}
  end
end

Generated Functions

Implementation