mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 04:32:42 +00:00
perf(auth): read the operator settings once per request
An app boot's /api/auth/me read the AppSettings singleton six times, each reader with its own few columns: the MFA policy, the Assistant switches, the module availability, the provider presence, the AI usage bounds and the reasoning controls. They now take their columns from one read, memoised for the request and read afresh inside a background job like the readers themselves. No answer changes.
This commit is contained in:
1 parent
e00943ff7f
commit
f8a88d1361
7 files changed
+68
-46
No files matched your search
@@ -17,6 +17,7 @@
|
||||
* (`PUT /api/auth/me/ai-usage`); a managed profile has no choice of its own
|
||||
* and follows the instance default.
|
||||
*/
|
||||
import { readOperatorRow } from "@/lib/settings/operator-row";
|
||||
import { prisma } from "@/lib/db";
|
||||
import { getEvent } from "@/lib/logging/context";
|
||||
import { memoizePerRequest } from "@/lib/request-cache";
|
||||
@@ -83,14 +84,7 @@ export function aiUsageSettingsFromRow(
|
||||
export function loadAiUsageSettings(): Promise<AiUsageSettings> {
|
||||
const read = async (): Promise<AiUsageSettings> => {
|
||||
try {
|
||||
const row = await prisma.appSettings.findUnique({
|
||||
where: { id: "singleton" },
|
||||
select: {
|
||||
aiUsageMaxLevel: true,
|
||||
aiUsageDefaultLevel: true,
|
||||
aiSyncRegenGapHours: true,
|
||||
},
|
||||
});
|
||||
const row = await readOperatorRow();
|
||||
return aiUsageSettingsFromRow(row);
|
||||
} catch {
|
||||
getEvent()?.addWarning(
|
||||
|
||||
+2
-14
@@ -1,4 +1,5 @@
|
||||
import type { AIProvider, CompletionResult } from "./types";
|
||||
import { readOperatorRow } from "@/lib/settings/operator-row";
|
||||
import { bindResponseTimeout } from "./effective-timeout";
|
||||
import { bindReasoningEffort } from "./reasoning-effort";
|
||||
import { prisma } from "@/lib/db";
|
||||
@@ -1145,16 +1146,6 @@ const PRESENCE_USER_SELECT = {
|
||||
aiResponseTimeoutSeconds: true,
|
||||
} as const;
|
||||
|
||||
const PRESENCE_SETTINGS_SELECT = {
|
||||
adminAiKeyEncrypted: true,
|
||||
adminAiModel: true,
|
||||
adminAiBaseUrl: true,
|
||||
adminCodexConnectionStatus: true,
|
||||
adminCodexAccessTokenEncrypted: true,
|
||||
adminCodexRefreshTokenEncrypted: true,
|
||||
adminCodexAccountIdEncrypted: true,
|
||||
} as const;
|
||||
|
||||
const NO_PRESENCE: ProviderPresence = Object.freeze({
|
||||
entries: [],
|
||||
localOcrEnabled: false,
|
||||
@@ -1217,10 +1208,7 @@ export function probeProviderChain(
|
||||
where: { id: recordId },
|
||||
select: PRESENCE_USER_SELECT,
|
||||
}),
|
||||
prisma.appSettings.findUnique({
|
||||
where: { id: "singleton" },
|
||||
select: PRESENCE_SETTINGS_SELECT,
|
||||
}),
|
||||
readOperatorRow(),
|
||||
]);
|
||||
if (!row) return NO_PRESENCE;
|
||||
const policy = providerCredentialPolicy(authority, row.managedProfileAt);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* Server-only. The decision itself is the pure `resolveReasoning` in
|
||||
* `./resolve.ts`; this file only gathers its inputs.
|
||||
*/
|
||||
import { readOperatorRow } from "@/lib/settings/operator-row";
|
||||
import { prisma } from "@/lib/db";
|
||||
import { annotate, getEvent } from "@/lib/logging/context";
|
||||
import { memoizePerRequest } from "@/lib/request-cache";
|
||||
@@ -70,10 +71,7 @@ function loadMemoisedControls(): Promise<ReasoningAdminControls> {
|
||||
"ai-reasoning-controls",
|
||||
async () => {
|
||||
try {
|
||||
const row = await prisma.appSettings.findUnique({
|
||||
where: { id: "singleton" },
|
||||
select: { aiReasoningEnabled: true, aiReasoningMaxEffort: true },
|
||||
});
|
||||
const row = await readOperatorRow();
|
||||
return {
|
||||
enabled: row?.aiReasoningEnabled ?? true,
|
||||
maxEffort: parseReasoningMaxEffort(row?.aiReasoningMaxEffort),
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
* out; the operator/CLI escape hatch (`scripts/disable-mfa.ts`, toggling the
|
||||
* policy off) is the recovery path of last resort.
|
||||
*/
|
||||
import { readOperatorRow } from "@/lib/settings/operator-row";
|
||||
import { cookies } from "next/headers";
|
||||
import { prisma } from "@/lib/db";
|
||||
import { shouldEmitSecureCookie } from "@/lib/auth/secure-cookie";
|
||||
@@ -44,10 +45,7 @@ export async function resolveMfaEnrollmentRequired(
|
||||
// Already has a confirmed TOTP secret → enrolled, nothing required.
|
||||
if (user.totpConfirmedAt) return false;
|
||||
|
||||
const settings = await prisma.appSettings.findUnique({
|
||||
where: { id: "singleton" },
|
||||
select: { mfaRequired: true },
|
||||
});
|
||||
const settings = await readOperatorRow();
|
||||
const policyApplies = Boolean(settings?.mfaRequired) || user.mfaEnforced;
|
||||
if (!policyApplies) return false;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { prisma } from "@/lib/db";
|
||||
import { readOperatorRow } from "@/lib/settings/operator-row";
|
||||
import { getEvent } from "@/lib/logging/context";
|
||||
import { memoizePerRequest } from "@/lib/request-cache";
|
||||
|
||||
@@ -57,16 +57,7 @@ export function loadAssistantSwitches(): Promise<AssistantFlagSet | null> {
|
||||
"assistant-flags",
|
||||
async () => {
|
||||
try {
|
||||
const settings = await prisma.appSettings.findUnique({
|
||||
where: { id: "singleton" },
|
||||
select: {
|
||||
assistantEnabled: true,
|
||||
assistantCoachEnabled: true,
|
||||
assistantBriefingEnabled: true,
|
||||
assistantInsightStatusEnabled: true,
|
||||
assistantDocumentAiEnabled: true,
|
||||
},
|
||||
});
|
||||
const settings = await readOperatorRow();
|
||||
return resolveAssistantFlags({
|
||||
enabled: settings?.assistantEnabled ?? true,
|
||||
coach: settings?.assistantCoachEnabled ?? true,
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
* 0343 folded the blob's `coach` key into the switch and removed it, and a
|
||||
* `coach` key that still turns up in the blob is ignored.
|
||||
*/
|
||||
import { prisma } from "@/lib/db";
|
||||
import { readOperatorRow } from "@/lib/settings/operator-row";
|
||||
import { getAssistantFlags } from "@/lib/feature-flags";
|
||||
import { getEvent } from "@/lib/logging/context";
|
||||
import { memoizePerRequest } from "@/lib/request-cache";
|
||||
@@ -84,10 +84,7 @@ export function resolveOperatorAvailability(
|
||||
/** The raw availability blob; a read error reads as "nothing disabled". */
|
||||
async function loadAvailabilityBlob(): Promise<unknown> {
|
||||
try {
|
||||
const settings = await prisma.appSettings.findUnique({
|
||||
where: { id: "singleton" },
|
||||
select: { moduleAvailabilityJson: true },
|
||||
});
|
||||
const settings = await readOperatorRow();
|
||||
return settings?.moduleAvailabilityJson ?? null;
|
||||
} catch {
|
||||
getEvent()?.addWarning(
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* The operator's settings that every app boot reads, in one statement per
|
||||
* request.
|
||||
*
|
||||
* `/api/auth/me` resolved six answers out of the `AppSettings` singleton (the
|
||||
* MFA policy, the Assistant switches, the module availability, the provider
|
||||
* presence, the AI usage bounds and the reasoning controls), each with its own
|
||||
* `SELECT` of a few columns, so one client boot read the same row six times.
|
||||
* Each reader now takes its columns from this one read, memoised for the
|
||||
* request (and read afresh for every call inside a background job, whose one
|
||||
* event spans a whole multi-user pass, like the readers it serves).
|
||||
*
|
||||
* A reader keeps its own error handling: a failed read rejects here, and the
|
||||
* memo forgets a rejected read so the next caller tries again.
|
||||
*/
|
||||
import type { Prisma } from "@/generated/prisma/client";
|
||||
import { prisma } from "@/lib/db";
|
||||
import { memoizePerRequest } from "@/lib/request-cache";
|
||||
|
||||
export const OPERATOR_ROW_SELECT = {
|
||||
mfaRequired: true,
|
||||
assistantEnabled: true,
|
||||
assistantCoachEnabled: true,
|
||||
assistantBriefingEnabled: true,
|
||||
assistantInsightStatusEnabled: true,
|
||||
assistantDocumentAiEnabled: true,
|
||||
moduleAvailabilityJson: true,
|
||||
adminAiKeyEncrypted: true,
|
||||
adminAiModel: true,
|
||||
adminAiBaseUrl: true,
|
||||
adminCodexConnectionStatus: true,
|
||||
adminCodexAccessTokenEncrypted: true,
|
||||
adminCodexRefreshTokenEncrypted: true,
|
||||
adminCodexAccountIdEncrypted: true,
|
||||
aiUsageMaxLevel: true,
|
||||
aiUsageDefaultLevel: true,
|
||||
aiSyncRegenGapHours: true,
|
||||
aiReasoningEnabled: true,
|
||||
aiReasoningMaxEffort: true,
|
||||
} as const satisfies Prisma.AppSettingsSelect;
|
||||
|
||||
export type OperatorRow = Prisma.AppSettingsGetPayload<{
|
||||
select: typeof OPERATOR_ROW_SELECT;
|
||||
}>;
|
||||
|
||||
export function readOperatorRow(): Promise<OperatorRow | null> {
|
||||
return memoizePerRequest(
|
||||
"operator-settings-row",
|
||||
() =>
|
||||
prisma.appSettings.findUnique({
|
||||
where: { id: "singleton" },
|
||||
select: OPERATOR_ROW_SELECT,
|
||||
}),
|
||||
{ freshInBackground: true },
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user