feat: display runs and create run and update run endpoint
This commit is contained in:
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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 />;
|
||||
|
||||
Reference in New Issue
Block a user