Gemini.Auth.TokenCache (GeminiEx v0.8.4)

View Source

ETS-based token caching with automatic expiration handling.

Provides thread-safe token caching to reduce API calls for token refresh. Tokens are automatically considered expired based on their TTL, with a configurable refresh buffer to ensure tokens are refreshed before expiration.

Features

  • Thread-safe ETS-based storage
  • Automatic expiration handling
  • Refresh buffer (default 5 minutes before expiry)
  • Multiple cache key support for different credentials

Usage

# Initialize the cache (called automatically on application start)
TokenCache.init()

# Cache a token with 3600 second TTL
TokenCache.put("my_key", "access_token_here", 3600)

# Retrieve cached token (returns nil if expired)
case TokenCache.get("my_key") do
  {:ok, token} -> {:ok, token}
  :error -> # Token expired or not found, refresh needed
end

# Invalidate a cached token
TokenCache.invalidate("my_key")

Summary

Functions

Clear all cached tokens.

Retrieve a cached token if it exists and has not expired.

Initialize the token cache table.

Invalidate (remove) a cached token.

Cache a token with the specified time-to-live (TTL).

Get statistics about the token cache.

Types

cache_entry()

@type cache_entry() :: {cache_key(), token(), expiry_time :: integer()}

cache_key()

@type cache_key() :: String.t() | atom()

token()

@type token() :: String.t()

ttl()

@type ttl() :: pos_integer()

Functions

clear()

@spec clear() :: :ok

Clear all cached tokens.

Removes all entries from the cache. Useful for testing or when you need to force refresh all tokens.

Examples

TokenCache.clear()

get(key)

@spec get(cache_key()) :: {:ok, token()} | :error

Retrieve a cached token if it exists and has not expired.

Returns {:ok, token} if the token is cached and still valid, or :error if the token is expired or not found.

Parameters

  • key: The cache key used when storing the token

Returns

  • {:ok, token} - Token is cached and still valid
  • :error - Token is expired, not found, or cache not initialized

Examples

case TokenCache.get("my_key") do
  {:ok, token} ->
    # Use the cached token
    {:ok, token}

  :error ->
    # Token expired or not found, need to refresh
    refresh_token()
end

init()

@spec init() :: :ok

Initialize the token cache table.

Creates an ETS table for storing tokens. This is called automatically when the application starts, but can be called manually if needed.

Safe to call multiple times - if the table already exists, it will not create a new one.

Examples

iex> Gemini.Auth.TokenCache.init()
:ok

invalidate(key)

@spec invalidate(cache_key()) :: :ok

Invalidate (remove) a cached token.

Useful when you know a token is no longer valid and want to force a refresh on the next request.

Parameters

  • key: The cache key to invalidate

Examples

TokenCache.invalidate("my_key")

put(key, token, ttl, opts \\ [])

@spec put(cache_key(), token(), ttl(), keyword()) :: :ok

Cache a token with the specified time-to-live (TTL).

The token will be considered expired after ttl seconds, minus the refresh buffer (default 5 minutes). This ensures tokens are refreshed before they actually expire.

Parameters

  • key: Unique identifier for this token (string or atom)
  • token: The access token to cache
  • ttl: Time-to-live in seconds

Options

  • :refresh_buffer - Seconds before expiry to consider token expired (default: 300 seconds / 5 minutes)

Examples

# Cache token for 1 hour
TokenCache.put("vertex_ai_token", "ya29.abc123", 3600)

# Cache with custom refresh buffer (refresh 10 minutes early)
TokenCache.put("my_token", "token123", 3600, refresh_buffer: 600)

stats()

@spec stats() :: %{size: non_neg_integer(), keys: [cache_key()]}

Get statistics about the token cache.

Returns information about the cache including number of entries and which tokens are cached.

Returns

Map with cache statistics:

  • :size - Number of cached tokens
  • :keys - List of cache keys

Examples

TokenCache.stats()
#=> %{size: 2, keys: ["vertex_ai_token", "another_token"]}