mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 06:32:03 +00:00
Revert "perf(insights): persist timeout stub for blood-pressure and weight status"
This reverts commit 27f3bec1f4.
This commit is contained in:
1 parent
812a8f287e
commit
cd2a579cc3
5 files changed
+4
-371
No files matched your search
@@ -109,104 +109,6 @@ describe("generateBloodPressureStatusForUser — v1.4.6 bucketed payload", () =>
|
||||
});
|
||||
});
|
||||
|
||||
describe("generateBloodPressureStatusForUser — v1.4.41 timeout-stub persistence", () => {
|
||||
it("persists a sentinel row keyed to today when the provider times out", async () => {
|
||||
vi.mocked(prisma.user.findUnique).mockResolvedValue({
|
||||
dateOfBirth: null,
|
||||
} as never);
|
||||
vi.mocked(prisma.auditLog.findFirst).mockResolvedValue(null);
|
||||
vi.mocked(prisma.measurement.findMany).mockResolvedValue([
|
||||
{ type: "BLOOD_PRESSURE_SYS", value: 132, measuredAt: new Date() },
|
||||
{ type: "BLOOD_PRESSURE_DIA", value: 84, measuredAt: new Date() },
|
||||
] as never);
|
||||
vi.mocked(prisma.medication.findMany).mockResolvedValue([] as never);
|
||||
vi.mocked(prisma.medicationIntakeEvent.findMany).mockResolvedValue(
|
||||
[] as never,
|
||||
);
|
||||
vi.mocked(prisma.moodEntry.findMany).mockResolvedValue([] as never);
|
||||
vi.mocked(prisma.auditLog.create).mockResolvedValue({
|
||||
createdAt: new Date(),
|
||||
} as never);
|
||||
|
||||
// Provider hangs past the 20 s timeout — withTimeout cuts the race.
|
||||
vi.mocked(resolveProvider).mockResolvedValue({
|
||||
type: "anthropic",
|
||||
generateCompletion: vi.fn(
|
||||
() =>
|
||||
new Promise(() => {
|
||||
/* never resolves */
|
||||
}),
|
||||
),
|
||||
} as never);
|
||||
|
||||
vi.useFakeTimers();
|
||||
const promise = generateBloodPressureStatusForUser("user-1", {
|
||||
locale: "en",
|
||||
});
|
||||
await vi.advanceTimersByTimeAsync(25_000);
|
||||
const result = await promise;
|
||||
vi.useRealTimers();
|
||||
|
||||
expect(result.text).toBeTruthy();
|
||||
expect(result.cached).toBe(true);
|
||||
expect(result.updatedAt).toBeTruthy();
|
||||
|
||||
const createCalls = vi.mocked(prisma.auditLog.create).mock.calls;
|
||||
expect(createCalls.length).toBe(1);
|
||||
const details = (createCalls[0][0] as { data: { details: string } }).data
|
||||
.details;
|
||||
const parsed = JSON.parse(details) as {
|
||||
dateKey?: string;
|
||||
text?: string;
|
||||
timeout?: boolean;
|
||||
model?: string;
|
||||
};
|
||||
expect(parsed.text).toBeTruthy();
|
||||
expect(parsed.timeout).toBe(true);
|
||||
expect(parsed.model).toBe("timeout-stub");
|
||||
expect(parsed.dateKey).toMatch(/^\d{4}-\d{2}-\d{2}$/);
|
||||
});
|
||||
|
||||
it("subsequent mounts short-circuit at the cache lookup and skip the race", async () => {
|
||||
const parts = new Intl.DateTimeFormat("en-US", {
|
||||
timeZone: "Europe/Berlin",
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
}).formatToParts(new Date());
|
||||
const y = parts.find((p) => p.type === "year")!.value;
|
||||
const m = parts.find((p) => p.type === "month")!.value;
|
||||
const d = parts.find((p) => p.type === "day")!.value;
|
||||
const todayKey = `${y}-${m}-${d}`;
|
||||
const stubRow = {
|
||||
createdAt: new Date(),
|
||||
details: JSON.stringify({
|
||||
dateKey: todayKey,
|
||||
locale: "en",
|
||||
text: "Blood-pressure assessment temporarily unavailable.",
|
||||
timeout: true,
|
||||
}),
|
||||
};
|
||||
|
||||
vi.mocked(prisma.auditLog.findFirst).mockResolvedValue(stubRow as never);
|
||||
const providerCall = vi.fn();
|
||||
vi.mocked(resolveProvider).mockResolvedValue({
|
||||
type: "anthropic",
|
||||
generateCompletion: providerCall,
|
||||
} as never);
|
||||
|
||||
const result = await generateBloodPressureStatusForUser("user-1", {
|
||||
locale: "en",
|
||||
});
|
||||
|
||||
expect(providerCall).not.toHaveBeenCalled();
|
||||
expect(result.text).toBe("Blood-pressure assessment temporarily unavailable.");
|
||||
expect(result.cached).toBe(true);
|
||||
expect(result.updatedAt).toBe(stubRow.createdAt.toISOString());
|
||||
expect(prisma.auditLog.create).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("generateBloodPressureStatusForUser — token-leak hardening (v1.4.27 F16)", () => {
|
||||
it("strips metric: tokens out of the cached text before persisting", async () => {
|
||||
vi.mocked(prisma.user.findUnique).mockResolvedValue({
|
||||
|
||||
@@ -82,92 +82,6 @@ describe("generateWeightStatusForUser — v1.4.6 bucketed payload", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("generateWeightStatusForUser — v1.4.41 timeout-stub persistence", () => {
|
||||
it("persists a sentinel row keyed to today when the provider times out", async () => {
|
||||
vi.mocked(prisma.auditLog.findFirst).mockResolvedValue(null);
|
||||
vi.mocked(prisma.measurement.findMany).mockResolvedValue([
|
||||
{ type: "WEIGHT", value: 82, measuredAt: new Date() },
|
||||
] as never);
|
||||
vi.mocked(prisma.moodEntry.findMany).mockResolvedValue([] as never);
|
||||
vi.mocked(prisma.auditLog.create).mockResolvedValue({
|
||||
createdAt: new Date(),
|
||||
} as never);
|
||||
|
||||
// Provider hangs past the 20 s timeout — withTimeout cuts the race.
|
||||
vi.mocked(resolveProvider).mockResolvedValue({
|
||||
type: "anthropic",
|
||||
generateCompletion: vi.fn(
|
||||
() =>
|
||||
new Promise(() => {
|
||||
/* never resolves */
|
||||
}),
|
||||
),
|
||||
} as never);
|
||||
|
||||
vi.useFakeTimers();
|
||||
const promise = generateWeightStatusForUser("user-1", { locale: "en" });
|
||||
await vi.advanceTimersByTimeAsync(25_000);
|
||||
const result = await promise;
|
||||
vi.useRealTimers();
|
||||
|
||||
expect(result.text).toBeTruthy();
|
||||
expect(result.cached).toBe(true);
|
||||
expect(result.updatedAt).toBeTruthy();
|
||||
|
||||
const createCalls = vi.mocked(prisma.auditLog.create).mock.calls;
|
||||
expect(createCalls.length).toBe(1);
|
||||
const details = (createCalls[0][0] as { data: { details: string } }).data
|
||||
.details;
|
||||
const parsed = JSON.parse(details) as {
|
||||
dateKey?: string;
|
||||
text?: string;
|
||||
timeout?: boolean;
|
||||
model?: string;
|
||||
};
|
||||
expect(parsed.text).toBeTruthy();
|
||||
expect(parsed.timeout).toBe(true);
|
||||
expect(parsed.model).toBe("timeout-stub");
|
||||
expect(parsed.dateKey).toMatch(/^\d{4}-\d{2}-\d{2}$/);
|
||||
});
|
||||
|
||||
it("subsequent mounts short-circuit at the cache lookup and skip the race", async () => {
|
||||
const parts = new Intl.DateTimeFormat("en-US", {
|
||||
timeZone: "Europe/Berlin",
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
}).formatToParts(new Date());
|
||||
const y = parts.find((p) => p.type === "year")!.value;
|
||||
const m = parts.find((p) => p.type === "month")!.value;
|
||||
const d = parts.find((p) => p.type === "day")!.value;
|
||||
const todayKey = `${y}-${m}-${d}`;
|
||||
const stubRow = {
|
||||
createdAt: new Date(),
|
||||
details: JSON.stringify({
|
||||
dateKey: todayKey,
|
||||
locale: "en",
|
||||
text: "Weight assessment temporarily unavailable.",
|
||||
timeout: true,
|
||||
}),
|
||||
};
|
||||
|
||||
vi.mocked(prisma.auditLog.findFirst).mockResolvedValue(stubRow as never);
|
||||
const providerCall = vi.fn();
|
||||
vi.mocked(resolveProvider).mockResolvedValue({
|
||||
type: "anthropic",
|
||||
generateCompletion: providerCall,
|
||||
} as never);
|
||||
|
||||
const result = await generateWeightStatusForUser("user-1", { locale: "en" });
|
||||
|
||||
expect(providerCall).not.toHaveBeenCalled();
|
||||
expect(result.text).toBe("Weight assessment temporarily unavailable.");
|
||||
expect(result.cached).toBe(true);
|
||||
expect(result.updatedAt).toBe(stubRow.createdAt.toISOString());
|
||||
expect(prisma.auditLog.create).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("generateWeightStatusForUser — token-leak hardening (v1.4.27 F16)", () => {
|
||||
it("strips metric: tokens out of the cached text before persisting", async () => {
|
||||
vi.mocked(prisma.auditLog.findFirst).mockResolvedValue(null);
|
||||
|
||||
@@ -542,50 +542,11 @@ export async function generateBloodPressureStatusForUser(
|
||||
);
|
||||
|
||||
if (raced.timedOut || raced.value === null) {
|
||||
// v1.4.41 — parity with bmi-status: persist a sentinel row keyed
|
||||
// to today so the next mount short-circuits at the cache lookup
|
||||
// above instead of re-racing the same 20 s provider call on every
|
||||
// cold visit. Without this, a single stall (provider hiccup,
|
||||
// network blip, model warm-up) left iOS users staring at the
|
||||
// loading state on every dashboard open for the rest of the day.
|
||||
// The body is the same no-key fallback the caller returned
|
||||
// before, so the user-facing UI is identical; only the re-fire
|
||||
// frequency drops to zero until the daily pre-warm job overwrites
|
||||
// the stub. `meta.timeout` is set so the pre-warm worker can
|
||||
// recognise and replace it rather than respect it as a real
|
||||
// assessment.
|
||||
const stubText = getNoKeyBloodPressureStatusText(locale);
|
||||
let stubUpdatedAt: string | null = null;
|
||||
try {
|
||||
const stub = await prisma.auditLog.create({
|
||||
data: {
|
||||
userId,
|
||||
action: cacheAction,
|
||||
details: JSON.stringify({
|
||||
dateKey: todayKey,
|
||||
locale,
|
||||
text: stubText,
|
||||
providerType: provider.type,
|
||||
model: "timeout-stub",
|
||||
tokensUsed: null,
|
||||
timeout: true,
|
||||
}),
|
||||
},
|
||||
select: { createdAt: true },
|
||||
});
|
||||
stubUpdatedAt = stub.createdAt.toISOString();
|
||||
} catch {
|
||||
// Best-effort persist — if the row write fails the caller still
|
||||
// sees the deterministic fallback text and the next mount falls
|
||||
// back to the (still expensive) race. Do not surface the error:
|
||||
// the user does not care that the cache write missed, only that
|
||||
// the page rendered.
|
||||
}
|
||||
return {
|
||||
hasProvider: true,
|
||||
text: stubText,
|
||||
text: getNoKeyBloodPressureStatusText(locale),
|
||||
cached: true,
|
||||
updatedAt: stubUpdatedAt,
|
||||
updatedAt: null,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -440,50 +440,11 @@ export async function generateWeightStatusForUser(
|
||||
);
|
||||
|
||||
if (raced.timedOut || raced.value === null) {
|
||||
// v1.4.41 — parity with bmi-status: persist a sentinel row keyed
|
||||
// to today so the next mount short-circuits at the cache lookup
|
||||
// above instead of re-racing the same 20 s provider call on every
|
||||
// cold visit. Without this, a single stall (provider hiccup,
|
||||
// network blip, model warm-up) left iOS users staring at the
|
||||
// loading state on every dashboard open for the rest of the day.
|
||||
// The body is the same no-key fallback the caller returned
|
||||
// before, so the user-facing UI is identical; only the re-fire
|
||||
// frequency drops to zero until the daily pre-warm job overwrites
|
||||
// the stub. `meta.timeout` is set so the pre-warm worker can
|
||||
// recognise and replace it rather than respect it as a real
|
||||
// assessment.
|
||||
const stubText = getNoKeyWeightStatusText(locale);
|
||||
let stubUpdatedAt: string | null = null;
|
||||
try {
|
||||
const stub = await prisma.auditLog.create({
|
||||
data: {
|
||||
userId,
|
||||
action: cacheAction,
|
||||
details: JSON.stringify({
|
||||
dateKey: todayKey,
|
||||
locale,
|
||||
text: stubText,
|
||||
providerType: provider.type,
|
||||
model: "timeout-stub",
|
||||
tokensUsed: null,
|
||||
timeout: true,
|
||||
}),
|
||||
},
|
||||
select: { createdAt: true },
|
||||
});
|
||||
stubUpdatedAt = stub.createdAt.toISOString();
|
||||
} catch {
|
||||
// Best-effort persist — if the row write fails the caller still
|
||||
// sees the deterministic fallback text and the next mount falls
|
||||
// back to the (still expensive) race. Do not surface the error:
|
||||
// the user does not care that the cache write missed, only that
|
||||
// the page rendered.
|
||||
}
|
||||
return {
|
||||
hasProvider: true,
|
||||
text: stubText,
|
||||
text: getNoKeyWeightStatusText(locale),
|
||||
cached: true,
|
||||
updatedAt: stubUpdatedAt,
|
||||
updatedAt: null,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user