Vaultx.Cache (Vaultx v0.7.0)
View SourceEnterprise-grade multi-layer caching system for VaultX.
â ïļ Experimental Feature: This caching system is currently experimental and may undergo breaking changes in future versions. Use with caution in production environments.
ð Coverage Note: This module is excluded from test coverage requirements as it's an experimental feature undergoing rapid development. See .coveralls.exs for details.
This module provides a sophisticated caching infrastructure with three distinct layers optimized for different access patterns and durability requirements. The system is designed for high-performance Vault operations with intelligent data management.
Architecture Overview
The cache system implements a hierarchical storage architecture:
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â Application Layer â
âââââââââââââââââââââââŽââââââââââââââââââââââââââââââââââââââââ
â
âââââââââââââââââââââââžââââââââââââââââââââââââââââââââââââââââ
â L1 Cache (Memory) â ETS Tables, ~1Ξs latency â
â âĒ Ultra-fast access â
â âĒ LRU eviction â
â âĒ Configurable size limits â
âââââââââââââââââââââââŽââââââââââââââââââââââââââââââââââââââââ
â (on miss)
âââââââââââââââââââââââžââââââââââââââââââââââââââââââââââââââââ
â L2 Cache (Distributed) â Pluggable adapters, ~10Ξs â
â âĒ Cross-node sharing â
â âĒ Memory/Redis adapters â
â âĒ Automatic promotion to L1 â
âââââââââââââââââââââââŽââââââââââââââââââââââââââââââââââââââââ
â (on miss)
âââââââââââââââââââââââžââââââââââââââââââââââââââââââââââââââââ
â L3 Cache (Persistent) â File system, ~10ms latency â
â âĒ Survives restarts â
â âĒ Optional AES-256-GCM encryption â
â âĒ Automatic promotion to L1/L2 â
âââââââââââââââââââââââŽââââââââââââââââââââââââââââââââââââââââ
â (on miss)
âââââââââââââââââââââââžââââââââââââââââââââââââââââââââââââââââ
â Original Data Source (Vault) â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââKey Features
Performance Optimization
- Hierarchical Access: Fastest cache checked first
- Automatic Promotion: Frequently accessed data moves to faster layers
- Intelligent Eviction: LRU and TTL-based cleanup
- Concurrent Operations: Lock-free reads, safe writes
- Memory Management: Configurable limits with automatic cleanup
Reliability & Durability
- Graceful Degradation: System continues if individual layers fail
- Atomic Operations: Consistent state during failures
- Process Monitoring: Automatic restart of failed cache layers
- Data Integrity: Checksums and validation for persistent storage
- Backup & Recovery: Export/import capabilities for cache data
Security & Compliance
- Encryption at Rest: AES-256-GCM for L3 persistent storage
- Secure Key Management: Multiple key sources with proper permissions
- Access Control: Integration with VaultX authentication
- Audit Logging: Comprehensive operation tracking
- Data Classification: Support for sensitive data handling
Usage Examples
# Basic cache operations
{:ok, secret} = Vaultx.Cache.get("secret/myapp/config")
:ok = Vaultx.Cache.put("secret/myapp/config", secret_data)
:ok = Vaultx.Cache.delete("secret/myapp/config")
# TTL-based caching
:ok = Vaultx.Cache.put("temp_token", token, ttl: :timer.minutes(5))
# Get-or-compute pattern (recommended)
secret = Vaultx.Cache.get_or_compute("secret/expensive/operation", fn ->
# This function only runs on cache miss
fetch_expensive_secret_from_vault()
end, ttl: :timer.hours(1))
# Bulk operations
{:ok, results} = Vaultx.Cache.get_many(["key1", "key2", "key3"])
:ok = Vaultx.Cache.put_many([{"key1", "val1"}, {"key2", "val2"}])
# Pattern-based operations
:ok = Vaultx.Cache.clear("secret/myapp/*") # Clear specific patterns
:ok = Vaultx.Cache.clear(:all) # Clear all caches
# Cache warming (preload frequently accessed data)
:ok = Vaultx.Cache.warm("secret/myapp/*", &load_secret_function/1)
# Monitoring and statistics
{:ok, stats} = Vaultx.Cache.stats()
# Returns comprehensive statistics for all cache layersConfiguration
# Application configuration
config :vaultx,
# Core cache settings
cache_enabled: true,
cache_eviction_policy: :lru,
cache_max_memory_usage: 100 * 1024 * 1024, # 100MB
# L1 Memory Cache
cache_l1_enabled: true,
cache_l1_max_size: 10_000,
cache_l1_ttl_default: 900_000, # 15 minutes
cache_l1_cleanup_interval: 300_000, # 5 minutes
# L2 Distributed Cache
cache_l2_enabled: true,
cache_l2_adapter: Vaultx.Cache.Adapters.Memory,
cache_l2_max_size: 50_000,
cache_l2_ttl_default: 3_600_000, # 1 hour
cache_l2_cleanup_interval: 600_000, # 10 minutes
# L3 Persistent Cache
cache_l3_enabled: false,
cache_l3_storage_path: "/var/cache/vaultx",
cache_l3_ttl_default: 86_400_000, # 24 hours
cache_l3_cleanup_interval: 3_600_000, # 1 hour
cache_l3_encryption: false,
# Advanced features
cache_warming_enabled: true,
cache_metrics_enabled: true,
cache_manager_cleanup_interval: 300_000 # 5 minutes
# Environment variable overrides
export VAULTX_CACHE_ENABLED=true
export VAULTX_CACHE_L3_ENABLED=true
export VAULTX_CACHE_L3_ENCRYPTION=true
export VAULTX_L3_ENCRYPTION_KEY="$(openssl rand -base64 32)"Performance Characteristics
| Layer | Latency | Throughput | Capacity | Durability |
|---|---|---|---|---|
| L1 | ~1Ξs | 1M+ ops/s | 10K items | Process |
| L2 | ~10Ξs | 100K ops/s | 50K items | Node |
| L3 | ~10ms | 1K ops/s | Unlimited | Persistent |
Integration with VaultX
Current Support Status
| Operation | Status | Cache Key Format | Default TTL |
|---|
| KV v2 Read | â
Implemented | kv2:{mount}:{path}|{version} | 15 minutes |
| KV v1 Read | â Not Supported | - | - |
| Auth Token Validation | ð§ Planned | auth:token:{hash} | Token TTL |
| Policy Evaluation | ð§ Planned | policy:{name}:{hash} | 1 hour |
| Mount Metadata | ð§ Planned | mount:{path}:metadata | 1 hour |
| Lease Information | ð§ Planned | lease:{id} | Lease TTL |
Supported Operations
- KV v2 Secrets: Automatic caching of secret reads with intelligent TTL
- Cache keys include mount path, secret path, and version
- Automatic cache invalidation on write/delete operations
- Configurable TTL with 15-minute default
- Support for both versioned and latest reads
Planned Integrations
- Auth Tokens: Token validation caching with security considerations
- Policy Data: Policy evaluation caching for performance optimization
- Metadata: Mount and engine metadata caching for reduced API calls
- Leases: Lease information caching with proper expiration handling
Best Practices
Development
- Use
get_or_compute/3for expensive operations - Set appropriate TTLs based on data sensitivity and change frequency
- Monitor cache hit rates and adjust configuration accordingly
- Test cache behavior in failure scenarios
Production
- Enable L3 persistent cache for critical data
- Use encryption for sensitive cached data
- Monitor memory usage and set appropriate limits
- Implement cache warming for frequently accessed data
- Set up proper monitoring and alerting
Security
- Enable encryption for sensitive data in L3 cache
- Use environment variables for encryption keys
- Regularly rotate encryption keys
- Monitor cache access patterns for anomalies
- Implement proper cache invalidation on security events
Summary
Functions
Clears all cache layers or specific patterns.
Deletes a value from the cache.
Gets a value from the cache.
Gets multiple values from the cache in a single operation.
Gets a value from cache or computes it if not found.
Puts a value into the cache.
Puts multiple key-value pairs into the cache.
Starts the cache system.
Gets comprehensive cache statistics.
Warms the cache by preloading data matching a pattern.
Types
@type cache_key() :: String.t()
@type cache_options() :: [ ttl: pos_integer(), layer: :l1 | :l2 | :l3 | :all, strategy: :lru | :lfu | :ttl, encrypt: boolean() ]
@type cache_result() :: {:ok, cache_value()} | {:error, :not_found | Vaultx.Base.Error.t()}
@type cache_stats() :: %{ l1: map(), l2: map(), l3: map(), total_hits: non_neg_integer(), total_misses: non_neg_integer(), hit_ratio: float(), memory_usage: non_neg_integer() }
@type cache_value() :: term()
Functions
@spec clear(String.t() | :all) :: :ok
Clears all cache layers or specific patterns.
Examples
:ok = Vaultx.Cache.clear()
:ok = Vaultx.Cache.clear("secret/myapp/*")
@spec delete(cache_key()) :: :ok | {:error, Vaultx.Base.Error.t()}
Deletes a value from the cache.
Removes the value from all cache layers.
Examples
:ok = Vaultx.Cache.delete("secret/myapp/config")
@spec get(cache_key(), cache_options()) :: cache_result()
Gets a value from the cache.
Searches through cache layers in order (L1 -> L2 -> L3) and returns the first found value. Updates higher-priority layers with found values.
Examples
{:ok, value} = Vaultx.Cache.get("secret/myapp/config")
{:error, :not_found} = Vaultx.Cache.get("nonexistent/key")
@spec get_many([cache_key()], cache_options()) :: {:ok, %{required(cache_key()) => cache_value()}}
Gets multiple values from the cache in a single operation.
Examples
{:ok, results} = Vaultx.Cache.get_many(["key1", "key2", "key3"])
# Returns: %{"key1" => value1, "key2" => value2, "key3" => nil}
@spec get_or_compute(cache_key(), (-> cache_value()), cache_options()) :: cache_value()
Gets a value from cache or computes it if not found.
This is the most commonly used caching pattern. If the key is not found in any cache layer, the compute function is called and the result is stored in the cache.
Examples
value = Vaultx.Cache.get_or_compute("expensive/operation", fn ->
perform_expensive_operation()
end, ttl: :timer.hours(1))
@spec put(cache_key(), cache_value(), cache_options()) :: :ok | {:error, Vaultx.Base.Error.t()}
Puts a value into the cache.
Stores the value in the specified layer(s) with optional TTL and encryption.
Examples
:ok = Vaultx.Cache.put("secret/myapp/config", %{"key" => "value"})
:ok = Vaultx.Cache.put("temp/data", data, ttl: :timer.minutes(5))
:ok = Vaultx.Cache.put("sensitive/data", secret, encrypt: true)
@spec put_many([{cache_key(), cache_value()}], cache_options()) :: :ok | {:error, Vaultx.Base.Error.t()}
Puts multiple key-value pairs into the cache.
Examples
:ok = Vaultx.Cache.put_many([{"key1", "val1"}, {"key2", "val2"}])
@spec start_link(keyword()) :: GenServer.on_start()
Starts the cache system.
@spec stats() :: {:ok, cache_stats()}
Gets comprehensive cache statistics.
Examples
{:ok, stats} = Vaultx.Cache.stats()
@spec warm(String.t(), (cache_key() -> cache_value())) :: :ok | {:error, Vaultx.Base.Error.t()}
Warms the cache by preloading data matching a pattern.
Examples
:ok = Vaultx.Cache.warm("secret/myapp/*", fn key ->
Vaultx.Secrets.KV.read(key)
end)