Skip to Content
Nextra 2 Alpha
Core FeaturesLock File Cache System

Lock File Cache System

Overview

The Lock File Cache System provides comprehensive caching capabilities for Rhema’s lock file operations, optimizing performance for read-heavy workloads and providing persistent storage for frequently accessed data. The system integrates seamlessly with the existing lock file infrastructure and provides multiple caching strategies and invalidation methods.

Features

1. In-Memory Caching

  • Fast access to frequently used lock file data
  • Configurable size limits and eviction strategies
  • Thread-safe concurrent access
  • Automatic cleanup of expired entries

2. Persistent Caching

  • Disk-based storage for cache persistence across sessions
  • Configurable compression for space efficiency
  • Automatic integrity verification with checksums
  • Metadata tracking for cache management

3. Cache Invalidation Strategies

  • Time-based expiration: Automatic cleanup of old entries
  • LRU (Least Recently Used): Evict least recently accessed entries
  • LFU (Least Frequently Used): Evict least frequently accessed entries
  • Size-based eviction: Remove largest entries when space is needed
  • Priority-based eviction: Respect entry priority levels
  • Hybrid strategy: Combine multiple approaches for optimal performance

4. Performance Metrics

  • Hit/miss ratio tracking
  • Access time monitoring
  • Memory usage statistics
  • Cache efficiency scoring
  • Performance optimization recommendations

5. Cache Warming

  • Preload frequently accessed data
  • Pattern-based warming strategies
  • Dependency relationship analysis
  • Time-based access pattern optimization

Architecture

Core Components

1. CacheEntry<T>

Represents a single cache entry with metadata:

pub struct CacheEntry<T> { pub data: T, // Cached data pub created_at: DateTime<Utc>, // Creation timestamp pub last_accessed: DateTime<Utc>, // Last access time pub access_count: u64, // Number of accesses pub ttl: Option<u64>, // Time-to-live in seconds pub checksum: String, // Integrity checksum pub size_bytes: usize, // Approximate size pub priority: u8, // Eviction priority pub pinned: bool, // Whether entry is pinned }

2. InMemoryCache

Handles fast in-memory storage with configurable eviction strategies:

pub struct InMemoryCache { entries: HashMap<String, CacheEntry<Vec<u8>>>, access_order: VecDeque<String>, config: CacheConfig, stats: CacheStats, last_cleanup: Instant, }

3. PersistentCache

Manages disk-based persistent storage:

pub struct PersistentCache { cache_dir: PathBuf, config: CacheConfig, compression_enabled: bool, }

4. LockFileCache

Main cache manager that coordinates in-memory and persistent caches:

pub struct LockFileCache { memory_cache: Arc<RwLock<InMemoryCache>>, persistent_cache: Option<Arc<PersistentCache>>, config: CacheConfig, stats: Arc<Mutex<CacheStats>>, }

Cache Key Types

The system supports multiple cache key types for different lock file data:

pub enum CacheKey { LockFile(PathBuf), // Lock file by repository path Scope(PathBuf), // Scope by path Dependency(String, String), // Dependency by path and constraint ResolutionResult(Vec<String>), // Resolution result by dependencies ValidationResult(String), // Validation result by checksum PerformanceMetrics(String), // Performance metrics by operation Custom(String), // Custom key }

Configuration

CacheConfig

pub struct CacheConfig { pub max_size_bytes: usize, // Maximum cache size pub default_ttl: Option<u64>, // Default time-to-live pub invalidation_strategy: InvalidationStrategy, pub enable_persistent: bool, // Enable persistent caching pub persistent_cache_dir: Option<PathBuf>, pub enable_compression: bool, // Enable compression pub max_entries: usize, // Maximum number of entries pub cleanup_interval: u64, // Cleanup interval in seconds pub enable_stats: bool, // Enable statistics pub enable_warming: bool, // Enable cache warming pub warming_strategy: WarmingStrategy, }

Default Configuration

impl Default for CacheConfig { fn default() -> Self { Self { max_size_bytes: 100 * 1024 * 1024, // 100MB default_ttl: Some(3600), // 1 hour invalidation_strategy: InvalidationStrategy::Hybrid, enable_persistent: true, persistent_cache_dir: None, // Uses .rhema/cache enable_compression: true, max_entries: 10000, cleanup_interval: 300, // 5 minutes enable_stats: true, enable_warming: false, warming_strategy: WarmingStrategy::None, } } }

Usage

Basic Usage

1. Initialize the Cache System

use rhema::lock::{LockSystem, CacheConfig, InvalidationStrategy}; // Initialize with default configuration LockSystem::initialize()?; // Or with custom configuration let config = CacheConfig { max_size_bytes: 50 * 1024 * 1024, // 50MB default_ttl: Some(1800), // 30 minutes invalidation_strategy: InvalidationStrategy::Lru, enable_persistent: true, ..Default::default() }; rhema::lock::init_global_cache(config)?;

2. Cache Lock File Operations

The cache system automatically integrates with lock file operations:

// Generate lock file (automatically cached) let lock_file = LockSystem::generate_lock_file(repo_path)?; // Subsequent calls will use cached data if available let cached_lock_file = LockSystem::generate_lock_file(repo_path)?;

3. Manual Cache Operations

use rhema::lock::{get_global_cache, CacheKey}; let cache = get_global_cache()?; // Store lock file in cache cache.set_lock_file(repo_path, &lock_file, Some(3600))?; // Retrieve from cache if let Some(cached_lock) = cache.get_lock_file(repo_path)? { println!("Using cached lock file"); } // Store scope in cache cache.set_scope(scope_path, &scope, Some(1800))?; // Retrieve scope from cache if let Some(cached_scope) = cache.get_scope(scope_path)? { println!("Using cached scope"); }

Advanced Usage

1. Custom Cache Keys

use rhema::lock::CacheKey; // Create custom cache key let key = CacheKey::Custom("my_custom_data".to_string()); // Store custom data let custom_data = vec![1, 2, 3, 4, 5]; cache.set_serializable(&key, &custom_data, Some(3600), 5)?; // Retrieve custom data let retrieved: Option<Vec<u8>> = cache.get_serializable(&key)?;

2. Cache Statistics and Monitoring

// Get cache statistics let stats = LockSystem::get_cache_stats()?; println!("Cache hit rate: {:.2}%", stats.hit_rate * 100.0); println!("Total entries: {}", stats.total_entries); println!("Total size: {} MB", stats.total_size_bytes / 1024 / 1024); // Get performance report let report = LockSystem::get_cache_performance_report()?; println!("{}", report);

3. Cache Management

// Clear all caches LockSystem::clear_caches()?; // Warm cache for a repository LockSystem::warm_cache(repo_path)?; // Optimize cache based on usage patterns LockSystem::optimize_cache()?;

4. Cache Warming Strategies

use rhema::lock::{CacheConfig, WarmingStrategy}; let config = CacheConfig { enable_warming: true, warming_strategy: WarmingStrategy::FrequentAccess, ..Default::default() }; // Initialize cache with warming enabled rhema::lock::init_global_cache(config)?; // Warm cache for repository LockSystem::warm_cache(repo_path)?;

Integration with Lock File System

Automatic Integration

The cache system automatically integrates with the existing lock file operations:

  1. Lock File Generation: Generated lock files are automatically cached
  2. Scope Resolution: Resolved scopes are cached for future use
  3. Dependency Resolution: Resolved dependencies are cached
  4. Validation Results: Validation results are cached

Performance Benefits

  • Faster Lock File Generation: Subsequent generations use cached data
  • Reduced Dependency Resolution: Cached dependencies avoid re-resolution
  • Improved Validation Performance: Cached validation results
  • Better Resource Utilization: Persistent cache reduces memory pressure

Cache Invalidation Strategies

1. Time-based Expiration

let config = CacheConfig { default_ttl: Some(3600), // 1 hour invalidation_strategy: InvalidationStrategy::TimeBased, ..Default::default() };

2. LRU (Least Recently Used)

let config = CacheConfig { invalidation_strategy: InvalidationStrategy::Lru, max_entries: 1000, ..Default::default() };

3. LFU (Least Frequently Used)

let config = CacheConfig { invalidation_strategy: InvalidationStrategy::Lfu, max_entries: 1000, ..Default::default() };

4. Size-based Eviction

let config = CacheConfig { invalidation_strategy: InvalidationStrategy::SizeBased, max_size_bytes: 50 * 1024 * 1024, // 50MB ..Default::default() };

5. Priority-based Eviction

let config = CacheConfig { invalidation_strategy: InvalidationStrategy::PriorityBased, max_entries: 1000, ..Default::default() };

6. Hybrid Strategy

let config = CacheConfig { invalidation_strategy: InvalidationStrategy::Hybrid, max_size_bytes: 100 * 1024 * 1024, // 100MB max_entries: 10000, ..Default::default() };

Performance Monitoring

Cache Statistics

pub struct CacheStats { pub hits: u64, // Total cache hits pub misses: u64, // Total cache misses pub total_entries: usize, // Current entries pub total_size_bytes: usize, // Current size pub max_size_bytes: usize, // Maximum size pub evictions: u64, // Number of evictions pub expired_entries: u64, // Number of expired entries pub avg_access_time_us: u64, // Average access time pub hit_rate: f64, // Hit rate (0.0 to 1.0) pub last_cleanup: Option<DateTime<Utc>>, pub efficiency_score: f64, // Overall efficiency }

Performance Report

let report = LockSystem::get_cache_performance_report()?; println!("{}", report);

Example output:

Cache Performance Report: - Hit Rate: 85.50% - Total Entries: 1,234 - Total Size: 45 MB - Average Access Time: 125 μs - Evictions: 23 - Expired Entries: 12 - Efficiency Score: 0.92

Best Practices

1. Configuration Optimization

  • Memory-constrained environments: Use smaller cache sizes and enable compression
  • High-performance requirements: Use larger cache sizes and disable compression
  • Long-running processes: Enable persistent caching
  • Short-lived processes: Use in-memory caching only

2. Cache Warming

  • Development environments: Use WarmingStrategy::FrequentAccess
  • Production environments: Use WarmingStrategy::DependencyBased
  • CI/CD pipelines: Use WarmingStrategy::AccessPattern

3. Invalidation Strategy Selection

  • Read-heavy workloads: Use InvalidationStrategy::Lru
  • Write-heavy workloads: Use InvalidationStrategy::TimeBased
  • Mixed workloads: Use InvalidationStrategy::Hybrid
  • Memory-constrained: Use InvalidationStrategy::SizeBased

4. Monitoring and Maintenance

  • Regularly monitor cache statistics
  • Adjust configuration based on usage patterns
  • Clear caches periodically to prevent stale data
  • Use cache optimization features

Error Handling

The cache system provides comprehensive error handling:

use rhema::lock::get_global_cache; match get_global_cache() { Ok(cache) => { // Use cache let result = cache.get_lock_file(repo_path)?; } Err(RhemaError::CacheError(msg)) => { // Handle cache-specific errors eprintln!("Cache error: {}", msg); } Err(e) => { // Handle other errors eprintln!("Error: {}", e); } }

Testing

The cache system includes comprehensive tests:

# Run cache integration tests cargo test cache_integration_test # Run specific cache tests cargo test test_cache_initialization cargo test test_cache_operations cargo test test_cache_invalidation_strategies

Troubleshooting

Common Issues

  1. Cache Not Working

    • Ensure cache is initialized: LockSystem::initialize()?
    • Check cache configuration
    • Verify cache directory permissions
  2. Low Hit Rate

    • Increase cache size
    • Adjust TTL settings
    • Enable cache warming
    • Review invalidation strategy
  3. High Memory Usage

    • Reduce cache size
    • Enable compression
    • Use persistent caching
    • Adjust cleanup interval
  4. Slow Performance

    • Check cache statistics
    • Optimize cache configuration
    • Enable cache warming
    • Review access patterns

Debug Information

Enable debug logging to troubleshoot cache issues:

use log::LevelFilter; // Set log level to debug env_logger::Builder::new() .filter_level(LevelFilter::Debug) .init();

Conclusion

The Lock File Cache System provides a robust, high-performance caching solution for Rhema’s lock file operations. With its flexible configuration options, multiple invalidation strategies, and comprehensive monitoring capabilities, it significantly improves performance for read-heavy workloads while maintaining data integrity and providing persistent storage options.

The system integrates seamlessly with the existing lock file infrastructure and provides both automatic and manual caching capabilities, making it suitable for a wide range of use cases from development environments to production systems.

Last updated on