116 lines
4.3 KiB
Python
116 lines
4.3 KiB
Python
import json
|
|
import os
|
|
import time
|
|
from datetime import datetime, timedelta
|
|
import threading
|
|
import queue
|
|
|
|
class PredictionCache:
|
|
_instance = None
|
|
_lock = threading.Lock()
|
|
|
|
def __new__(cls):
|
|
with cls._lock:
|
|
if cls._instance is None:
|
|
cls._instance = super(PredictionCache, cls).__new__(cls)
|
|
return cls._instance
|
|
|
|
def __init__(self):
|
|
if not hasattr(self, 'initialized'):
|
|
self.cache_dir = 'cache/predictions'
|
|
self.cache_duration = timedelta(hours=24) # 缓存24小时
|
|
self.cache = {}
|
|
self.cache_queue = queue.Queue()
|
|
self.initialized = True
|
|
|
|
# 确保缓存目录存在
|
|
os.makedirs(self.cache_dir, exist_ok=True)
|
|
|
|
# 启动缓存清理线程
|
|
self.cleanup_thread = threading.Thread(target=self._cleanup_old_cache, daemon=True)
|
|
self.cleanup_thread.start()
|
|
|
|
# 加载现有缓存
|
|
self._load_cache()
|
|
|
|
def _load_cache(self):
|
|
"""加载磁盘上的缓存文件"""
|
|
try:
|
|
for filename in os.listdir(self.cache_dir):
|
|
if filename.endswith('.json'):
|
|
filepath = os.path.join(self.cache_dir, filename)
|
|
with open(filepath, 'r', encoding='utf-8') as f:
|
|
cache_data = json.load(f)
|
|
# 检查缓存是否过期
|
|
if self._is_cache_valid(cache_data['timestamp']):
|
|
topic = filename[:-5] # 移除.json后缀
|
|
self.cache[topic] = cache_data
|
|
else:
|
|
# 删除过期缓存文件
|
|
os.remove(filepath)
|
|
except Exception as e:
|
|
print(f"加载缓存失败: {e}")
|
|
|
|
def _cleanup_old_cache(self):
|
|
"""定期清理过期缓存的后台线程"""
|
|
while True:
|
|
try:
|
|
# 检查并清理内存缓存
|
|
current_time = datetime.now()
|
|
expired_topics = []
|
|
|
|
for topic, cache_data in self.cache.items():
|
|
if not self._is_cache_valid(cache_data['timestamp']):
|
|
expired_topics.append(topic)
|
|
|
|
# 删除过期缓存
|
|
for topic in expired_topics:
|
|
del self.cache[topic]
|
|
cache_file = os.path.join(self.cache_dir, f"{topic}.json")
|
|
if os.path.exists(cache_file):
|
|
os.remove(cache_file)
|
|
|
|
# 休眠1小时后再次检查
|
|
time.sleep(3600)
|
|
except Exception as e:
|
|
print(f"清理缓存时出错: {e}")
|
|
time.sleep(3600) # 发生错误时也等待1小时
|
|
|
|
def _is_cache_valid(self, timestamp):
|
|
"""检查缓存是否有效"""
|
|
cache_time = datetime.fromtimestamp(timestamp)
|
|
return datetime.now() - cache_time < self.cache_duration
|
|
|
|
def get(self, topic):
|
|
"""获取话题的预测缓存"""
|
|
if topic in self.cache and self._is_cache_valid(self.cache[topic]['timestamp']):
|
|
return self.cache[topic]['prediction']
|
|
return None
|
|
|
|
def set(self, topic, prediction):
|
|
"""设置话题的预测缓存"""
|
|
cache_data = {
|
|
'prediction': prediction,
|
|
'timestamp': datetime.now().timestamp()
|
|
}
|
|
|
|
# 更新内存缓存
|
|
self.cache[topic] = cache_data
|
|
|
|
# 异步保存到磁盘
|
|
self.cache_queue.put((topic, cache_data))
|
|
threading.Thread(target=self._save_cache_to_disk, daemon=True).start()
|
|
|
|
def _save_cache_to_disk(self):
|
|
"""异步保存缓存到磁盘"""
|
|
try:
|
|
while not self.cache_queue.empty():
|
|
topic, cache_data = self.cache_queue.get()
|
|
cache_file = os.path.join(self.cache_dir, f"{topic}.json")
|
|
with open(cache_file, 'w', encoding='utf-8') as f:
|
|
json.dump(cache_data, f, ensure_ascii=False, indent=2)
|
|
except Exception as e:
|
|
print(f"保存缓存到磁盘失败: {e}")
|
|
|
|
# 创建全局缓存实例
|
|
prediction_cache = PredictionCache() |