mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 13:52:20 +00:00
fix(whoop): a dead token no longer reports a successful sync
Port the hard-fail ledger the Fitbit transport already carries. A revoked WHOOP grant makes every resource short-circuit and return zero rows without throwing, so the cycle read as clean: it stamped success, un-parked the reconnect state, reset the failure streak, and the hourly cohort hammered the dead refresh token on every tick. Record the three dead-token null-return paths on the ledger and fold that verdict into both drivers — the full orchestrator and the per-resource cron path that runs most often — so a dead-token cycle refuses the success stamp and the park holds. Return an imported-plus-failed verdict from the orchestrator and gate the history backfill on it: an interrupted full-history walk now throws for a pg-boss retry instead of being stamped complete, and a connection parked at reauth returns without burning the retry budget. Thread the same verdict into the one-shot sleep-timeline backfill. Also catch a write-path throw on both drivers so a persistent measurement-write failure surfaces on the status ledger instead of leaving a stale-green pill, and widen the cycle overlap to the seven-day re-score window the other collections use so a late-revised day's strain and energy are re-fetched rather than stepped past.
This commit is contained in:
1 parent
8be7458c7a
commit
9a69e4e557
14 files changed
+672
-65
No files matched your search
@@ -30,7 +30,7 @@ describe("POST /api/whoop/sync", () => {
|
||||
beforeEach(() => vi.clearAllMocks());
|
||||
|
||||
it("triggers an incremental sync by default", async () => {
|
||||
sync.mockResolvedValue(7);
|
||||
sync.mockResolvedValue({ imported: 7, failed: false });
|
||||
const res = (await (
|
||||
POST as unknown as (r: NextRequest) => Promise<{ data: unknown }>
|
||||
)(req({}))) as { data: { imported: number; fullSync: boolean } };
|
||||
@@ -40,7 +40,7 @@ describe("POST /api/whoop/sync", () => {
|
||||
});
|
||||
|
||||
it("honours fullSync: true", async () => {
|
||||
sync.mockResolvedValue(99);
|
||||
sync.mockResolvedValue({ imported: 99, failed: false });
|
||||
const res = (await (
|
||||
POST as unknown as (r: NextRequest) => Promise<{ data: unknown }>
|
||||
)(req({ fullSync: true }))) as { data: { fullSync: boolean } };
|
||||
|
||||
@@ -27,6 +27,6 @@ export const POST = apiHandler(async (request: NextRequest) => {
|
||||
// no body provided -> default incremental sync
|
||||
}
|
||||
|
||||
const imported = await syncUserWhoop(user.id, { fullSync });
|
||||
const { imported } = await syncUserWhoop(user.id, { fullSync });
|
||||
return apiSuccess({ imported, fullSync });
|
||||
});
|
||||
Reference in new issue
Block a user