Skip to content

HTTP 响应缓存层 #5

@Arcadia822

Description

@Arcadia822

背景

当前 IntelligenceService 的 RSS 拉取(_default_fetch)和翻译调用(_default_translate)都没有 HTTP 缓存。每次 digest run:

  1. RSS 全量重拉:即使源 5 分钟前刚拉过且内容没变,仍然完整请求并解析 XML。
  2. Translation 全量重调:同一事件标题在多次 run 中会被重复翻译(虽然 HTTP 响应缓存层 #5 提案的哈希缓存能缓解应用层问题,但 HTTP 层仍有优化空间)。
  3. 无条件请求支持:未使用 If-Modified-SinceETag 等 HTTP 条件请求头,浪费带宽。

参考实现

OpenTrends (nexmoe/opentrends) 实现了三层缓存架构:

层级 机制 TTL
L1 内存 Map<string, entry> 进程生命周期
L2 KV Cloudflare KV with CacheEnvelope<T> 7 天
L3 数据库 PostgreSQL source + sourceItem 永久

每层都支持 stale-while-revalidate:返回过期数据的同时触发后台刷新。OpenTrends 还根据源类型设置了 5 档刷新策略(hot 5min、community 10min、rss 30min、daily 12h、slow 2h)。

提案

考虑到 Skrya 是文件系统驱动的 skill pack(无数据库/无 KV),提议一个轻量级 HTTP 缓存层:

1. 缓存存储

<skrya-data-root>/cache/
  http/
    <url-hash>/
      response.xml       # 缓存的响应体
      meta.json          # 缓存元数据
{
  "url": "https://www.theverge.com/rss/ai/index.xml",
  "url_hash": "a1b2c3d4",
  "fetched_at": "2026-05-17T09:30:00+08:00",
  "etag": "W/\"abc123\"",
  "last_modified": "Sat, 17 May 2026 01:30:00 GMT",
  "content_type": "application/rss+xml",
  "status": 200,
  "ttl_seconds": 1800,
  "expires_at": "2026-05-17T10:00:00+08:00"
}

2. 缓存策略

def _cached_fetch(self, url: str, ttl: int = 1800) -> str:
    cache_key = self._url_hash(url)
    cached = self._http_cache.get(cache_key)
    
    if cached and not cached.is_expired():
        return cached.body  # L1 命中
    
    headers = {}
    if cached:
        if cached.etag:
            headers["If-None-Match"] = cached.etag
        if cached.last_modified:
            headers["If-Modified-Since"] = cached.last_modified
    
    response = self._raw_fetch(url, headers=headers)
    
    if response.status == 304 and cached:
        cached.refresh_ttl()  # 内容未变,续期
        return cached.body
    
    self._http_cache.put(cache_key, response)
    return response.body

3. TTL 分档

源类型 默认 TTL 说明
rss (热源) 30 分钟 主流新闻源
rss (温源) 2 小时 更新不频繁的专业源
rsshub 10 分钟 社区/热榜类(如果有 #1 的 RSSHub 提案)
runtime-retrieval 不缓存 每次需要实时检索
translation 7 天 翻译结果长期有效

4. 缓存清理

  • 自动清理:expires_at 过期后文件保留 24h 再删除
  • 手动清理:--clear-http-cache CLI 命令
  • 全量刷新:--force-refresh 跳过缓存直接拉取

收益

  • digest 速度提升:缓存命中时跳过网络 I/O,典型场景节省 30-60 秒
  • 减少外部请求频率:对公共 RSS 源和 RSSHub 实例更友好
  • 条件请求:利用 ETag/304 减少不必要的数据传输
  • HTTP 响应缓存层 #5 互补HTTP 响应缓存层 #5 解决翻译应用层缓存,本提案解决 HTTP 传输层缓存

优先级

— 性能优化,对频繁运行 digest 的 agent 场景收益明显。

备注

来源:agent=牛马AI, model=mimo-v2.5-pro, reference=opentrends

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions