LlmGuard.Cache.PatternCache (LlmGuard v0.3.1)

View Source

High-performance caching layer for compiled patterns and detection results.

Provides two-tier caching:

  1. Pattern Cache - Persistent cache of compiled regex patterns (never expires)
  2. Result Cache - TTL-based cache of detection results (configurable expiration)

Features

  • ETS-based storage for fast concurrent access
  • Configurable TTL for result caching
  • LRU eviction for result cache
  • Thread-safe operations
  • Memory-efficient storage
  • Cache statistics and monitoring

Performance

  • Pattern compilation: O(1) after first compilation
  • Result lookup: O(1) average case
  • Memory usage: ~5KB per cached pattern, ~1KB per result
  • Throughput: >100,000 ops/sec

Examples

# Start the cache
{:ok, _pid} = PatternCache.start_link()

# Cache a compiled pattern
pattern = ~r/ignore.*instructions/i
PatternCache.put_pattern("ignore_inst", pattern)

# Retrieve cached pattern
{:ok, pattern} = PatternCache.get_pattern("ignore_inst")

# Cache detection result
result = {:detected, %{confidence: 0.95}}
PatternCache.put_result("input_hash_123", "prompt_injection", result, 300)

# Retrieve cached result
{:ok, result} = PatternCache.get_result("input_hash_123", "prompt_injection")

# Get cache statistics
stats = PatternCache.stats()

Summary

Functions

Returns a specification to start this module under a supervisor.

Clears all caches (patterns and results).

Clears all cached results.

Retrieves a cached pattern.

Retrieves a cached detection result.

Computes SHA256 hash of input string for cache key.

Caches a compiled regex pattern.

Synchronous version of put_result for testing. Caches a detection result and waits for the operation to complete.

Starts the pattern cache GenServer.

Returns cache statistics.

Triggers cleanup of expired entries synchronously. Useful for testing expiration behavior without timing dependencies.

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

clear_all()

@spec clear_all() :: :ok

Clears all caches (patterns and results).

Returns

:ok

clear_results()

@spec clear_results() :: :ok

Clears all cached results.

Patterns are not cleared as they are permanent.

Returns

:ok

get_pattern(pattern_id)

@spec get_pattern(String.t() | atom()) :: {:ok, Regex.t()} | :error

Retrieves a cached pattern.

Parameters

  • pattern_id - Pattern identifier

Returns

  • {:ok, pattern} - Pattern found
  • :error - Pattern not found

get_result(input_hash, detector)

@spec get_result(String.t(), String.t() | atom()) :: {:ok, any()} | :error

Retrieves a cached detection result.

Parameters

  • input_hash - Hash of the input text
  • detector - Detector module name

Returns

  • {:ok, result} - Cached result found and not expired
  • :error - No cached result or expired

hash_input(input)

@spec hash_input(String.t()) :: String.t()

Computes SHA256 hash of input string for cache key.

Parameters

  • input - Input string to hash

Returns

Hex-encoded hash string

put_pattern(pattern_id, compiled_pattern)

@spec put_pattern(String.t() | atom(), Regex.t()) :: :ok

Caches a compiled regex pattern.

Patterns are cached permanently and never expire.

Parameters

  • pattern_id - Unique identifier for the pattern
  • compiled_pattern - Compiled regex pattern

Returns

:ok

put_result(input_hash, detector, result, ttl \\ nil)

@spec put_result(String.t(), String.t() | atom(), any(), pos_integer() | nil) :: :ok

Caches a detection result.

Results are cached with TTL and subject to LRU eviction.

Parameters

  • input_hash - Hash of the input text
  • detector - Detector module name
  • result - Detection result to cache
  • ttl - Time-to-live in seconds (optional, uses default if not provided)

Returns

:ok

put_result_sync(input_hash, detector, result, ttl \\ nil)

@spec put_result_sync(String.t(), String.t() | atom(), any(), pos_integer() | nil) ::
  :ok

Synchronous version of put_result for testing. Caches a detection result and waits for the operation to complete.

start_link(opts \\ [])

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

Starts the pattern cache GenServer.

Options

  • :max_results - Maximum number of cached results (default: 10,000)
  • :result_ttl - Default TTL for results in seconds (default: 300)
  • :cleanup_interval - Interval for cleanup in ms (default: 60,000)

stats()

@spec stats() :: %{
  pattern_count: non_neg_integer(),
  result_count: non_neg_integer(),
  pattern_hits: integer(),
  pattern_misses: integer(),
  result_hits: integer(),
  result_misses: integer(),
  hit_rate: float()
}

Returns cache statistics.

Returns

Map with statistics:

  • :pattern_count - Number of cached patterns
  • :result_count - Number of cached results
  • :pattern_hits - Pattern cache hits
  • :pattern_misses - Pattern cache misses
  • :result_hits - Result cache hits
  • :result_misses - Result cache misses
  • :hit_rate - Overall cache hit rate (0.0-1.0)

trigger_cleanup()

@spec trigger_cleanup() :: :ok

Triggers cleanup of expired entries synchronously. Useful for testing expiration behavior without timing dependencies.