fix(schedule): apply HTTP full snapshot as authoritative SQLite state - #225
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
No high-confidence issues found in the changed sync implementation. The fixed-range diff was reviewed across code quality, performance, security, and documentation. Focused Vitest execution was attempted but could not run because the checked-out workspace has no usable vitest binary (Permission denied / dependencies unavailable).
Wintercom
left a comment
There was a problem hiding this comment.
发现一个确认的问题:isValidSchedule 将 end_time 解析为 end,但没有检查非空 schedule.end_time 在解析失败时的情况。比如 end_time: "not-an-iso-instant" 会通过校验(因为后续只有 end !== null 时才比较),随后被写入 SQLite;这与 start_time、created_at、updated_at 和 reminder_trigger_at 的校验不一致,也会污染本地投影。建议在应用前增加 schedule.end_time !== null && end === null 的拒绝条件,并补充回归测试。
|
@Wintercom 已在 d190f41 修复:现在会拒绝无法解析的非空 end_time,并新增回归测试验证返回 invalid_snapshot 且 SQLite 不发生任何写入。相关测试和 CI 均已通过。 |
Summary
Part of #176
applyFullScheduleSnapshotToSqliteboundary for HTTP recovery while keepingapplyScheduleSnapshotToSqliteas the unchanged WebSocket incremental pathschedules = [], preserve account isolation and device-local reminder runtime fields, and retain per-schedulecloud_revisionprotection for rows still present in the snapshotVerification
npx vitest run tests/integration/scheduleSyncService.test.ts— 1 file / 20 tests passednpm run check(Node 20.20.2, clean LF checkout matching CI) — ESLint passed; Prettier passed; TypeScript passed; Vitest 3 files / 38 tests passed; Jest 7 suites / 28 tests passednpx expo export --platform android --output-dir dist— Android bundle exported successfullygit diff --check— passedScope
This PR only fixes HTTP Full Snapshot → client SQLite full-recovery semantics.
next_trigger_at,snoozed_until,geofence_armed, local disposition state, andsync_status) through the existing repository upsert semantics; cloud-owned schedule/reminder configuration fields are refreshed.Concurrency note
For schedule IDs present in the HTTP snapshot, a lower incoming revision cannot overwrite a newer local
cloud_revision; its local overrides are preserved as part of the same protection. The current HTTP contract has no account-wide snapshot version or cursor, so it cannot totally order an HTTP response against a WebSocket-created schedule that commits after the HTTP snapshot was generated but before local application. The exclusive SQLite transaction prevents interleaved/partial local writes, but eliminating that protocol-level absent-row race would require a future global snapshot version and is intentionally outside this focused PR.