Files
Jyotisha/frontend/src/lib/consult-packet-warm.ts
T
Jesse_ChenandClaude Opus 5.5 b4eedb7725
Independent Staging Quality Gate / validate (push) Successful in 13m12s
Independent Staging Quality Gate / publish (push) Successful in 4m16s
fix(consult): a warm that cannot be scheduled no longer fails the save (BUG-1305)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
2026-10-09 15:17:00 +08:00

73 lines
2.4 KiB
TypeScript

import { after } from "next/server";
/**
* After a chart is saved, ask the engine to cache today's full-data packet.
* The save response does not wait for that build (TASK fix F5).
*/
type WarmDeps = {
after: (task: () => Promise<void> | void) => void;
fetch: typeof fetch;
apiBase?: string;
};
function asNumber(value: unknown): number | null {
if (typeof value === "number" && Number.isFinite(value)) return value;
if (typeof value === "string" && value.trim() && Number.isFinite(Number(value))) return Number(value);
return null;
}
export function consultWarmBodyFromColumns(columns: Record<string, unknown> | null | undefined): Record<string, unknown> | null {
if (!columns) return null;
const date = typeof columns.birth_date === "string" ? columns.birth_date : "";
const time = typeof columns.reported_birth_time === "string" ? columns.reported_birth_time : "";
const lat = asNumber(columns.latitude);
const lon = asNumber(columns.longitude);
const tz = asNumber(columns.timezone_offset);
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(date);
const clock = /^(\d{1,2}):(\d{2})/.exec(time);
if (!match || !clock || lat === null || lon === null || tz === null) return null;
return {
year: Number(match[1]),
month: Number(match[2]),
day: Number(match[3]),
hour: Number(clock[1]),
minute: Number(clock[2]),
second: 0,
lat,
lon,
tz,
ayanamsa: typeof columns.ayanamsa === "string" && columns.ayanamsa ? columns.ayanamsa : "lahiri",
node_mode: "mean",
consult_card_warm_only: true,
};
}
export function scheduleConsultPacketWarm(
columns: Record<string, unknown> | null | undefined,
deps: WarmDeps = {
after,
fetch,
apiBase: process.env.JYOTISH_API_BASE ?? "http://127.0.0.1:5200",
},
): boolean {
const body = consultWarmBodyFromColumns(columns);
if (!body) return false;
const apiBase = deps.apiBase ?? "http://127.0.0.1:5200";
// Warm is best effort. `after` throws outside a request scope; the save has
// already been written by then, so a scheduling failure must not turn it
// into a 500 (BUG-1305).
try {
deps.after(() => {
return deps.fetch(`${apiBase}/api/consultation_workflow`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(body),
}).then(() => undefined).catch(() => undefined);
});
} catch {
return false;
}
return true;
}