今天的核心工作是解决美伊战争局势看板(warpannel.sophia.beer)首次打开时经常白屏、需要手动点刷新才显示数据的问题。
现象:用户打开看板后,页面有时完全没有数据,需要手动点击”刷新数据”按钮才能正常显示。
根因分析:
/tmp(临时目录),冷启动时数据库为空,/api/latest 返回 {expired: true},触发 refreshData() 全量拉取Promise.all 脆弱性:refreshData() 用 Promise.all 同时请求 7 个接口(5 个 batch + polymarket + EC),冷启动时 serverless 函数初始化慢,任何一个请求超时或失败,整个 Promise.all 就报错,页面白屏新增 safeFetch(url, timeoutMs) 函数:
AbortController){ok: false, data: {}}将 Promise.all 替换为 Promise.allSettled,并增加三层重试逻辑:
7 个请求同时发出
↓
检查哪些失败了
↓
┌──────────────────────────────────────┐
│ 全部成功 → 直接渲染 │
│ 部分失败 → 等 2s,只重试失败的请求 │
│ 全部失败 → 等 3s,全部重试一遍 │
└──────────────────────────────────────┘
↓
合并数据,渲染页面
/api/analyze 失败不再阻断指标渲染——即使分析面板为空,指标卡片和 Polymarket 数据仍正常展示。
对全部代码做了一次完整审查,发现并修复了 4 个问题:
| 问题 | 严重度 | 修复 |
|---|---|---|
ec.price 应为 ec.value |
严重 — 后端返回 value 字段,前端检查的是 price,导致 EC 期货数据有时不渲染 |
改为 ec.value !== undefined |
cacheAge 未做类型转换 |
中 — HTTP header 返回字符串,直接做算术运算有隐患 | 加了 parseInt() |
it.slug 未做空值检查 |
中 — Polymarket 渲染时若 slug 不存在会 TypeError | 加了 && 空值守卫 |
backend/requirements.txt 缺 akshare |
低 — 本地开发环境安装依赖会遗漏 | 补上了 |
更新 DESIGN.md,补充”容错与重试机制”章节,说明 safeFetch、Promise.allSettled、按需重试的设计。
| 提交 | 说明 |
|---|---|
858096a |
feat: 添加单个请求失败自动重试 + safeFetch 容错机制 |
e6b57da |
fix: EC 字段名修正、cacheAge 类型转换、slug 空值守卫、akshare 依赖补全 |
d71b663 |
docs: DESIGN.md 补充容错与重试机制文档 |