Caching Layer
Relevant source files
The following files were used as context for generating this wiki page:
The Caching Layer in Loco provides a unified interface for temporary data storage and retrieval, aiming to improve application performance by reducing the need for expensive data operations. It supports multiple backend drivers, allowing developers to switch between in-memory storage for local development or small-scale needs and Redis for distributed, production-grade environments.
This layer is integrated into the AppContext, making it globally accessible to controllers and background workers. It also participates in the application's health monitoring system, ensuring that the cache backend is reachable during readiness checks.
Sources: src/controller/monitoring.rs:48-77, tests/controller/middlewares.rs:46-55
Architecture and Drivers
Loco utilizes a driver-based architecture for caching. The system abstracts specific implementation details behind a common set of operations, such as ping for connectivity checks and standard key-value manipulations.
Supported Drivers
| Driver | Description | Configuration Options |
|---|---|---|
| In-Memory | Stores data in the local process memory. Best for development or single-instance apps. | max_capacity |
| Redis | Uses a Redis server for storage. Required for distributed systems and multi-instance deployments. | uri, max_size |
| Null | A no-op driver that effectively disables caching. | N/A |
Sources: src/controller/monitoring.rs:56-76, src/cache/drivers/redis.rs, src/cache/drivers/inmem.rs
Driver Initialization
Drivers are instantiated based on the CacheConfig defined in the application configuration. In tests, drivers are often created and manually assigned to the AppContext to verify specific behavior.
// Example: Initializing Redis Driver in tests
let redis_cache = cache::drivers::redis::new(&config::RedisCacheConfig {
uri: redis_url,
max_size: 10,
})
.await
.expect("Failed to create Redis cache");
ctx.cache = redis_cache.into();
Sources: src/controller/monitoring.rs:198-204, src/cache/drivers/inmem.rs
Monitoring and Readiness
The Caching Layer is a critical component of the application's readiness check. The readiness endpoint probes the cache driver to ensure the application is fully prepared to handle traffic.
The diagram shows how the readiness logic iterates through infrastructure components, specifically branching based on the configured cache driver.
Sources: src/controller/monitoring.rs:48-77
Integration with Middleware
Caching concepts are also applied at the HTTP layer through specialized middleware. While distinct from the general key-value cache store, these middlewares use caching strategies to optimize web responses.
ETag Middleware
The ETag (Entity Tag) middleware allows the server to determine if the client's cached version of a resource is still valid. If the if-none-match header matches the generated ETag, the server returns a 304 Not Modified status, saving bandwidth.
Static Assets Caching
When serving static assets, Loco supports Cache-Control headers and precompressed files (e.g., Brotli or Gzip) to leverage browser-side caching.
| Feature | Description | File Path |
|---|---|---|
| Cache-Control | Configurable headers for browser caching durations. | tests/controller/middlewares.rs:252 |
| Precompression | Ability to serve .gz or .br files if they exist. | tests/controller/middlewares.rs:251 |
Sources: tests/controller/middlewares.rs:242-255
Implementation Details
Redis Driver Implementation
The Redis driver manages a connection pool to the Redis server. Its primary responsibility is translating Loco cache commands into Redis protocol commands. It is enabled via the cache_redis feature flag.
Sources: src/cache/drivers/redis.rs, src/controller/monitoring.rs:66-73
In-Memory Driver Implementation
The in-memory driver uses a synchronized data structure (typically protected by a Mutex or similar) to store values within the application's heap. It is enabled via the cache_inmem feature flag.
Sources: src/cache/drivers/inmem.rs, src/controller/monitoring.rs:57-64
Summary
The Caching Layer provides a flexible and monitored approach to data persistence and performance optimization. By supporting both in-memory and Redis backends, it accommodates various deployment scales while maintaining a consistent API. Its integration into the readiness checks ensures that the application does not report health until its cache dependencies are fully operational.
Sources: src/controller/monitoring.rs:48-77, tests/controller/middlewares.rs:46-73