feat: add persistent personal report document v2
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { after, NextResponse } from "next/server";
|
||||
import { NextResponse } from "next/server";
|
||||
import { runConsultationWorkflow } from "@/mastra";
|
||||
import { createPersonalReportAgent } from "@/mastra/personal-report";
|
||||
import { loadLanguageModelCatalog } from "@/lib/model-catalog";
|
||||
@@ -20,19 +20,20 @@ import {
|
||||
createSupabasePersonalReportService,
|
||||
type PersonalReportService,
|
||||
} from "@/lib/personal-report-service";
|
||||
import { createSupabasePersonalReportJobService } from "@/lib/personal-report-job-service";
|
||||
import { createAdminSupabaseClient } from "@/lib/supabase/admin";
|
||||
import { isSupabaseConfigurationError } from "@/lib/supabase/config";
|
||||
import { createServerSupabaseClient } from "@/lib/supabase/server";
|
||||
|
||||
export const runtime = "nodejs";
|
||||
export const maxDuration = 120;
|
||||
const STALE_GENERATION_MS = 15 * 60 * 1000;
|
||||
|
||||
const REPORT_LIST_COLUMNS = [
|
||||
"id",
|
||||
"request_id",
|
||||
"report_type",
|
||||
"presentation_mode",
|
||||
"depth",
|
||||
"requested_themes",
|
||||
"status",
|
||||
"failure_code",
|
||||
@@ -56,6 +57,7 @@ function listReportView(value: unknown) {
|
||||
requestId: typeof row.request_id === "string" ? row.request_id : "",
|
||||
reportType: typeof row.report_type === "string" ? row.report_type : "personal_full",
|
||||
presentationMode: typeof row.presentation_mode === "string" ? row.presentation_mode : "default",
|
||||
depth: typeof row.depth === "string" ? row.depth : "standard",
|
||||
themes: Array.isArray(row.requested_themes)
|
||||
? row.requested_themes.filter((theme): theme is string => typeof theme === "string")
|
||||
: [],
|
||||
@@ -113,25 +115,6 @@ export async function POST(request: Request) {
|
||||
const persistence: PersonalReportService = createSupabasePersonalReportService(admin);
|
||||
const adminDataClient = createPersonalReportDataClient(admin);
|
||||
|
||||
// `after()` is bounded by the route duration and can be interrupted by a
|
||||
// process restart. Reclaim only rows far beyond that bound so a killed
|
||||
// task never blocks the user's next explicit generation forever.
|
||||
if (userId) {
|
||||
const now = new Date();
|
||||
const staleBefore = new Date(now.getTime() - STALE_GENERATION_MS).toISOString();
|
||||
const { error } = await admin
|
||||
.from("personal_reports")
|
||||
.update({
|
||||
status: "failed",
|
||||
failure_code: REPORT_STABLE_CODES.calculationUnavailable,
|
||||
updated_at: now.toISOString(),
|
||||
})
|
||||
.eq("user_id", userId)
|
||||
.eq("status", "generating")
|
||||
.lte("updated_at", staleBefore);
|
||||
if (error) throw error;
|
||||
}
|
||||
|
||||
let profile: unknown = null;
|
||||
let profileError: unknown = null;
|
||||
if (userId) {
|
||||
@@ -208,7 +191,7 @@ export async function POST(request: Request) {
|
||||
runWorkflow: (input) => runConsultationWorkflow(input),
|
||||
createAgent: (model) => createPersonalReportAgent(model as Parameters<typeof createPersonalReportAgent>[0]),
|
||||
skillSnapshot: resolveSkillSnapshot(),
|
||||
deferGeneration: (task) => after(task),
|
||||
jobs: createSupabasePersonalReportJobService(admin),
|
||||
};
|
||||
|
||||
const response = await resolveReportCreate(deps);
|
||||
|
||||
Reference in New Issue
Block a user