| import json |
| import os |
| import time |
| from typing import Optional, Dict, Any |
|
|
|
|
| class AnswersCache: |
| def __init__(self, filename: str = "cache.json", max_size: int = 1000): |
| self.filename = filename |
| self.max_size = max_size |
| self.cache: Dict[str, Dict[str, Any]] = {} |
| self._load_cache() |
|
|
| def _load_cache(self): |
| """Load cache from file if it exists""" |
| if os.path.exists(self.filename): |
| try: |
| with open(self.filename, 'r') as f: |
| self.cache = json.load(f) |
| except (json.JSONDecodeError, FileNotFoundError): |
| self.cache = {} |
|
|
| def _save_cache(self): |
| """Save cache to file""" |
| with open(self.filename, 'w') as f: |
| json.dump(self.cache, f, indent=2) |
|
|
| def set(self, key: str, value: str, ttl: Optional[int] = None): |
| """Set a key-value pair with optional TTL (time to live in seconds)""" |
| if len(self.cache) >= self.max_size: |
| self._evict_oldest() |
|
|
| cache_entry = { |
| 'value': value, |
| 'created_at': time.time(), |
| 'ttl': ttl |
| } |
| self.cache[key] = cache_entry |
| self._save_cache() |
|
|
| def get(self, key: str) -> Optional[str]: |
| """Get value for key, returns None if not found or expired""" |
| if key not in self.cache: |
| return None |
|
|
| entry = self.cache[key] |
|
|
| |
| if entry['ttl'] is not None: |
| if time.time() - entry['created_at'] > entry['ttl']: |
| self.delete(key) |
| return None |
|
|
| return entry['value'] |
|
|
| def delete(self, key: str): |
| """Delete a key from cache""" |
| if key in self.cache: |
| del self.cache[key] |
| self._save_cache() |
|
|
| def clear(self): |
| """Clear all cache entries""" |
| self.cache = {} |
| self._save_cache() |
|
|
| def _evict_oldest(self): |
| """Remove the oldest entry when cache is full""" |
| if not self.cache: |
| return |
|
|
| oldest_key = min(self.cache.keys(), |
| key=lambda k: self.cache[k]['created_at']) |
| del self.cache[oldest_key] |