97 lines
3.2 KiB
Python
97 lines
3.2 KiB
Python
"""
|
|
快取輔助函數
|
|
用於提升應用程式效能
|
|
"""
|
|
from functools import wraps
|
|
from flask import request, current_app
|
|
from app import cache
|
|
import hashlib
|
|
import json
|
|
|
|
def cache_key(*args, **kwargs):
|
|
"""生成快取鍵值"""
|
|
key_data = {
|
|
'args': args,
|
|
'kwargs': kwargs,
|
|
'user_id': getattr(request, 'user_id', 'anonymous'),
|
|
'path': request.path if hasattr(request, 'path') else ''
|
|
}
|
|
key_string = json.dumps(key_data, sort_keys=True, default=str)
|
|
return hashlib.md5(key_string.encode('utf-8')).hexdigest()
|
|
|
|
def cached_route(timeout=300):
|
|
"""路由快取裝飾器"""
|
|
def decorator(f):
|
|
@wraps(f)
|
|
def decorated_function(*args, **kwargs):
|
|
if not current_app.config.get('CACHE_TYPE') or current_app.debug:
|
|
return f(*args, **kwargs)
|
|
|
|
key = f"route:{f.__name__}:{cache_key(*args, **kwargs)}"
|
|
|
|
# 嘗試從快取獲取
|
|
cached_result = cache.get(key)
|
|
if cached_result is not None:
|
|
current_app.logger.debug(f"快取命中: {key}")
|
|
return cached_result
|
|
|
|
# 執行函數並快取結果
|
|
result = f(*args, **kwargs)
|
|
cache.set(key, result, timeout=timeout)
|
|
current_app.logger.debug(f"快取設定: {key}")
|
|
|
|
return result
|
|
return decorated_function
|
|
return decorator
|
|
|
|
def cached_query(timeout=300):
|
|
"""資料庫查詢快取裝飾器"""
|
|
def decorator(f):
|
|
@wraps(f)
|
|
def decorated_function(*args, **kwargs):
|
|
if not current_app.config.get('CACHE_TYPE') or current_app.debug:
|
|
return f(*args, **kwargs)
|
|
|
|
key = f"query:{f.__name__}:{cache_key(*args, **kwargs)}"
|
|
|
|
# 嘗試從快取獲取
|
|
cached_result = cache.get(key)
|
|
if cached_result is not None:
|
|
current_app.logger.debug(f"查詢快取命中: {key}")
|
|
return cached_result
|
|
|
|
# 執行查詢並快取結果
|
|
result = f(*args, **kwargs)
|
|
cache.set(key, result, timeout=timeout)
|
|
current_app.logger.debug(f"查詢快取設定: {key}")
|
|
|
|
return result
|
|
return decorated_function
|
|
return decorator
|
|
|
|
def invalidate_cache(pattern):
|
|
"""清除快取"""
|
|
try:
|
|
if hasattr(cache, 'delete_many'):
|
|
# Redis backend
|
|
keys = cache.cache._read_clients.keys(f"flask_cache_{pattern}*")
|
|
if keys:
|
|
cache.delete_many(*keys)
|
|
current_app.logger.info(f"清除快取: {len(keys)} 個項目")
|
|
else:
|
|
# Simple cache backend
|
|
cache.clear()
|
|
current_app.logger.info("清除所有快取")
|
|
except Exception as e:
|
|
current_app.logger.error(f"清除快取失敗: {e}")
|
|
|
|
# 快取統計
|
|
def cache_stats():
|
|
"""獲取快取統計資訊"""
|
|
try:
|
|
if hasattr(cache.cache, 'info'):
|
|
return cache.cache.info()
|
|
else:
|
|
return {"status": "simple cache", "info": "無統計資訊"}
|
|
except Exception as e:
|
|
return {"error": str(e)} |