feat: add cold start duration display
This commit is contained in:
@@ -2,62 +2,73 @@ import { RunInputs } from "@/components/RunInputs";
|
||||
import { RunOutputs } from "@/components/RunOutputs";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import { TableCell, TableRow } from "@/components/ui/table";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
import { getDuration, getRelativeTime } from "@/lib/getRelativeTime";
|
||||
import { type findAllRuns } from "@/server/findAllRuns";
|
||||
import { Suspense } from "react";
|
||||
import { LiveStatus } from "./LiveStatus";
|
||||
|
||||
export async function RunDisplay({
|
||||
run,
|
||||
run,
|
||||
}: {
|
||||
run: Awaited<ReturnType<typeof findAllRuns>>[0];
|
||||
run: Awaited<ReturnType<typeof findAllRuns>>[0];
|
||||
}) {
|
||||
return (
|
||||
<Dialog>
|
||||
<DialogTrigger asChild className="appearance-none hover:cursor-pointer">
|
||||
<TableRow>
|
||||
<TableCell>{run.number}</TableCell>
|
||||
<TableCell className="font-medium truncate">
|
||||
{run.machine?.name}
|
||||
</TableCell>
|
||||
<TableCell className="truncate">
|
||||
{getRelativeTime(run.created_at)}
|
||||
</TableCell>
|
||||
<TableCell>{run.version?.version}</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant="outline" className="truncate">
|
||||
{run.origin}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="truncate">
|
||||
{getDuration(run.duration)}
|
||||
</TableCell>
|
||||
<LiveStatus run={run} />
|
||||
</TableRow>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-w-3xl">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Run outputs</DialogTitle>
|
||||
<DialogDescription>
|
||||
You can view your run's outputs here
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="max-h-96 overflow-y-scroll">
|
||||
<RunInputs run={run} />
|
||||
<Suspense>
|
||||
<RunOutputs run_id={run.id} />
|
||||
</Suspense>
|
||||
</div>
|
||||
{/* <div className="max-h-96 overflow-y-scroll">{view}</div> */}
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
return (
|
||||
<Dialog>
|
||||
<DialogTrigger asChild className="appearance-none hover:cursor-pointer">
|
||||
<TableRow>
|
||||
<TableCell>{run.number}</TableCell>
|
||||
<TableCell className="font-medium truncate">
|
||||
{run.machine?.name}
|
||||
</TableCell>
|
||||
<TableCell className="truncate">
|
||||
{getRelativeTime(run.created_at)}
|
||||
</TableCell>
|
||||
<TableCell>{run.version?.version}</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant="outline" className="truncate">
|
||||
{run.origin}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="truncate">
|
||||
<Tooltip>
|
||||
<TooltipTrigger>{getDuration(run.duration)}</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<div>Cold start: {getDuration(run.cold_start_duration)}</div>
|
||||
<div>Run duration: {getDuration(run.run_duration)}</div>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TableCell>
|
||||
<LiveStatus run={run} />
|
||||
</TableRow>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-w-3xl">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Run outputs</DialogTitle>
|
||||
<DialogDescription>
|
||||
You can view your run's outputs here
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="max-h-96 overflow-y-scroll">
|
||||
<RunInputs run={run} />
|
||||
<Suspense>
|
||||
<RunOutputs run_id={run.id} />
|
||||
</Suspense>
|
||||
</div>
|
||||
{/* <div className="max-h-96 overflow-y-scroll">{view}</div> */}
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
import {
|
||||
findAllDeployments,
|
||||
findAllRunsWithCounts,
|
||||
} from "../server/findAllRuns";
|
||||
import { DeploymentDisplay } from "./DeploymentDisplay";
|
||||
import { PaginationControl } from "./PaginationControl";
|
||||
import { RunDisplay } from "./RunDisplay";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -15,6 +8,13 @@ import {
|
||||
} from "@/components/ui/table";
|
||||
import { parseAsInteger } from "next-usequerystate";
|
||||
import { headers } from "next/headers";
|
||||
import {
|
||||
findAllDeployments,
|
||||
findAllRunsWithCounts,
|
||||
} from "../server/findAllRuns";
|
||||
import { DeploymentDisplay } from "./DeploymentDisplay";
|
||||
import { PaginationControl } from "./PaginationControl";
|
||||
import { RunDisplay } from "./RunDisplay";
|
||||
|
||||
const itemPerPage = 6;
|
||||
const pageParser = parseAsInteger.withDefault(1);
|
||||
@@ -33,40 +33,40 @@ export async function RunsTable(props: {
|
||||
offset: (page - 1) * itemPerPage,
|
||||
});
|
||||
return (
|
||||
<div>
|
||||
<div className="overflow-auto h-fit w-full">
|
||||
<Table className="">
|
||||
{allRuns.length == 0 && (
|
||||
<TableCaption>A list of your recent runs.</TableCaption>
|
||||
)}
|
||||
<TableHeader className="bg-background top-0 sticky">
|
||||
<TableRow>
|
||||
<TableHead className="truncate">Number</TableHead>
|
||||
<TableHead className="truncate">Machine</TableHead>
|
||||
<TableHead className="truncate">Time</TableHead>
|
||||
<TableHead className="truncate">Version</TableHead>
|
||||
<TableHead className="truncate">Origin</TableHead>
|
||||
<TableHead className="truncate">Duration</TableHead>
|
||||
<TableHead className="truncate">Live Status</TableHead>
|
||||
<TableHead className="text-right">Status</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{allRuns.map((run) => (
|
||||
<RunDisplay run={run} key={run.id} />
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
<div>
|
||||
<div className="overflow-auto h-fit w-full">
|
||||
<Table className="">
|
||||
{allRuns.length === 0 && (
|
||||
<TableCaption>A list of your recent runs.</TableCaption>
|
||||
)}
|
||||
<TableHeader className="bg-background top-0 sticky">
|
||||
<TableRow>
|
||||
<TableHead className="truncate">Number</TableHead>
|
||||
<TableHead className="truncate">Machine</TableHead>
|
||||
<TableHead className="truncate">Time</TableHead>
|
||||
<TableHead className="truncate">Version</TableHead>
|
||||
<TableHead className="truncate">Origin</TableHead>
|
||||
<TableHead className="truncate">Duration</TableHead>
|
||||
<TableHead className="truncate">Live Status</TableHead>
|
||||
<TableHead className="text-right">Status</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{allRuns.map((run) => (
|
||||
<RunDisplay run={run} key={run.id} />
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
|
||||
{Math.ceil(total / itemPerPage) > 0 && (
|
||||
<PaginationControl
|
||||
totalPage={Math.ceil(total / itemPerPage)}
|
||||
currentPage={page}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
{Math.ceil(total / itemPerPage) > 0 && (
|
||||
<PaginationControl
|
||||
totalPage={Math.ceil(total / itemPerPage)}
|
||||
currentPage={page}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export async function DeploymentsTable(props: { workflow_id: string }) {
|
||||
|
||||
+33
-32
@@ -1,13 +1,13 @@
|
||||
import { relations, type InferSelectModel } from "drizzle-orm";
|
||||
import { type InferSelectModel, relations } from "drizzle-orm";
|
||||
import {
|
||||
text,
|
||||
pgSchema,
|
||||
uuid,
|
||||
integer,
|
||||
timestamp,
|
||||
jsonb,
|
||||
pgEnum,
|
||||
boolean,
|
||||
boolean,
|
||||
integer,
|
||||
jsonb,
|
||||
pgEnum,
|
||||
pgSchema,
|
||||
text,
|
||||
timestamp,
|
||||
uuid,
|
||||
} from "drizzle-orm/pg-core";
|
||||
import { createInsertSchema } from "drizzle-zod";
|
||||
import { z } from "zod";
|
||||
@@ -130,29 +130,30 @@ export const machinesStatus = pgEnum("machine_status", [
|
||||
|
||||
// We still want to keep the workflow run record.
|
||||
export const workflowRunsTable = dbSchema.table("workflow_runs", {
|
||||
id: uuid("id").primaryKey().defaultRandom().notNull(),
|
||||
// when workflow version deleted, still want to keep this record
|
||||
workflow_version_id: uuid("workflow_version_id").references(
|
||||
() => workflowVersionTable.id,
|
||||
{
|
||||
onDelete: "set null",
|
||||
}
|
||||
),
|
||||
workflow_inputs:
|
||||
jsonb("workflow_inputs").$type<Record<string, string | number>>(),
|
||||
workflow_id: uuid("workflow_id")
|
||||
.notNull()
|
||||
.references(() => workflowTable.id, {
|
||||
onDelete: "cascade",
|
||||
}),
|
||||
// when machine deleted, still want to keep this record
|
||||
machine_id: uuid("machine_id").references(() => machinesTable.id, {
|
||||
onDelete: "set null",
|
||||
}),
|
||||
origin: workflowRunOrigin("origin").notNull().default("api"),
|
||||
status: workflowRunStatus("status").notNull().default("not-started"),
|
||||
ended_at: timestamp("ended_at"),
|
||||
created_at: timestamp("created_at").defaultNow().notNull(),
|
||||
id: uuid("id").primaryKey().defaultRandom().notNull(),
|
||||
// when workflow version deleted, still want to keep this record
|
||||
workflow_version_id: uuid("workflow_version_id").references(
|
||||
() => workflowVersionTable.id,
|
||||
{
|
||||
onDelete: "set null",
|
||||
},
|
||||
),
|
||||
workflow_inputs:
|
||||
jsonb("workflow_inputs").$type<Record<string, string | number>>(),
|
||||
workflow_id: uuid("workflow_id")
|
||||
.notNull()
|
||||
.references(() => workflowTable.id, {
|
||||
onDelete: "cascade",
|
||||
}),
|
||||
// when machine deleted, still want to keep this record
|
||||
machine_id: uuid("machine_id").references(() => machinesTable.id, {
|
||||
onDelete: "set null",
|
||||
}),
|
||||
origin: workflowRunOrigin("origin").notNull().default("api"),
|
||||
status: workflowRunStatus("status").notNull().default("not-started"),
|
||||
ended_at: timestamp("ended_at"),
|
||||
created_at: timestamp("created_at").defaultNow().notNull(),
|
||||
started_at: timestamp("started_at"),
|
||||
});
|
||||
|
||||
export const workflowRunRelations = relations(
|
||||
|
||||
+206
-197
@@ -1,11 +1,10 @@
|
||||
"use server";
|
||||
|
||||
import { withServerPromise } from "./withServerPromise";
|
||||
import { db } from "@/db/db";
|
||||
import type {
|
||||
MachineType,
|
||||
WorkflowRunOriginType,
|
||||
WorkflowVersionType,
|
||||
MachineType,
|
||||
WorkflowRunOriginType,
|
||||
WorkflowVersionType,
|
||||
} from "@/db/schema";
|
||||
import { machinesTable, workflowRunsTable } from "@/db/schema";
|
||||
import type { APIKeyUserType } from "@/server/APIKeyBodyRequest";
|
||||
@@ -16,219 +15,229 @@ import { and, eq } from "drizzle-orm";
|
||||
import { revalidatePath } from "next/cache";
|
||||
import "server-only";
|
||||
import { v4 } from "uuid";
|
||||
import { withServerPromise } from "./withServerPromise";
|
||||
|
||||
export const createRun = withServerPromise(
|
||||
async ({
|
||||
origin,
|
||||
workflow_version_id,
|
||||
machine_id,
|
||||
inputs,
|
||||
runOrigin,
|
||||
apiUser,
|
||||
}: {
|
||||
origin: string;
|
||||
workflow_version_id: string | WorkflowVersionType;
|
||||
machine_id: string | MachineType;
|
||||
inputs?: Record<string, string | number>;
|
||||
runOrigin?: WorkflowRunOriginType;
|
||||
apiUser?: APIKeyUserType;
|
||||
}) => {
|
||||
const machine =
|
||||
typeof machine_id === "string"
|
||||
? await db.query.machinesTable.findFirst({
|
||||
where: and(
|
||||
eq(machinesTable.id, machine_id),
|
||||
eq(machinesTable.disabled, false)
|
||||
),
|
||||
})
|
||||
: machine_id;
|
||||
async ({
|
||||
origin,
|
||||
workflow_version_id,
|
||||
machine_id,
|
||||
inputs,
|
||||
runOrigin,
|
||||
apiUser,
|
||||
}: {
|
||||
origin: string;
|
||||
workflow_version_id: string | WorkflowVersionType;
|
||||
machine_id: string | MachineType;
|
||||
inputs?: Record<string, string | number>;
|
||||
runOrigin?: WorkflowRunOriginType;
|
||||
apiUser?: APIKeyUserType;
|
||||
}) => {
|
||||
const machine =
|
||||
typeof machine_id === "string"
|
||||
? await db.query.machinesTable.findFirst({
|
||||
where: and(
|
||||
eq(machinesTable.id, machine_id),
|
||||
eq(machinesTable.disabled, false),
|
||||
),
|
||||
})
|
||||
: machine_id;
|
||||
|
||||
if (!machine) {
|
||||
throw new Error("Machine not found");
|
||||
}
|
||||
if (!machine) {
|
||||
throw new Error("Machine not found");
|
||||
}
|
||||
|
||||
const workflow_version_data =
|
||||
typeof workflow_version_id === "string"
|
||||
? await db.query.workflowVersionTable.findFirst({
|
||||
where: eq(workflowRunsTable.id, workflow_version_id),
|
||||
with: {
|
||||
workflow: {
|
||||
columns: {
|
||||
org_id: true,
|
||||
user_id: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
: workflow_version_id;
|
||||
const workflow_version_data =
|
||||
typeof workflow_version_id === "string"
|
||||
? await db.query.workflowVersionTable.findFirst({
|
||||
where: eq(workflowRunsTable.id, workflow_version_id),
|
||||
with: {
|
||||
workflow: {
|
||||
columns: {
|
||||
org_id: true,
|
||||
user_id: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
: workflow_version_id;
|
||||
|
||||
if (!workflow_version_data) {
|
||||
throw new Error("Workflow version not found");
|
||||
}
|
||||
if (!workflow_version_data) {
|
||||
throw new Error("Workflow version not found");
|
||||
}
|
||||
|
||||
if (apiUser)
|
||||
if (apiUser.org_id) {
|
||||
// is org api call, check org only
|
||||
if (apiUser.org_id != workflow_version_data.workflow.org_id) {
|
||||
throw new Error("Workflow not found");
|
||||
}
|
||||
} else {
|
||||
// is user api call, check user only
|
||||
if (
|
||||
apiUser.user_id != workflow_version_data.workflow.user_id &&
|
||||
workflow_version_data.workflow.org_id == null
|
||||
) {
|
||||
throw new Error("Workflow not found");
|
||||
}
|
||||
}
|
||||
if (apiUser)
|
||||
if (apiUser.org_id) {
|
||||
// is org api call, check org only
|
||||
if (apiUser.org_id != workflow_version_data.workflow.org_id) {
|
||||
throw new Error("Workflow not found");
|
||||
}
|
||||
} else {
|
||||
// is user api call, check user only
|
||||
if (
|
||||
apiUser.user_id != workflow_version_data.workflow.user_id &&
|
||||
workflow_version_data.workflow.org_id == null
|
||||
) {
|
||||
throw new Error("Workflow not found");
|
||||
}
|
||||
}
|
||||
|
||||
const workflow_api = workflow_version_data.workflow_api;
|
||||
const workflow_api = workflow_version_data.workflow_api;
|
||||
|
||||
// Replace the inputs
|
||||
if (inputs && workflow_api) {
|
||||
for (const key in inputs) {
|
||||
Object.entries(workflow_api).forEach(([_, node]) => {
|
||||
if (node.inputs["input_id"] === key) {
|
||||
node.inputs["input_id"] = inputs[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
// Replace the inputs
|
||||
if (inputs && workflow_api) {
|
||||
for (const key in inputs) {
|
||||
Object.entries(workflow_api).forEach(([_, node]) => {
|
||||
if (node.inputs["input_id"] === key) {
|
||||
node.inputs["input_id"] = inputs[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let prompt_id: string | undefined = undefined;
|
||||
const shareData = {
|
||||
workflow_api: workflow_api,
|
||||
status_endpoint: `${origin}/api/update-run`,
|
||||
file_upload_endpoint: `${origin}/api/file-upload`,
|
||||
};
|
||||
let prompt_id: string | undefined = undefined;
|
||||
const shareData = {
|
||||
workflow_api: workflow_api,
|
||||
status_endpoint: `${origin}/api/update-run`,
|
||||
file_upload_endpoint: `${origin}/api/file-upload`,
|
||||
};
|
||||
|
||||
prompt_id = v4();
|
||||
prompt_id = v4();
|
||||
|
||||
// Add to our db
|
||||
const workflow_run = await db
|
||||
.insert(workflowRunsTable)
|
||||
.values({
|
||||
id: prompt_id,
|
||||
workflow_id: workflow_version_data.workflow_id,
|
||||
workflow_version_id: workflow_version_data.id,
|
||||
workflow_inputs: inputs,
|
||||
machine_id: machine.id,
|
||||
origin: runOrigin,
|
||||
})
|
||||
.returning();
|
||||
// Add to our db
|
||||
const workflow_run = await db
|
||||
.insert(workflowRunsTable)
|
||||
.values({
|
||||
id: prompt_id,
|
||||
workflow_id: workflow_version_data.workflow_id,
|
||||
workflow_version_id: workflow_version_data.id,
|
||||
workflow_inputs: inputs,
|
||||
machine_id: machine.id,
|
||||
origin: runOrigin,
|
||||
})
|
||||
.returning();
|
||||
|
||||
revalidatePath(`/${workflow_version_data.workflow_id}`);
|
||||
revalidatePath(`/${workflow_version_data.workflow_id}`);
|
||||
|
||||
try {
|
||||
switch (machine.type) {
|
||||
case "comfy-deploy-serverless":
|
||||
case "modal-serverless":
|
||||
const _data = {
|
||||
input: {
|
||||
...shareData,
|
||||
prompt_id: prompt_id,
|
||||
},
|
||||
};
|
||||
try {
|
||||
switch (machine.type) {
|
||||
case "comfy-deploy-serverless":
|
||||
case "modal-serverless":
|
||||
const _data = {
|
||||
input: {
|
||||
...shareData,
|
||||
prompt_id: prompt_id,
|
||||
},
|
||||
};
|
||||
|
||||
const ___result = await fetch(`${machine.endpoint}/run`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(_data),
|
||||
cache: "no-store",
|
||||
});
|
||||
console.log(___result);
|
||||
if (!___result.ok)
|
||||
throw new Error(
|
||||
`Error creating run, ${
|
||||
___result.statusText
|
||||
} ${await ___result.text()}`
|
||||
);
|
||||
console.log(_data, ___result);
|
||||
break;
|
||||
case "runpod-serverless":
|
||||
const data = {
|
||||
input: {
|
||||
...shareData,
|
||||
prompt_id: prompt_id,
|
||||
},
|
||||
};
|
||||
const ___result = await fetch(`${machine.endpoint}/run`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(_data),
|
||||
cache: "no-store",
|
||||
});
|
||||
console.log(___result);
|
||||
if (!___result.ok)
|
||||
throw new Error(
|
||||
`Error creating run, ${
|
||||
___result.statusText
|
||||
} ${await ___result.text()}`,
|
||||
);
|
||||
console.log(_data, ___result);
|
||||
break;
|
||||
case "runpod-serverless":
|
||||
const data = {
|
||||
input: {
|
||||
...shareData,
|
||||
prompt_id: prompt_id,
|
||||
},
|
||||
};
|
||||
|
||||
if (
|
||||
!machine.auth_token &&
|
||||
!machine.endpoint.includes("localhost") &&
|
||||
!machine.endpoint.includes("127.0.0.1")
|
||||
) {
|
||||
throw new Error("Machine auth token not found");
|
||||
}
|
||||
if (
|
||||
!machine.auth_token &&
|
||||
!machine.endpoint.includes("localhost") &&
|
||||
!machine.endpoint.includes("127.0.0.1")
|
||||
) {
|
||||
throw new Error("Machine auth token not found");
|
||||
}
|
||||
|
||||
const __result = await fetch(`${machine.endpoint}/run`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${machine.auth_token}`,
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
cache: "no-store",
|
||||
});
|
||||
console.log(__result);
|
||||
if (!__result.ok)
|
||||
throw new Error(
|
||||
`Error creating run, ${
|
||||
__result.statusText
|
||||
} ${await __result.text()}`
|
||||
);
|
||||
console.log(data, __result);
|
||||
break;
|
||||
case "classic":
|
||||
const body = {
|
||||
...shareData,
|
||||
prompt_id: prompt_id,
|
||||
};
|
||||
// console.log(body);
|
||||
const comfyui_endpoint = `${machine.endpoint}/comfyui-deploy/run`;
|
||||
const _result = await fetch(comfyui_endpoint, {
|
||||
method: "POST",
|
||||
body: JSON.stringify(body),
|
||||
cache: "no-store",
|
||||
});
|
||||
// console.log(_result);
|
||||
const __result = await fetch(`${machine.endpoint}/run`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${machine.auth_token}`,
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
cache: "no-store",
|
||||
});
|
||||
console.log(__result);
|
||||
if (!__result.ok)
|
||||
throw new Error(
|
||||
`Error creating run, ${
|
||||
__result.statusText
|
||||
} ${await __result.text()}`,
|
||||
);
|
||||
console.log(data, __result);
|
||||
break;
|
||||
case "classic":
|
||||
const body = {
|
||||
...shareData,
|
||||
prompt_id: prompt_id,
|
||||
};
|
||||
// console.log(body);
|
||||
const comfyui_endpoint = `${machine.endpoint}/comfyui-deploy/run`;
|
||||
const _result = await fetch(comfyui_endpoint, {
|
||||
method: "POST",
|
||||
body: JSON.stringify(body),
|
||||
cache: "no-store",
|
||||
});
|
||||
// console.log(_result);
|
||||
|
||||
if (!_result.ok) {
|
||||
let message = `Error creating run, ${_result.statusText}`;
|
||||
try {
|
||||
const result = await ComfyAPI_Run.parseAsync(
|
||||
await _result.json()
|
||||
);
|
||||
message += ` ${result.node_errors}`;
|
||||
} catch (error) {}
|
||||
throw new Error(message);
|
||||
}
|
||||
// prompt_id = result.prompt_id;
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
await db
|
||||
.update(workflowRunsTable)
|
||||
.set({
|
||||
status: "failed",
|
||||
})
|
||||
.where(eq(workflowRunsTable.id, workflow_run[0].id));
|
||||
throw e;
|
||||
}
|
||||
if (!_result.ok) {
|
||||
let message = `Error creating run, ${_result.statusText}`;
|
||||
try {
|
||||
const result = await ComfyAPI_Run.parseAsync(
|
||||
await _result.json(),
|
||||
);
|
||||
message += ` ${result.node_errors}`;
|
||||
} catch (error) {}
|
||||
throw new Error(message);
|
||||
}
|
||||
// prompt_id = result.prompt_id;
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
await db
|
||||
.update(workflowRunsTable)
|
||||
.set({
|
||||
status: "failed",
|
||||
})
|
||||
.where(eq(workflowRunsTable.id, workflow_run[0].id));
|
||||
throw e;
|
||||
}
|
||||
|
||||
return {
|
||||
workflow_run_id: workflow_run[0].id,
|
||||
message: "Successful workflow run",
|
||||
};
|
||||
}
|
||||
// It successfully started, update the started_at time
|
||||
|
||||
await db
|
||||
.update(workflowRunsTable)
|
||||
.set({
|
||||
started_at: new Date(),
|
||||
})
|
||||
.where(eq(workflowRunsTable.id, workflow_run[0].id));
|
||||
|
||||
return {
|
||||
workflow_run_id: workflow_run[0].id,
|
||||
message: "Successful workflow run",
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
export async function checkStatus(run_id: string) {
|
||||
const { userId } = auth();
|
||||
if (!userId) throw new Error("User not found");
|
||||
const { userId } = auth();
|
||||
if (!userId) throw new Error("User not found");
|
||||
|
||||
return await getRunsData(run_id);
|
||||
return await getRunsData(run_id);
|
||||
}
|
||||
|
||||
@@ -16,32 +16,42 @@ export async function findAllRuns({
|
||||
offset = 0,
|
||||
}: RunsSearchTypes) {
|
||||
return await db.query.workflowRunsTable.findMany({
|
||||
where: eq(workflowRunsTable.workflow_id, workflow_id),
|
||||
orderBy: desc(workflowRunsTable.created_at),
|
||||
offset: offset,
|
||||
limit: limit,
|
||||
extras: {
|
||||
number: sql<number>`row_number() over (order by created_at)`.as("number"),
|
||||
total: sql<number>`count(*) over ()`.as("total"),
|
||||
duration:
|
||||
sql<number>`(extract(epoch from ended_at) - extract(epoch from created_at))`.as(
|
||||
"duration"
|
||||
),
|
||||
},
|
||||
with: {
|
||||
machine: {
|
||||
columns: {
|
||||
name: true,
|
||||
endpoint: true,
|
||||
},
|
||||
},
|
||||
version: {
|
||||
columns: {
|
||||
version: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
where: eq(workflowRunsTable.workflow_id, workflow_id),
|
||||
orderBy: desc(workflowRunsTable.created_at),
|
||||
offset: offset,
|
||||
limit: limit,
|
||||
extras: {
|
||||
number: sql<number>`row_number() over (order by created_at)`.as(
|
||||
"number",
|
||||
),
|
||||
total: sql<number>`count(*) over ()`.as("total"),
|
||||
duration:
|
||||
sql<number>`(extract(epoch from ended_at) - extract(epoch from created_at))`.as(
|
||||
"duration",
|
||||
),
|
||||
cold_start_duration:
|
||||
sql<number>`(extract(epoch from started_at) - extract(epoch from created_at))`.as(
|
||||
"cold_start_duration",
|
||||
),
|
||||
run_duration:
|
||||
sql<number>`(extract(epoch from ended_at) - extract(epoch from started_at))`.as(
|
||||
"run_duration",
|
||||
),
|
||||
},
|
||||
with: {
|
||||
machine: {
|
||||
columns: {
|
||||
name: true,
|
||||
endpoint: true,
|
||||
},
|
||||
},
|
||||
version: {
|
||||
columns: {
|
||||
version: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function findAllRunsWithCounts(props: RunsSearchTypes) {
|
||||
|
||||
Reference in New Issue
Block a user