feat: display runs and create run and update run endpoint

This commit is contained in:
BennyKok
2023-12-10 16:06:20 +08:00
parent 6a1c1d0ff5
commit 9c8a518c46
11 changed files with 335 additions and 219 deletions
+76 -8
View File
@@ -1,5 +1,8 @@
import { MachineSelect, VersionSelect } from "@/components/VersionSelect";
import { Button } from "@/components/ui/button";
import {
MachineSelect,
RunWorkflowButton,
VersionSelect,
} from "@/components/VersionSelect";
import {
Card,
CardContent,
@@ -7,12 +10,24 @@ import {
CardHeader,
CardTitle,
} from "@/components/ui/card";
import {
Table,
TableBody,
TableCaption,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { db } from "@/db/db";
import { workflowTable, workflowVersionTable } from "@/db/schema";
import {
workflowRunsTable,
workflowTable,
workflowVersionTable,
} from "@/db/schema";
import { getRelativeTime } from "@/lib/getRelativeTime";
import { getMachines } from "@/server/curdMachine";
import { desc, eq } from "drizzle-orm";
import { Play } from "lucide-react";
export async function findFirstTableWithVersion(workflow_id: string) {
return await db.query.workflowTable.findFirst({
@@ -21,6 +36,32 @@ export async function findFirstTableWithVersion(workflow_id: string) {
});
}
export async function findAllRuns(workflow_id: string) {
const workflowVersion = await db.query.workflowVersionTable.findFirst({
where: eq(workflowVersionTable.workflow_id, workflow_id),
});
if (!workflowVersion) {
return [];
}
return await db.query.workflowRunsTable.findMany({
where: eq(workflowRunsTable.workflow_version_id, workflowVersion?.id),
with: {
machine: {
columns: {
name: true,
},
},
version: {
columns: {
version: true,
},
},
},
});
}
export default async function Page({
params,
}: {
@@ -45,9 +86,7 @@ export default async function Page({
<div className="flex gap-2 ">
<VersionSelect workflow={workflow} />
<MachineSelect machines={machines} />
<Button className="gap-2">
Run <Play size={14} />
</Button>
<RunWorkflowButton workflow={workflow} machines={machines} />
</div>
</CardContent>
</Card>
@@ -57,8 +96,37 @@ export default async function Page({
<CardTitle>Run</CardTitle>
</CardHeader>
<CardContent />
<CardContent>
<RunsTable workflow_id={workflow_id} />
</CardContent>
</Card>
</div>
);
}
async function RunsTable(props: { workflow_id: string }) {
const allRuns = await findAllRuns(props.workflow_id);
return (
<Table>
<TableCaption>A list of your recent runs.</TableCaption>
<TableHeader>
<TableRow>
<TableHead className="w-[100px]">Version</TableHead>
<TableHead>Machine</TableHead>
<TableHead>Time</TableHead>
<TableHead className="text-right">Status</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{allRuns.map((run) => (
<TableRow key={run.id}>
<TableCell>{run.version.version}</TableCell>
<TableCell className="font-medium">{run.machine.name}</TableCell>
<TableCell>{getRelativeTime(run.created_at)}</TableCell>
<TableCell className="text-right">{run.status}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
);
}
+76 -26
View File
@@ -1,56 +1,106 @@
import { parseDataSafe } from "../../../lib/parseDataSafe";
import { db } from "@/db/db";
import {
workflowRunStatus,
workflowRunsTable,
workflowTable,
workflowVersionTable,
} from "@/db/schema";
import { eq, sql } from "drizzle-orm";
import { workflowRunsTable } from "@/db/schema";
import { eq } from "drizzle-orm";
import { revalidatePath } from "next/cache";
import { NextResponse } from "next/server";
import { ZodFormattedError, z } from "zod";
import { z } from "zod";
const Request = z.object({
workflow_version_id: z.string(),
// workflow_version: z.number().optional(),
machine_id: z.string(),
});
export async function OPTIONS(request: Request) {
return new Response(null, {
status: 204,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
},
});
}
const ComfyAPI_Run = z.object({
prompt_id: z.string(),
number: z.number(),
node_errors: z.any(),
});
export async function POST(request: Request) {
const [data, error] = await parseDataSafe(Request, request);
if (!data || error) return error;
let { workflow_version_id, machine_id } = data;
const origin = new URL(request.url).origin;
const { workflow_version_id, machine_id } = data;
const machine = await db.query.machinesTable.findFirst({
where: eq(workflowRunsTable.id, machine_id),
});
if (!machine) {
return new Response("Machine not found", {
status: 404,
});
}
const workflow_version_data =
// workflow_version_id
// ?
await db.query.workflowVersionTable.findFirst({
where: eq(workflowRunsTable.id, workflow_version_id),
});
// : workflow_version != undefined
// ? await db.query.workflowVersionTable.findFirst({
// where: and(
// eq(workflowVersionTable.version, workflow_version),
// eq(workflowVersionTable.workflow_id)
// ),
// })
// : null;
if (!workflow_version_data) {
return new Response("Workflow version not found", {
status: 404,
});
}
const comfyui_endpoint = `${machine.endpoint}/comfy-deploy/run`;
// Sending to comfyui
const result = await fetch(comfyui_endpoint, {
method: "POST",
// headers: {
// "Content-Type": "application/json",
// },
body: JSON.stringify({
workflow_api: workflow_version_data.workflow_api,
status_endpoint: `${origin}/api/update-run`,
}),
})
.then(async (res) => ComfyAPI_Run.parseAsync(await res.json()))
.catch((error) => {
console.error(error);
return new Response(error.details, {
status: 500,
});
});
// return the error
if (result instanceof Response) {
return result;
}
// Add to our db
const workflow_run = await db
.insert(workflowRunsTable)
.values({
workflow_version_id,
id: result.prompt_id,
workflow_version_id: workflow_version_data.id,
machine_id,
})
.returning();
revalidatePath(`./${workflow_version_data.workflow_id}`);
return NextResponse.json(
{
workflow_run_id: workflow_run[0].id,
},
{
status: 200,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
},
},
}
);
}
+9 -17
View File
@@ -2,6 +2,7 @@ import { parseDataSafe } from "../../../lib/parseDataSafe";
import { db } from "@/db/db";
import { workflowRunsTable } from "@/db/schema";
import { eq } from "drizzle-orm";
import { revalidatePath } from "next/cache";
import { NextResponse } from "next/server";
import { z } from "zod";
@@ -10,17 +11,6 @@ const Request = z.object({
status: z.enum(["not-started", "running", "success", "failed"]),
});
export async function OPTIONS(request: Request) {
return new Response(null, {
status: 204,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
},
});
}
export async function POST(request: Request) {
const [data, error] = await parseDataSafe(Request, request);
if (!data || error) return error;
@@ -32,7 +22,14 @@ export async function POST(request: Request) {
.set({
status: status,
})
.where(eq(workflowRunsTable.id, run_id));
.where(eq(workflowRunsTable.id, run_id))
.returning();
const workflow_version = await db.query.workflowVersionTable.findFirst({
where: eq(workflowRunsTable.id, workflow_run[0].workflow_version_id),
});
revalidatePath(`./${workflow_version?.workflow_id}`);
return NextResponse.json(
{
@@ -40,11 +37,6 @@ export async function POST(request: Request) {
},
{
status: 200,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
},
}
);
}
+1 -1
View File
@@ -2,7 +2,7 @@ import { WorkflowList } from "@/components/WorkflowList";
import { db } from "@/db/db";
import { usersTable, workflowTable, workflowVersionTable } from "@/db/schema";
import { auth, clerkClient } from "@clerk/nextjs";
import { desc, eq, sql } from "drizzle-orm";
import { desc, eq } from "drizzle-orm";
export default function Home() {
return <WorkflowServer />;