Cache Controller Functionality and Supported Backends in Music Assistant
The Cache Controller provides an expiration-aware key/value store using SQLite as its sole supported backend, offering namespaced storage, stale-while-revalidate patterns, and automatic database cleanup for the Music Assistant application.
The music-assistant/server repository implements a centralized Cache Controller at music_assistant/controllers/cache/controller.py to manage temporary data across all music providers. This component serves as the primary caching layer, handling API responses, metadata storage, and provider-specific data with configurable expiration policies and checksum validation.
How the Cache Controller Works
Persistent Storage with SQLite
The controller persists all cache entries in an SQLite database file located at $HOME/.musicassistant/cache.db. It leverages the DatabaseConnection helper from music_assistant/helpers/database.py to execute async operations against this single database file, providing durability across application restarts.
Namespacing by Provider and Category
Every cache entry is scoped by provider and category parameters. This isolation prevents collisions between different music providers (e.g., Spotify, YouTube Music) while allowing each service to maintain its own cached data namespaces within the shared database.
Expiration and Stale-While-Revalidate
Each entry stores an expires timestamp upon creation. The get method supports an allow_expired_cache=True parameter that returns expired entries when fresh data is unavailable. This stale-while-revalidate pattern, utilized by the @use_cache decorator, allows the application to serve cached data while triggering background refresh operations.
Checksum Validation
The controller supports optional checksum validation through the checksum parameter in the set method. When retrieving data via get, the controller verifies that the stored checksum matches the requested value, ensuring data integrity for critical cached responses.
Persistence Flag
When setting cache entries with persistent=True, the data survives normal clear operations. This flag protects essential cached data during user-initiated cache clears while allowing routine cleanup of transient entries.
Bypass Support
A BYPASS_CACHE context variable enables temporary cache disablement for specific requests. This mechanism supports debugging scenarios and forced refresh operations without modifying the underlying cached data.
Automatic Cleanup
The controller registers a daily background task identified by CACHE_DATABASE_CLEANUP_TASK_ID that removes expired rows not marked with allow_expired_cache. It also monitors the total database size against MAX_CACHE_DB_SIZE_MB and emits warnings when the cache database exceeds configured thresholds.
Supported Caching Backends
SQLite as the Sole Backend
The Cache Controller currently supports only one backend: an SQLite database. While the architecture abstracts database operations through DatabaseConnection, no alternative storage engines such as Redis, in-memory dictionaries, or file-based JSON are implemented in the repository.
All cache operations—including insert_or_replace, get_row, delete, and execute—target the single SQLite file. Features like "persistent" entries and "allow_expired_cache" operate within this same physical database, using schema flags rather than separate storage backends.
Implementation Files and Architecture
Core Controller Implementation
The file music_assistant/controllers/cache/controller.py contains the full implementation including initialization, CRUD operations, cleanup logic, and background task registration. This class inherits from the base controller defined in music_assistant/models/core_controller.py, which provides manifest handling and lifecycle hooks.
Database Abstraction Layer
Located at music_assistant/helpers/database.py, this module provides a minimal wrapper around aiosqlite that exposes async database operations used exclusively by the cache controller for SQLite interactions.
Configuration Constants
The file music_assistant/controllers/cache/constants.py defines schema versions, default expiration intervals, and the MAX_CACHE_DB_SIZE_MB threshold utilized by the cleanup routines.
Practical Usage Examples
The following patterns demonstrate typical Cache Controller interactions from provider implementations:
# Store API response with 2-hour expiration
await mass.cache.set(
key="album_details:12345",
data={"title": "Great Album", "artist": "Cool Band"},
expiration=2 * 60 * 60,
provider="spotify",
category=0,
persistent=False,
)
# Retrieve cached data with fallback default
album = await mass.cache.get(
key="album_details:12345",
provider="spotify",
category=0,
default=None,
)
# Clear non-persistent entries for specific provider
await mass.cache.clear(provider_filter="spotify", include_persistent=False)
# Bypass cache for forced refresh
async with mass.cache.handle_refresh(bypass=True):
fresh_data = await some_api_call()
Summary
- The Cache Controller in
music_assistant/controllers/cache/controller.pyprovides the core caching infrastructure for the Music Assistant application using SQLite as its only supported backend. - It implements namespacing via provider and category parameters to isolate data between different music services.
- Expiration-aware storage supports stale-while-revalidate patterns through
allow_expired_cacheand includes checksum validation for data integrity. - The persistence flag protects critical data from routine cache clears, while the bypass mechanism enables debugging and forced refreshes.
- Automatic maintenance includes daily cleanup of expired entries and database size monitoring against
MAX_CACHE_DB_SIZE_MB.
Frequently Asked Questions
What caching backends does the Cache Controller support?
The Cache Controller supports only SQLite as its caching backend, storing data in $HOME/.musicassistant/cache.db. While the code abstracts database operations through DatabaseConnection, no Redis, Memcached, or in-memory alternatives are implemented in the current codebase.
How does the stale-while-revalidate pattern work?
When allow_expired_cache=True is passed to the get method, the controller returns expired entries if present, allowing the application to serve stale data while triggering background refresh operations. This pattern is primarily utilized through the @use_cache decorator.
Where is the cache physically stored on disk?
All cache data resides in an SQLite database file located at $HOME/.musicassistant/cache.db. This includes both persistent and non-persistent entries, with differentiation handled via database flags rather than separate files.
How can developers bypass the cache for debugging?
Developers can use the BYPASS_CACHE context variable through the handle_refresh context manager with bypass=True. This temporarily disables cache reads for the scope of the request without deleting existing cached data, enabling forced API refreshes during debugging.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →