mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 20:42:43 +00:00
fix(medication-compliance): scope coverage-miss backfill enqueue to caller user
QA F-SEC-M-01 (v1.4.39): the route's coverage-miss fallback was firing `enqueueBootTimeMedicationComplianceBackfill` on every authenticated hit, running a cluster-wide `LEFT JOIN medication_intake_events x medication_compliance_rollups` discovery scan in the request path. On a multi-tenant cluster with millions of intake events the planner walked all of them per request — a soft DoS amplifier. Split into two helpers: `enqueueUserMedicationComplianceBackfill(userId)` for the request path (one targeted enqueue, no discovery scan) and the existing cluster-wide discovery stays for the worker-boot path. Mirrors the mood-rollup `ensureUserMoodRollupsFresh` posture. Pinned with a unit test that asserts the user-scoped helper never issues `$queryRaw`.
This commit is contained in:
1 parent
aacfbf5b61
commit
6ec2d499fb
3 files changed
+97
-5
No files matched your search
@@ -30,7 +30,7 @@ import {
|
||||
readMedicationCompliance,
|
||||
hasMedicationComplianceCoverage,
|
||||
recomputeMedicationComplianceForEvent,
|
||||
enqueueBootTimeMedicationComplianceBackfill,
|
||||
enqueueUserMedicationComplianceBackfill,
|
||||
type ComplianceBucket as RollupComplianceBucket,
|
||||
} from "@/lib/medications/compliance-rollups";
|
||||
|
||||
@@ -169,10 +169,16 @@ async function readComplianceBucketsWithFallback(
|
||||
}
|
||||
|
||||
// Coverage miss — the legacy aggregator stays correct over an empty
|
||||
// rollup window. Fire the boot backfill in the background so the
|
||||
// next request lands on the rollup tier; the current request still
|
||||
// returns the live-derived buckets.
|
||||
void enqueueBootTimeMedicationComplianceBackfill();
|
||||
// rollup window. Fire a user-scoped backfill in the background so
|
||||
// the next request lands on the rollup tier; the current request
|
||||
// still returns the live-derived buckets.
|
||||
//
|
||||
// QA F-SEC-M-01 (v1.4.39): pre-fix this fired the cluster-wide
|
||||
// `enqueueBootTimeMedicationComplianceBackfill` on every coverage-
|
||||
// miss request, opening a soft-DoS amplifier (every authenticated
|
||||
// user could drive a multi-tenant `LEFT JOIN` scan on each hit).
|
||||
// The user-scoped helper enqueues exactly the caller's account.
|
||||
void enqueueUserMedicationComplianceBackfill(userId);
|
||||
annotate({
|
||||
meta: {
|
||||
medication_compliance_path: "live-fallback",
|
||||
|
||||
@@ -54,6 +54,7 @@ import {
|
||||
hasMedicationComplianceCoverage,
|
||||
recomputeUserMedicationCompliance,
|
||||
enqueueBootTimeMedicationComplianceBackfill,
|
||||
enqueueUserMedicationComplianceBackfill,
|
||||
MEDICATION_COMPLIANCE_BACKFILL_QUEUE,
|
||||
} from "../compliance-rollups";
|
||||
|
||||
@@ -434,3 +435,41 @@ describe("enqueueBootTimeMedicationComplianceBackfill", () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("enqueueUserMedicationComplianceBackfill", () => {
|
||||
it("is a no-op when no boss is attached", async () => {
|
||||
getGlobalBossMock.mockReturnValue(null);
|
||||
const result = await enqueueUserMedicationComplianceBackfill("user-1");
|
||||
expect(result).toEqual({ enqueued: false, error: null });
|
||||
// Critically: no `$queryRaw` cluster-wide LEFT JOIN scan.
|
||||
expect(queryRaw).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("enqueues exactly one job for the caller's user and never touches the cluster-wide LEFT JOIN", async () => {
|
||||
// QA F-SEC-M-01 (v1.4.39): pre-fix the request-path coverage-miss
|
||||
// path called `enqueueBootTimeMedicationComplianceBackfill` which
|
||||
// issued a cluster-wide `LEFT JOIN medication_intake_events ×
|
||||
// medication_compliance_rollups` on every hit. The user-scoped
|
||||
// helper sends one targeted job and never runs the discovery scan.
|
||||
getGlobalBossMock.mockReturnValue({ send: bossSend });
|
||||
bossSend.mockResolvedValueOnce("job-1");
|
||||
const result = await enqueueUserMedicationComplianceBackfill("user-1");
|
||||
expect(result).toEqual({ enqueued: true, error: null });
|
||||
expect(queryRaw).not.toHaveBeenCalled();
|
||||
expect(bossSend).toHaveBeenCalledTimes(1);
|
||||
expect(bossSend).toHaveBeenCalledWith(
|
||||
MEDICATION_COMPLIANCE_BACKFILL_QUEUE,
|
||||
expect.objectContaining({ userId: "user-1" }),
|
||||
expect.objectContaining({
|
||||
singletonKey: "medication-compliance-boot-backfill|user-1",
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("reports a coalesced enqueue as `enqueued:false`", async () => {
|
||||
getGlobalBossMock.mockReturnValue({ send: bossSend });
|
||||
bossSend.mockResolvedValueOnce(null);
|
||||
const result = await enqueueUserMedicationComplianceBackfill("user-2");
|
||||
expect(result).toEqual({ enqueued: false, error: null });
|
||||
});
|
||||
});
|
||||
@@ -516,6 +516,53 @@ export async function ensureUserMedicationComplianceFresh(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* v1.4.39 hotfix (QA F-SEC-M-01) — user-scoped enqueue helper for the
|
||||
* request-path coverage-miss fallback.
|
||||
*
|
||||
* Mirrors `ensureUserMoodRollupsFresh`: the route fires this when its
|
||||
* coverage probe returned false so the caller's account picks up a
|
||||
* targeted boot-backfill job, instead of running a cluster-wide
|
||||
* `LEFT JOIN` over `medication_intake_events × medication_compliance_rollups`
|
||||
* on every authenticated coverage-miss request. The cluster-wide scan
|
||||
* was a soft DoS amplifier — an authenticated user iterating
|
||||
* coverage-miss requests could drive a multi-tenant table scan on
|
||||
* every hit.
|
||||
*
|
||||
* The boot-time discovery helper below stays cluster-wide (it runs
|
||||
* once per worker boot, not per request).
|
||||
*/
|
||||
export async function enqueueUserMedicationComplianceBackfill(
|
||||
userId: string,
|
||||
): Promise<{ enqueued: boolean; error: string | null }> {
|
||||
const boss = getGlobalBoss();
|
||||
if (!boss) {
|
||||
return { enqueued: false, error: null };
|
||||
}
|
||||
try {
|
||||
const payload: MedicationComplianceBackfillPayload = {
|
||||
userId,
|
||||
enqueuedAt: new Date().toISOString(),
|
||||
};
|
||||
const jobId = await boss.send(
|
||||
MEDICATION_COMPLIANCE_BACKFILL_QUEUE,
|
||||
payload,
|
||||
{
|
||||
retryLimit: 3,
|
||||
retryDelay: 60,
|
||||
retryBackoff: true,
|
||||
singletonKey: `medication-compliance-boot-backfill|${userId}`,
|
||||
},
|
||||
);
|
||||
return { enqueued: jobId !== null && jobId !== undefined, error: null };
|
||||
} catch (err) {
|
||||
return {
|
||||
enqueued: false,
|
||||
error: err instanceof Error ? err.message : String(err),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Boot-time enqueue helper — mirrors v1.4.35.1
|
||||
* `enqueueBootTimeRollupBackfill`. Finds users with intake events but
|
||||
|
||||
Reference in new issue
Block a user