How CasaOS Implements Caching with Its Cache Package: Architecture and Usage
CasaOS implements a lightweight, thread-safe caching layer by wrapping the patrickmn/go-cache library in a singleton pattern with a 5-minute default TTL and 60-second cleanup interval.
The CasaOS cache package provides an in-process memory store for the IceWhaleTech/CasaOS repository, eliminating the need for external dependencies like Redis while offering fast temporary storage for frequently accessed data. This implementation leverages a global cache instance initialized at boot time, making it accessible across all service components through a simple API.
Cache Package Architecture and Dependencies
CasaOS does not implement a custom caching algorithm from scratch. Instead, it creates a thin abstraction over the well-established patrickmn/go-cache library to handle expiration and garbage collection.
The Wrapper Implementation in pkg/cache/cache.go
The core initialization logic resides in pkg/cache/cache.go, which imports github.com/patrickmn/go-cache and exposes a single helper function:
// pkg/cache/cache.go
import (
"github.com/patrickmn/go-cache"
"time"
)
// Init creates a global cache instance with a default
// expiration of 5 minutes and a cleanup interval of 60 seconds.
func Init() *cache.Cache {
return cache.New(5*time.Minute, 60*time.Second)
}
This function establishes the default time-to-live (TTL) of 5 minutes for all cache entries, coupled with a background cleanup routine that purges expired items every 60 seconds.
Global Cache Variable in service/service.go
To ensure the cache is accessible throughout the application without dependency injection complexity, CasaOS declares a global pointer in the service layer:
// service/service.go
import "github.com/patrickmn/go-cache"
var Cache *cache.Cache
This global variable acts as the single source of truth for all caching operations, allowing any component to read from or write to the cache directly.
Boot-Time Initialization and Configuration
The cache follows a singleton pattern established during application startup, ensuring consistent behavior across the lifespan of the CasaOS process.
Initializing the Cache in main.go
When the CasaOS application launches, the Init() function is called and the result is assigned to the global variable:
// main.go
import "github.com/IceWhaleTech/CasaOS/pkg/cache"
func main() {
// ...
service.Cache = cache.Init()
// ...
}
This initialization sequence ensures the cache is ready before any service components attempt to store or retrieve data, preventing nil pointer dereferences.
Configuring Cache Expiration in model/storage.go
While the global cache uses fixed defaults, CasaOS exposes configuration flexibility through struct definitions. The model/storage.go file includes a CacheExpiration field that allows specific storage backends to define their own TTL values:
// model/storage.go (simplified)
type Storage struct {
CacheExpiration time.Duration
// ... other fields
}
Although the global cache instance maintains its 5-minute default, individual components can override expiration times per-entry using the Set method's duration parameter.
Usage Patterns and Thread Safety
The underlying go-cache library handles all concurrency concerns with internal mutex locks, making service.Cache safe for concurrent access across goroutines without additional synchronization.
Standard Get-Set Pattern
Components interact with the cache using a straightforward check-store-retrieve flow:
package main
import (
"fmt"
"github.com/IceWhaleTech/CasaOS/pkg/cache"
"github.com/IceWhaleTech/CasaOS/service"
"time"
)
func main() {
// Initialize the global cache (normally done in main.go)
service.Cache = cache.Init()
// Store a value with a custom 2-minute expiration
service.Cache.Set("user:123", "John Doe", 2*time.Minute)
// Retrieve the value later
if v, found := service.Cache.Get("user:123"); found {
fmt.Println("Cached user:", v)
} else {
fmt.Println("Cache miss - compute and store")
}
}
Entries not explicitly assigned a TTL inherit the 5-minute default expiration established during initialization. The automatic cleanup mechanism removes expired objects every 60 seconds, preventing memory leaks from stale data.
Summary
CasaOS implements caching through a deliberate, minimalist approach:
- Single global instance: A singleton
*cache.Cachecreated at startup inmain.goand exposed viaservice.Cache - Sensible defaults: 5-minute default expiration with 60-second garbage collection cycles
- Thread-safe access: Leverages
patrickmn/go-cacheinternal mutexes for concurrent safety - Zero external dependencies: Requires no Redis or Memcached servers, reducing operational complexity
- Configurable per-entry: Supports custom TTLs via the
Setmethod while maintaining global defaults
This design prioritizes simplicity and performance for a single-node operating system deployment.
Frequently Asked Questions
How does CasaOS handle cache expiration?
CasaOS relies on the patrickmn/go-cache library's built-in expiration mechanism. When initialized in pkg/cache/cache.go, the cache uses a default expiration of 5 minutes and runs a cleanup interval of 60 seconds to automatically purge stale entries. Developers can override the TTL for individual items using the Set method's duration parameter.
Is the CasaOS cache safe for concurrent access?
Yes, the cache is fully thread-safe. The underlying go-cache library implements internal read-write mutexes (sync.RWMutex) to protect the cache map. Since CasaOS exposes a single global instance via service.Cache, multiple goroutines can safely call Get, Set, and Delete operations without implementing additional synchronization logic.
Why does CasaOS use a global variable for caching instead of dependency injection?
CasaOS opts for a global Cache variable declared in service/service.go to simplify the architecture and reduce boilerplate across the codebase. This approach eliminates the need to pass cache references through multiple layers of constructors, making it easier for various service components to access temporary storage while the application maintains a single cache instance initialized at boot time.
Can I configure the default cache TTL in CasaOS?
The default TTL of 5 minutes and cleanup interval of 60 seconds are hardcoded in the Init() function within pkg/cache/cache.go. While you cannot change these global defaults without modifying the source code, you can specify custom durations when calling service.Cache.Set("key", value, customDuration) for individual entries. The model/storage.go file also defines CacheExpiration fields for storage-specific configuration, though these require manual integration with the global cache instance.
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 →