mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 22:26:13 +00:00
fix(ai): read AI switches, modules and consent afresh inside background jobs
A background job opens one wide event for its whole run, and the per-request memo cached the operator switches, module availability, module preferences, provider presence and consent kinds on it. The nightly status passes loop over every candidate inside that one event, so a switch turned off mid-run did not stop the remaining users, and the wire re-check read the same cached answer. memoizePerRequest takes a freshInBackground option; every input that decides whether AI work may run sets it, so a background caller reads them on every call while a request still reads them once.
This commit is contained in:
1 parent
4ae231d757
commit
06251d7219
10 files changed
+236
-67
No files matched your search
+26
-22
@@ -169,28 +169,32 @@ export function resolveModuleEnabled(
|
||||
|
||||
/** Internal: load the gate inputs once per request. */
|
||||
function loadInputs(userId: string): Promise<ModuleGateInputs> {
|
||||
return memoizePerRequest(`module-gate-inputs:${userId}`, async () => {
|
||||
const [user, cycleProfile] = await Promise.all([
|
||||
prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
select: {
|
||||
gender: true,
|
||||
disableCoach: true,
|
||||
modulePreferencesJson: true,
|
||||
},
|
||||
}),
|
||||
prisma.cycleProfile.findUnique({
|
||||
where: { userId },
|
||||
select: { cycleTrackingEnabled: true },
|
||||
}),
|
||||
]);
|
||||
return {
|
||||
gender: user?.gender ?? null,
|
||||
disableCoach: user?.disableCoach ?? false,
|
||||
modulePreferences: normalisePrefs(user?.modulePreferencesJson),
|
||||
cycleTrackingEnabled: cycleProfile?.cycleTrackingEnabled ?? null,
|
||||
};
|
||||
});
|
||||
return memoizePerRequest(
|
||||
`module-gate-inputs:${userId}`,
|
||||
async () => {
|
||||
const [user, cycleProfile] = await Promise.all([
|
||||
prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
select: {
|
||||
gender: true,
|
||||
disableCoach: true,
|
||||
modulePreferencesJson: true,
|
||||
},
|
||||
}),
|
||||
prisma.cycleProfile.findUnique({
|
||||
where: { userId },
|
||||
select: { cycleTrackingEnabled: true },
|
||||
}),
|
||||
]);
|
||||
return {
|
||||
gender: user?.gender ?? null,
|
||||
disableCoach: user?.disableCoach ?? false,
|
||||
modulePreferences: normalisePrefs(user?.modulePreferencesJson),
|
||||
cycleTrackingEnabled: cycleProfile?.cycleTrackingEnabled ?? null,
|
||||
};
|
||||
},
|
||||
{ freshInBackground: true },
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -104,13 +104,17 @@ async function loadAvailabilityBlob(): Promise<unknown> {
|
||||
* all-available so the modules stay visible on first boot.
|
||||
*/
|
||||
export async function getOperatorModuleAvailability(): Promise<OperatorModuleAvailability> {
|
||||
return memoizePerRequest("operator-module-availability", async () => {
|
||||
const [blob, switches] = await Promise.all([
|
||||
loadAvailabilityBlob(),
|
||||
getAssistantFlags(),
|
||||
]);
|
||||
return resolveOperatorAvailability(blob, switches.coach);
|
||||
});
|
||||
return memoizePerRequest(
|
||||
"operator-module-availability",
|
||||
async () => {
|
||||
const [blob, switches] = await Promise.all([
|
||||
loadAvailabilityBlob(),
|
||||
getAssistantFlags(),
|
||||
]);
|
||||
return resolveOperatorAvailability(blob, switches.coach);
|
||||
},
|
||||
{ freshInBackground: true },
|
||||
);
|
||||
}
|
||||
|
||||
/** A module key whose operator layer the blob owns (every key but the Coach). */
|
||||
|
||||
Reference in new issue
Block a user