fix(sync): 「全部历史」真的拉全部历史,自动同步不再每次静默失败
四个独立的 bug 叠在一起,表现为「只同步两天、没有进度」:
* 前端 `...(days ? { days } : {})` 把 days=0 当成未传。「全部历史」
存的就是 0,请求体里根本没有 days,后端退回 7 天默认值。
* scheduler 用 `s[0]` 读 query_one 返回的 dict,抛 KeyError 后被
per-account 的 except 吞掉。只要用户存过一次设置,每 30 分钟的
自动同步就一次都没成功过——库里那 2 天全是手动点出来的。
* 增量同步查 `health_daily`(表其实叫 health_data),后台线程直接
死掉,状态永远卡在 syncing,进度条不动。
* UI 完全不看 /sync 的返回值,rate_limited 时按钮点了没反应;轮询
结束时又把 rate_limited 归进 else 分支报「同步完成」。
顺带:
* 日循环遇到 429 立即退避并保留已拉到的天数,而不是当成「跳过一天」
继续往下捶 700 天——这正是之前限流死循环的来源之一。
* 定时循环显式传 SYNC_DAYS。历史范围按 UI 文案只描述手动全量同步,
让半小时一次的 tick 重拉 730 天必然把限流撞得更深。
* 短同步逐天上报进度(原来每 5 天一次,7 天的同步全程停在 0)。
* /sync 路由重复解析 body,空 body 会 None.get 崩。
* 4 个 StubGarth 缺 configure(),7 个测试在此之前一直是红的。
新增 deploy/push.sh:NAS 只认密码,脚本开一个 ssh 复用连接,密码只
输一次,后面推送 / 重启 / 健康检查全走它。不碰 .env、.venv 和数据库。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -105,7 +105,7 @@ export interface Activity {
|
||||
}
|
||||
|
||||
export interface SyncStatus {
|
||||
status: 'idle' | 'syncing' | 'error';
|
||||
status: 'idle' | 'syncing' | 'error' | 'rate_limited';
|
||||
lastSyncTime: string | null;
|
||||
recordsSynced: number;
|
||||
totalDays: number;
|
||||
@@ -120,7 +120,7 @@ export interface SyncStatus {
|
||||
}
|
||||
|
||||
export interface SyncResult {
|
||||
status: 'success' | 'error';
|
||||
status: 'success' | 'error' | 'rate_limited';
|
||||
recordsSynced: number;
|
||||
activitiesSynced?: number;
|
||||
message: string;
|
||||
@@ -442,10 +442,15 @@ class ApiClient {
|
||||
*/
|
||||
/** Starts a sync in the background; poll getGarminSyncStatus for progress. */
|
||||
async syncGarminData(days?: number, garminPassword?: string) {
|
||||
const { data } = await this.client.post<{ status: string; days?: number }>(
|
||||
const { data } = await this.client.post<{
|
||||
status: string; days?: number; message?: string; retryAfterSeconds?: number;
|
||||
}>(
|
||||
'/garmin/sync',
|
||||
{
|
||||
...(days ? { days } : {}),
|
||||
// `days` must survive being 0 — that is "全部历史", not "unset".
|
||||
// `days ? …` dropped it, so the backend fell back to its 7-day
|
||||
// default and a full backfill silently pulled a week.
|
||||
...(days === undefined || days === null ? {} : { days }),
|
||||
...(garminPassword ? { garminPassword } : {}),
|
||||
}
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user