Add an optional in-memory cache with a configurable TTL to the Docker client wrapper, preventing redundant API calls during rapid refreshes or simultaneous section refreshes.
Current State
- Every refresh hits the Docker API with no caching
ctrl+r (global refresh) triggers all 4 sections to refresh simultaneously, causing 4+ parallel API calls
- The auto-refresh interval can be set as low as desired, potentially hammering the daemon
Proposed Approach
1. Create a caching wrapper
In internal/client/cached_client.go, create a CachedClient that wraps a real Client:
type CachedClient struct {
inner Client
ttl time.Duration
cache map[string]cacheEntry
mu sync.RWMutex
}
type cacheEntry struct {
value any
expiresAt time.Time
}
2. Cache list responses
Cache responses for ListContainers, ListImages, ListVolumes, ListNetworks with the configured TTL. Cache key = method name + serialized options.
3. Bypass cache for mutations
All write operations (start, stop, delete, create, etc.) bypass the cache and also invalidate the relevant cache keys so the next read gets fresh data.
4. Make it configurable
In internal/config/config.go, add:
[cache]
enabled = true
ttl = "1s"
5. Wire into app startup
In cmd/docker-dash/main.go, wrap the real client with CachedClient if caching is enabled in config.
Acceptance Criteria
Add an optional in-memory cache with a configurable TTL to the Docker client wrapper, preventing redundant API calls during rapid refreshes or simultaneous section refreshes.
Current State
ctrl+r(global refresh) triggers all 4 sections to refresh simultaneously, causing 4+ parallel API callsProposed Approach
1. Create a caching wrapper
In
internal/client/cached_client.go, create aCachedClientthat wraps a realClient:2. Cache list responses
Cache responses for
ListContainers,ListImages,ListVolumes,ListNetworkswith the configured TTL. Cache key = method name + serialized options.3. Bypass cache for mutations
All write operations (start, stop, delete, create, etc.) bypass the cache and also invalidate the relevant cache keys so the next read gets fresh data.
4. Make it configurable
In
internal/config/config.go, add:5. Wire into app startup
In
cmd/docker-dash/main.go, wrap the real client withCachedClientif caching is enabled in config.Acceptance Criteria
config.tomlmake test-race) pass