Cache Manager
Overview
The CacheManager provides centralized resource caching for OpenStack resources, backed by the MemoryKit framework. It serves as the interface layer between the TUI and the underlying MemoryKit-backed storage, providing computed property accessors and cache invalidation for all resource types.
Location: Sources/Substation/Framework/CacheManager.swift
Architecture
graph TB
subgraph TUI["TUI Layer"]
VC[ViewCoordinator]
DM[DataManager]
Modules[Module Views]
end
subgraph Framework["Framework Layer"]
CM[CacheManager]
RNC[ResourceNameCache]
end
subgraph MemoryKit["MemoryKit Layer"]
SMC[SubstationMemoryContainer]
ORC[OpenStackResourceCache]
end
VC --> CM
DM --> CM
Modules --> CM
CM --> SMC
CM --> RNC
SMC --> ORC
Class Definition
@MainActor
final class CacheManager {
// Dependencies
private let memoryContainer: SubstationMemoryContainer
internal var resourceCache: OpenStackResourceCache
internal let resourceNameCache: ResourceNameCache
internal weak var swiftNavState: SwiftNavigationState?
// Initialization
init(memoryContainer: SubstationMemoryContainer, resourceNameCache: ResourceNameCache)
}
Cached Resource Types
Compute Resources
| Property |
Type |
Service |
cachedServers |
[Server] |
Nova |
cachedServerGroups |
[ServerGroup] |
Nova |
cachedFlavors |
[Flavor] |
Nova |
cachedKeyPairs |
[KeyPair] |
Nova |
cachedAvailabilityZones |
[String] |
Nova |
cachedHypervisors |
[Hypervisor] |
Nova |
cachedComputeServices |
[ComputeService] |
Nova |
Network Resources
| Property |
Type |
Service |
cachedNetworks |
[Network] |
Neutron |
cachedPorts |
[Port] |
Neutron |
cachedRouters |
[Router] |
Neutron |
cachedFloatingIPs |
[FloatingIP] |
Neutron |
cachedSubnets |
[Subnet] |
Neutron |
cachedSecurityGroups |
[SecurityGroup] |
Neutron |
cachedQoSPolicies |
[QoSPolicy] |
Neutron |
Block Storage Resources
| Property |
Type |
Service |
cachedVolumes |
[Volume] |
Cinder |
cachedVolumeTypes |
[VolumeType] |
Cinder |
cachedVolumeSnapshots |
[VolumeSnapshot] |
Cinder |
cachedVolumeBackups |
[VolumeBackup] |
Cinder |
Image Resources
| Property |
Type |
Service |
cachedImages |
[Image] |
Glance |
Key Management Resources
| Property |
Type |
Service |
cachedSecrets |
[Secret] |
Barbican |
Container Infrastructure Resources
| Property |
Type |
Service |
cachedClusters |
[Cluster] |
Magnum |
cachedClusterTemplates |
[ClusterTemplate] |
Magnum |
cachedNodegroups |
[Nodegroup] |
Magnum |
Object Storage Resources
| Property |
Type |
Service |
cachedSwiftContainers |
[SwiftContainer] |
Swift |
cachedSwiftObjects |
[SwiftObject]? |
Swift |
Quota Data
| Property |
Type |
Service |
cachedComputeQuotas |
ComputeQuotaSet? |
Nova |
cachedNetworkQuotas |
NetworkQuotaSet? |
Neutron |
cachedVolumeQuotas |
VolumeQuotaSet? |
Cinder |
cachedComputeLimits |
ComputeQuotaSet? |
Nova |
Cache Flow
sequenceDiagram
participant View as View/Module
participant CM as CacheManager
participant ORC as OpenStackResourceCache
participant MK as MemoryKit
View->>CM: Read cachedServers
CM->>ORC: resourceCache.servers
ORC->>MK: Get from cache
MK-->>ORC: Cached data
ORC-->>CM: [Server]
CM-->>View: [Server]
View->>CM: Write cachedServers = newValue
CM->>ORC: Task { setServers(newValue) }
ORC->>MK: Store in cache
Swift Object Storage Methods
The CacheManager provides specialized methods for Swift object storage due to its container-based structure:
Container Cache Methods
/// Check if the container list cache is fresh
func isSwiftContainersCacheFresh(maxAge: TimeInterval = 30) -> Bool
/// Get the cache timestamp for the container list
func getSwiftContainersCacheTime() -> Date
Object Cache Methods
/// Clear cached Swift objects for a specific container
func clearSwiftObjects(forContainer containerName: String)
/// Check if the cache for a container's objects is fresh
func isSwiftObjectsCacheFresh(forContainer containerName: String, maxAge: TimeInterval = 30) -> Bool
/// Get the cache timestamp for a container's objects
func getSwiftObjectsCacheTime(forContainer containerName: String) -> Date?
/// Add objects to the cache for a container (optimistic update)
func addSwiftObjects(_ objects: [SwiftObject], forContainer containerName: String) async
/// Remove objects from the cache for a container (optimistic update)
func removeSwiftObjects(withNames objectNames: Set<String>, forContainer containerName: String) async
/// Remove a single object from the cache for a container
func removeSwiftObject(withName objectName: String, forContainer containerName: String) async
Cache Operations
Clear All Caches
/// Clear all caches - resets all cached resources to empty states
func clearAllCaches() async
Cache Statistics
/// Get cache statistics for monitoring and debugging
func getCacheStatistics() async -> OpenStackCacheStatistics
Flavor Recommendations
The CacheManager also manages flavor recommendations for workload optimization:
/// Cached flavor recommendations for all workload types
var cachedFlavorRecommendations: [WorkloadType: [FlavorRecommendation]]
/// Timestamp of last recommendations refresh
var lastRecommendationsRefresh: Date
Usage Examples
Reading Cached Resources
// Access cached servers
let servers = cacheManager.cachedServers
// Access cached networks
let networks = cacheManager.cachedNetworks
// Check Swift container cache freshness
if cacheManager.isSwiftContainersCacheFresh(maxAge: 60) {
// Use cached data
} else {
// Refresh from API
}
Writing to Cache
// Update cached servers
cacheManager.cachedServers = newServers
// Clear Swift objects after deletion
await cacheManager.removeSwiftObject(withName: "deleted-file.txt", forContainer: "my-container")
Cache Statistics
let stats = await cacheManager.getCacheStatistics()
print("Total cached resources: \(stats.totalItems)")
Thread Safety
The CacheManager is marked with @MainActor to ensure thread-safe access from the TUI. All write operations to the underlying cache are performed asynchronously using Task blocks to prevent blocking the main thread.
L3 Disk Cache and Cloud-Specific Storage
The underlying MemoryKit multi-level cache stores persistent data on disk (L3 tier) in cloud-specific directories:
~/.config/substation/multi-level-cache/<cloudName>/
Key Features
- Cloud Isolation: Each OpenStack cloud has its own cache directory, preventing data mixing between clouds
- Consistent Filenames: Cache files use hash-based naming (
cache_<hash>.dat) for deterministic caching across restarts
- Automatic Cleanup: Stale cache files (older than 8 hours) are automatically removed at application startup
Cache File Lifecycle
graph LR
Start[App Start] --> Cleanup[Cleanup stale files > 8h]
Cleanup --> Load[Load L3 index]
Load --> Use[Cache operations]
Use --> Promote[Promote hot data to L1/L2]
Use --> Demote[Demote cold data to L3]
For detailed information about the multi-level cache implementation, see MemoryKit API Reference.
Dependencies
- SubstationMemoryContainer: Provides the MemoryKit integration
- OpenStackResourceCache: The underlying cache storage
- ResourceNameCache: Cache for resource display name lookups
- SwiftNavigationState: Reference for container-specific object caching