v1.9.2 缓存默认时效改为7天 + 支持-1永久缓存 + 重试间隔默认15秒
1) 缓存时效: 默认 ttl_seconds 3600→604800(7天); ttl_seconds=-1 表示永久有效(不按时间过滤, 历史有成功记录就一直命中), 全局配置与 per-request cache_ttl_seconds 均支持 2) 重试间隔: 默认 delay_seconds 2→15秒 3) 前端: 徽章/弹窗显示7天或永久(fmtTtl), 有效期输入框支持-1, 保存换算-1原样存储, API文档同步(-1=永久说明) 验证: 7天TTL命中今日记录 / ttl=-1命中超7天旧记录(0.0098s返回PNG, 源站已挂仍可用) / 恢复默认
This commit is contained in:
@@ -260,10 +260,10 @@ def save_smart_config(cfg):
|
||||
|
||||
|
||||
# ===== 网址缓存 + 失败重试 配置 =====
|
||||
# cache: enabled=是否启用网址缓存(命中直接返回历史, 不重新提取); ttl_seconds=缓存有效期(秒)
|
||||
# retry: max_retries=提取失败后的重试次数(默认2, 即最多尝试3次); delay_seconds=每次重试间隔(秒)
|
||||
DEFAULT_CACHE_CONFIG = {"enabled": True, "ttl_seconds": 3600}
|
||||
DEFAULT_RETRY_CONFIG = {"max_retries": 2, "delay_seconds": 2}
|
||||
# cache: enabled=是否启用网址缓存(命中直接返回历史, 不重新提取); ttl_seconds=缓存有效期(秒, 默认7天, -1=永久有效)
|
||||
# retry: max_retries=提取失败后的重试次数(默认2, 即最多尝试3次); delay_seconds=每次重试间隔(秒, 默认15)
|
||||
DEFAULT_CACHE_CONFIG = {"enabled": True, "ttl_seconds": 7 * 24 * 3600} # 7天
|
||||
DEFAULT_RETRY_CONFIG = {"max_retries": 2, "delay_seconds": 15}
|
||||
|
||||
|
||||
def load_capture_settings():
|
||||
@@ -310,17 +310,28 @@ def save_capture_settings(settings):
|
||||
def find_cache_hit(url, action, ttl_seconds):
|
||||
"""
|
||||
按 url+action 在提取历史中查缓存:取最近一条成功记录,且创建时间在 TTL 内。
|
||||
ttl_seconds < 0 表示永久有效(不按时间过滤)。
|
||||
命中返回 dict(记录),未命中返回 None。
|
||||
"""
|
||||
from datetime import timedelta
|
||||
cutoff = (datetime.now() - timedelta(seconds=max(1, int(ttl_seconds)))).strftime("%Y-%m-%d %H:%M:%S")
|
||||
conn = get_db()
|
||||
row = conn.execute(
|
||||
"SELECT id, url, title, backend, file_path, content, html_path, created_at FROM captures "
|
||||
"WHERE url=? AND action=? AND status='success' AND created_at >= ? "
|
||||
"ORDER BY id DESC LIMIT 1",
|
||||
(url, action, cutoff)
|
||||
).fetchone()
|
||||
ttl = int(ttl_seconds)
|
||||
if ttl < 0:
|
||||
# 永久有效
|
||||
row = conn.execute(
|
||||
"SELECT id, url, title, backend, file_path, content, html_path, created_at FROM captures "
|
||||
"WHERE url=? AND action=? AND status='success' "
|
||||
"ORDER BY id DESC LIMIT 1",
|
||||
(url, action)
|
||||
).fetchone()
|
||||
else:
|
||||
from datetime import timedelta
|
||||
cutoff = (datetime.now() - timedelta(seconds=max(1, ttl))).strftime("%Y-%m-%d %H:%M:%S")
|
||||
row = conn.execute(
|
||||
"SELECT id, url, title, backend, file_path, content, html_path, created_at FROM captures "
|
||||
"WHERE url=? AND action=? AND status='success' AND created_at >= ? "
|
||||
"ORDER BY id DESC LIMIT 1",
|
||||
(url, action, cutoff)
|
||||
).fetchone()
|
||||
conn.close()
|
||||
return dict(row) if row else None
|
||||
|
||||
@@ -1585,7 +1596,7 @@ def capture():
|
||||
"action": "screenshot" | "html" | "text" | "smart",
|
||||
"refresh": false, // 可选:true=强制实时提取(绕过网址缓存)
|
||||
"cache": true, // 可选:false=本次请求禁用缓存
|
||||
"cache_ttl_seconds": 3600, // 可选:本次请求的缓存时效(秒),覆盖全局设置;命中判定也用它
|
||||
"cache_ttl_seconds": 604800, // 可选:本次请求的缓存时效(秒, -1=永久),覆盖全局设置;命中判定也用它
|
||||
"scroll_times": 0,
|
||||
"scroll_delay": 1000,
|
||||
"full_page": false,
|
||||
@@ -1639,10 +1650,11 @@ def capture():
|
||||
cache_cfg = settings.get("cache", DEFAULT_CACHE_CONFIG)
|
||||
retry_cfg = settings.get("retry", DEFAULT_RETRY_CONFIG)
|
||||
force_refresh = bool(data.get("refresh") or data.get("force"))
|
||||
# per-request 缓存参数:cache_ttl_seconds=本次缓存时效(覆盖全局),cache=false / no_cache=true=本次禁用缓存
|
||||
# per-request 缓存参数:cache_ttl_seconds=本次缓存时效(秒, -1=永久, 覆盖全局),cache=false / no_cache=true=本次禁用缓存
|
||||
no_cache = data.get("cache") is False or str(data.get("no_cache")).lower() in ("true", "1", "yes")
|
||||
try:
|
||||
cache_ttl_override = max(1, int(data.get("cache_ttl_seconds"))) if data.get("cache_ttl_seconds") is not None else None
|
||||
v = int(data.get("cache_ttl_seconds"))
|
||||
cache_ttl_override = v if v != 0 else None
|
||||
except Exception:
|
||||
cache_ttl_override = None
|
||||
|
||||
|
||||
Reference in New Issue
Block a user