diff --git a/CLAUDE.md b/CLAUDE.md index b60e2c2..85925db 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -136,3 +136,6 @@ cd backend && .venv/bin/python tests/smoke.py - 双后端 SQL 注意:**MariaDB 的 CAST 不支持 TEXT 目标类型**(SQLite 支持)——写跨库 查询不要用 `CAST(x AS TEXT)`,两侧都是字符串时直接比较即可(曾导致 refill_backlog 活动分支在 NAS 上 1064 刷屏,commit 617c832 已修)。 +- 双后端 SQL 注意:**MariaDB 的 `trigger` 是保留字,SQLite 却允许它做列名**——本地 + pytest 全绿也不代表生产可用(首次部署 `sync_history` 即 1064 起服务失败)。跨库建表 + 列名避免 `trigger`,用 `trigger_kind` 之类替代(commit 5e6fc01)。 diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 914a6c7..5a19a2f 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -100,10 +100,11 @@ - `DB_TYPE=sqlite`(开发默认,`backend/data/health.db`)↔ `DB_TYPE=mariadb` (生产 NAS)。`config.py` 读取,业务代码不分叉。 -- 20 张表:`users health_data activities sync_status garmin_tokens badges - personal_records job_locks garmin_mfa_sessions user_settings +- 21 张表:`users health_data activities sync_status sync_history garmin_tokens + badges personal_records job_locks garmin_mfa_sessions user_settings activity_details body_composition blood_pressure race_predictions - daily_series challenges devices ai_recommendations ai_jobs ai_insights`。 + daily_series challenges devices ai_recommendations ai_jobs ai_insights` + (`sync_history` 追加式记录每次自动/手动/立即同步结果,见数据流 §1)。 - `init_db()` 幂等(`CREATE TABLE IF NOT EXISTS` + 按列检测的 `ALTER`), 多 gunicorn worker 并发调用安全。`id` 为 VARCHAR(64),外键指向 `users`。 @@ -112,10 +113,12 @@ ### 1. Garmin 同步(手动 + 自动) ``` -用户/调度器触发 +用户/调度器触发(trigger_kind: auto/manual/quick) → 检查 sync_status.rate_limited_until(429 冷却 24h,DB 为准) → garmin.py 分批拉取(health_data 每日指标、activities、daily_series 等) → 库内 upsert → 更新 sync_status → prefetch_insights(AI 洞察预取入队) + → 每次尝试(含被限流拒绝)都向 sync_history 追加一行(只读查询 + GET /api/garmin/sync-history,前端「同步记录」页展示) ``` - 同步频率与历史范围(history_days)读用户设置;`0` 表示全部历史 = 730 天上限。