mirror of
https://github.com/sstent/AICycling_mcp.git
synced 2026-01-26 17:11:37 +00:00
restrcuted repo
This commit is contained in:
147
core/cache_manager.py
Normal file
147
core/cache_manager.py
Normal file
@@ -0,0 +1,147 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Cache Manager - Handles caching of MCP responses and other data
|
||||
"""
|
||||
|
||||
import time
|
||||
import logging
|
||||
from typing import Any, Dict, Optional, List
|
||||
from dataclasses import dataclass
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@dataclass
|
||||
class CacheEntry:
|
||||
"""Cache entry with TTL"""
|
||||
data: Any
|
||||
timestamp: float
|
||||
ttl: int # Time to live in seconds
|
||||
|
||||
class CacheManager:
|
||||
"""Manages caching of data with TTL support"""
|
||||
|
||||
def __init__(self, default_ttl: int = 300):
|
||||
self.default_ttl = default_ttl
|
||||
self._cache: Dict[str, CacheEntry] = {}
|
||||
|
||||
def set(self, key: str, data: Any, ttl: Optional[int] = None) -> None:
|
||||
"""Set cache entry with TTL"""
|
||||
ttl = ttl or self.default_ttl
|
||||
self._cache[key] = CacheEntry(
|
||||
data=data,
|
||||
timestamp=time.time(),
|
||||
ttl=ttl
|
||||
)
|
||||
logger.debug(f"Cached data for key '{key}' with TTL {ttl}s")
|
||||
|
||||
def get(self, key: str, default: Any = None) -> Any:
|
||||
"""Get cache entry, return default if expired or missing"""
|
||||
if key not in self._cache:
|
||||
logger.debug(f"Cache miss for key '{key}'")
|
||||
return default
|
||||
|
||||
entry = self._cache[key]
|
||||
|
||||
# Check if expired
|
||||
if time.time() - entry.timestamp > entry.ttl:
|
||||
logger.debug(f"Cache expired for key '{key}'")
|
||||
del self._cache[key]
|
||||
return default
|
||||
|
||||
logger.debug(f"Cache hit for key '{key}'")
|
||||
return entry.data
|
||||
|
||||
def has(self, key: str) -> bool:
|
||||
"""Check if key exists and is not expired"""
|
||||
return self.get(key) is not None
|
||||
|
||||
def delete(self, key: str) -> bool:
|
||||
"""Delete cache entry"""
|
||||
if key in self._cache:
|
||||
del self._cache[key]
|
||||
logger.debug(f"Deleted cache entry for key '{key}'")
|
||||
return True
|
||||
return False
|
||||
|
||||
def clear(self) -> None:
|
||||
"""Clear all cache entries"""
|
||||
count = len(self._cache)
|
||||
self._cache.clear()
|
||||
logger.debug(f"Cleared {count} cache entries")
|
||||
|
||||
def cleanup_expired(self) -> int:
|
||||
"""Remove expired cache entries and return count removed"""
|
||||
current_time = time.time()
|
||||
expired_keys = [
|
||||
key for key, entry in self._cache.items()
|
||||
if current_time - entry.timestamp > entry.ttl
|
||||
]
|
||||
|
||||
for key in expired_keys:
|
||||
del self._cache[key]
|
||||
|
||||
if expired_keys:
|
||||
logger.debug(f"Cleaned up {len(expired_keys)} expired cache entries")
|
||||
|
||||
return len(expired_keys)
|
||||
|
||||
def get_all(self) -> Dict[str, Any]:
|
||||
"""Get all non-expired cache entries"""
|
||||
self.cleanup_expired()
|
||||
return {key: entry.data for key, entry in self._cache.items()}
|
||||
|
||||
def get_stats(self) -> Dict[str, Any]:
|
||||
"""Get cache statistics"""
|
||||
self.cleanup_expired()
|
||||
return {
|
||||
"total_entries": len(self._cache),
|
||||
"keys": list(self._cache.keys()),
|
||||
"memory_usage_estimate": sum(
|
||||
len(str(entry.data)) for entry in self._cache.values()
|
||||
)
|
||||
}
|
||||
|
||||
def set_multiple(self, data: Dict[str, Any], ttl: Optional[int] = None) -> None:
|
||||
"""Set multiple cache entries at once"""
|
||||
for key, value in data.items():
|
||||
self.set(key, value, ttl)
|
||||
|
||||
def get_multiple(self, keys: List[str]) -> Dict[str, Any]:
|
||||
"""Get multiple cache entries at once"""
|
||||
return {key: self.get(key) for key in keys}
|
||||
|
||||
# Specialized cache for common cycling data patterns
|
||||
class CyclingDataCache(CacheManager):
|
||||
"""Specialized cache for cycling data with helper methods"""
|
||||
|
||||
def cache_user_profile(self, profile_data: Dict[str, Any]) -> None:
|
||||
"""Cache user profile data"""
|
||||
self.set("user_profile", profile_data, ttl=3600) # 1 hour TTL
|
||||
|
||||
def cache_activities(self, activities: List[Dict[str, Any]]) -> None:
|
||||
"""Cache activities list"""
|
||||
self.set("recent_activities", activities, ttl=900) # 15 minutes TTL
|
||||
|
||||
def cache_activity_details(self, activity_id: str, details: Dict[str, Any]) -> None:
|
||||
"""Cache specific activity details"""
|
||||
self.set(f"activity_details_{activity_id}", details, ttl=3600)
|
||||
|
||||
def get_user_profile(self) -> Optional[Dict[str, Any]]:
|
||||
"""Get cached user profile"""
|
||||
return self.get("user_profile")
|
||||
|
||||
def get_recent_activities(self) -> List[Dict[str, Any]]:
|
||||
"""Get cached recent activities"""
|
||||
return self.get("recent_activities", [])
|
||||
|
||||
def get_activity_details(self, activity_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get cached activity details"""
|
||||
return self.get(f"activity_details_{activity_id}")
|
||||
|
||||
def cache_workout_analysis(self, workout_id: str, analysis: str) -> None:
|
||||
"""Cache workout analysis results"""
|
||||
self.set(f"analysis_{workout_id}", analysis, ttl=86400) # 24 hours TTL
|
||||
|
||||
def get_workout_analysis(self, workout_id: str) -> Optional[str]:
|
||||
"""Get cached workout analysis"""
|
||||
return self.get(f"analysis_{workout_id}")
|
||||
Reference in New Issue
Block a user