mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-04-11 13:23:00 +00:00
Improve cache functionality. Add max_age parameter to CacheManager, fix WeatherManager API calls, and enhance error handling.
This commit is contained in:
@@ -125,13 +125,13 @@ class CacheManager:
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get_cached_data(self, key: str) -> Optional[Dict[str, Any]]:
|
def get_cached_data(self, key: str, max_age: int = 60) -> Optional[Dict[str, Any]]:
|
||||||
"""Get cached data with memory cache priority."""
|
"""Get cached data with memory cache priority and max age check."""
|
||||||
current_time = time.time()
|
current_time = time.time()
|
||||||
|
|
||||||
# Check memory cache first
|
# Check memory cache first
|
||||||
if key in self._memory_cache:
|
if key in self._memory_cache:
|
||||||
if current_time - self._memory_cache_timestamps.get(key, 0) < 60: # 1 minute TTL
|
if current_time - self._memory_cache_timestamps.get(key, 0) < max_age: # Use provided max_age
|
||||||
return self._memory_cache[key]
|
return self._memory_cache[key]
|
||||||
else:
|
else:
|
||||||
# Clear expired memory cache
|
# Clear expired memory cache
|
||||||
@@ -139,7 +139,30 @@ class CacheManager:
|
|||||||
del self._memory_cache_timestamps[key]
|
del self._memory_cache_timestamps[key]
|
||||||
|
|
||||||
# Fall back to disk cache
|
# Fall back to disk cache
|
||||||
return self.load_cache(key)
|
cache_path = self._get_cache_path(key)
|
||||||
|
if not os.path.exists(cache_path):
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
with self._cache_lock:
|
||||||
|
with open(cache_path, 'r') as f:
|
||||||
|
try:
|
||||||
|
data = json.load(f)
|
||||||
|
# Check if data is stale
|
||||||
|
if current_time - data.get('timestamp', 0) > max_age:
|
||||||
|
return None
|
||||||
|
# Update memory cache
|
||||||
|
self._memory_cache[key] = data['data']
|
||||||
|
self._memory_cache_timestamps[key] = current_time
|
||||||
|
return data['data']
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
self.logger.error(f"Error parsing cache file for {key}: {e}")
|
||||||
|
# If the file is corrupted, remove it
|
||||||
|
os.remove(cache_path)
|
||||||
|
return None
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"Error loading cache for {key}: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
def clear_cache(self, key: Optional[str] = None) -> None:
|
def clear_cache(self, key: Optional[str] = None) -> None:
|
||||||
"""Clear cache for a specific key or all keys."""
|
"""Clear cache for a specific key or all keys."""
|
||||||
|
|||||||
@@ -105,27 +105,55 @@ class WeatherManager:
|
|||||||
|
|
||||||
# Check if we need to update
|
# Check if we need to update
|
||||||
if current_time - self._last_update < self._update_interval:
|
if current_time - self._last_update < self._update_interval:
|
||||||
cached_data = self.cache_manager.get_cached_data('weather')
|
cached_data = self.cache_manager.get_cached_data('weather', max_age=self._update_interval)
|
||||||
if cached_data:
|
if cached_data:
|
||||||
self.logger.info("Using cached weather data")
|
self.logger.info("Using cached weather data")
|
||||||
return self._process_forecast_data(cached_data)
|
return self._process_forecast_data(cached_data)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Fetch new data
|
# Fetch new data from OpenWeatherMap API
|
||||||
data = self._fetch_from_api()
|
api_key = self.weather_config.get('api_key')
|
||||||
if data:
|
location = self.weather_config.get('location')
|
||||||
self._last_update = current_time
|
units = self.weather_config.get('units', 'imperial')
|
||||||
self.cache_manager.save_cache('weather', data)
|
|
||||||
return self._process_forecast_data(data)
|
# Fetch current weather
|
||||||
|
current_url = "https://api.openweathermap.org/data/2.5/weather"
|
||||||
|
params = {
|
||||||
|
"q": location,
|
||||||
|
"appid": api_key,
|
||||||
|
"units": units
|
||||||
|
}
|
||||||
|
|
||||||
|
response = requests.get(current_url, params=params, timeout=10)
|
||||||
|
response.raise_for_status()
|
||||||
|
current_data = response.json()
|
||||||
|
|
||||||
|
# Fetch forecast
|
||||||
|
forecast_url = "https://api.openweathermap.org/data/2.5/forecast"
|
||||||
|
response = requests.get(forecast_url, params=params, timeout=10)
|
||||||
|
response.raise_for_status()
|
||||||
|
forecast_data = response.json()
|
||||||
|
|
||||||
|
# Combine the data
|
||||||
|
data = {
|
||||||
|
"current": current_data,
|
||||||
|
"hourly": forecast_data.get("list", []),
|
||||||
|
"daily": [] # Daily forecast will be processed from hourly data
|
||||||
|
}
|
||||||
|
|
||||||
|
self._last_update = current_time
|
||||||
|
self.cache_manager.save_cache('weather', data)
|
||||||
|
return self._process_forecast_data(data)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"Error fetching weather data: {e}")
|
self.logger.error(f"Error fetching weather data: {e}")
|
||||||
# Try to use cached data as fallback
|
# Try to use cached data as fallback
|
||||||
cached_data = self.cache_manager.get_cached_data('weather')
|
cached_data = self.cache_manager.get_cached_data('weather', max_age=self._update_interval)
|
||||||
if cached_data:
|
if cached_data:
|
||||||
self.logger.info("Using cached weather data as fallback")
|
self.logger.info("Using cached weather data as fallback")
|
||||||
return self._process_forecast_data(cached_data)
|
return self._process_forecast_data(cached_data)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _process_current_conditions(self, current: Dict[str, Any]) -> Dict[str, Any]:
|
def _process_current_conditions(self, current: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
"""Process current conditions with minimal processing."""
|
"""Process current conditions with minimal processing."""
|
||||||
|
|||||||
Reference in New Issue
Block a user