feat: add update failed display when the graph execution error

This commit is contained in:
BennyKok 2023-12-15 16:16:35 +08:00
parent ccf167d48e
commit 23db3c1a45
8 changed files with 110 additions and 49 deletions

View File

@ -162,6 +162,10 @@ async def send_json_override(self, event, data, sid=None):
if event == 'executing' and data.get('node') is None: if event == 'executing' and data.get('node') is None:
update_run(prompt_id, Status.SUCCESS) update_run(prompt_id, Status.SUCCESS)
if event == 'execution_error':
update_run(prompt_id, Status.FAILED)
asyncio.create_task(update_run_with_output(prompt_id, data))
if event == 'executed' and 'node' in data and 'output' in data: if event == 'executed' and 'node' in data and 'output' in data:
asyncio.create_task(update_run_with_output(prompt_id, data.get('output'))) asyncio.create_task(update_run_with_output(prompt_id, data.get('output')))
# update_run_with_output(prompt_id, data.get('output')) # update_run_with_output(prompt_id, data.get('output'))
@ -178,6 +182,11 @@ def update_run(prompt_id, status: Status):
return return
if ('status' not in prompt_metadata[prompt_id] or prompt_metadata[prompt_id]['status'] != status): if ('status' not in prompt_metadata[prompt_id] or prompt_metadata[prompt_id]['status'] != status):
# when the status is already failed, we don't want to update it to success
if ('status' in prompt_metadata[prompt_id] and prompt_metadata[prompt_id]['status'] == Status.FAILED):
return
status_endpoint = prompt_metadata[prompt_id]['status_endpoint'] status_endpoint = prompt_metadata[prompt_id]['status_endpoint']
body = { body = {
"run_id": prompt_id, "run_id": prompt_id,

View File

@ -75,7 +75,7 @@
.shiki { .shiki {
/* @apply rounded-lg p-2 overflow-x-scroll */ /* @apply rounded-lg p-2 overflow-x-scroll */
@apply rounded-lg p-2 overflow-hidden @apply p-2 max-w-full overflow-auto w-full
} }
@layer base { @layer base {

View File

@ -8,12 +8,12 @@ export async function CodeBlock(props: { code: string; lang: Lang }) {
}); });
return ( return (
<div className="relative w-full max-w-full text-sm"> <div className="relative w-full text-sm">
{/* max-w-[calc(32rem-1.5rem-1.5rem)] */} {/* max-w-[calc(32rem-1.5rem-1.5rem)] */}
{/* <div className=""> */} {/* <div className=""> */}
<p <p
// tabIndex={1} // tabIndex={1}
className="[&>pre]:p-4 rounded-sm " className="[&>pre]:p-4 rounded-lg max-h-96 overflow-auto w-full"
style={{ style={{
overflowWrap: "break-word", overflowWrap: "break-word",
}} }}

View File

@ -0,0 +1,41 @@
"use client";
import { useStore } from "@/components/MachinesWS";
import { StatusBadge } from "@/components/StatusBadge";
import { TableCell } from "@/components/ui/table";
import { type findAllRuns } from "@/server/findAllRuns";
export function LiveStatus({
run,
}: {
run: Awaited<ReturnType<typeof findAllRuns>>[0];
}) {
const data = useStore(
(state) =>
state.data
.filter((x) => x.id === run.id)
.sort((a, b) => b.timestamp - a.timestamp)?.[0]
);
let status = run.status;
// const [view, setView] = useState<any>();
if (data?.json.event == "executing" && data.json.data.node == undefined) {
status = "success";
} else if (data?.json.event == "executing") {
status = "running";
}
return (
<>
<TableCell>
{data && status != "success"
? `${data.json.event} - ${data.json.data.node}`
: "-"}
</TableCell>
<TableCell className="text-right">
<StatusBadge status={status} />
</TableCell>
</>
);
}

View File

@ -1,8 +1,6 @@
"use client"; "use client";
import { RunOutputs } from "./RunOutputs"; import { LiveStatus } from "./LiveStatus";
import { useStore } from "@/components/MachinesWS";
import { StatusBadge } from "@/components/StatusBadge";
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@ -14,52 +12,44 @@ import {
import { TableCell, TableRow } from "@/components/ui/table"; import { TableCell, TableRow } from "@/components/ui/table";
import { getRelativeTime } from "@/lib/getRelativeTime"; import { getRelativeTime } from "@/lib/getRelativeTime";
import { type findAllRuns } from "@/server/findAllRuns"; import { type findAllRuns } from "@/server/findAllRuns";
import { getRunsOutputDisplay } from "@/server/getRunsOutput";
import { useState } from "react";
export function RunDisplay({ export function RunDisplay({
run, run,
}: { }: {
run: Awaited<ReturnType<typeof findAllRuns>>[0]; run: Awaited<ReturnType<typeof findAllRuns>>[0];
}) { }) {
const data = useStore( const [view, setView] = useState<any>();
(state) =>
state.data
.filter((x) => x.id === run.id)
.sort((a, b) => b.timestamp - a.timestamp)?.[0]
);
let status = run.status;
if (data?.json.event == "executing" && data.json.data.node == undefined) {
status = "success";
} else if (data?.json.event == "executing") {
status = "running";
}
return ( return (
<Dialog> <Dialog>
<DialogTrigger asChild className="appearance-none hover:cursor-pointer"> <DialogTrigger
asChild
className="appearance-none hover:cursor-pointer"
onClick={async () => {
if (view) return;
const _view = await getRunsOutputDisplay(run.id);
setView(_view);
}}
>
<TableRow> <TableRow>
<TableCell>{run.version?.version}</TableCell> <TableCell>{run.version?.version}</TableCell>
<TableCell className="font-medium">{run.machine?.name}</TableCell> <TableCell className="font-medium">{run.machine?.name}</TableCell>
<TableCell>{getRelativeTime(run.created_at)}</TableCell> <TableCell>{getRelativeTime(run.created_at)}</TableCell>
<TableCell> <LiveStatus run={run} />
{data && status != "success"
? `${data.json.event} - ${data.json.data.node}`
: "-"}
</TableCell>
<TableCell className="text-right">
<StatusBadge status={status} />
</TableCell>
</TableRow> </TableRow>
</DialogTrigger> </DialogTrigger>
<DialogContent> <DialogContent className="max-w-3xl">
<DialogHeader> <DialogHeader>
<DialogTitle>Run outputs</DialogTitle> <DialogTitle>Run outputs</DialogTitle>
<DialogDescription> <DialogDescription>
You can view your run&apos;s outputs here You can view your run&apos;s outputs here
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
{/* <Suspense>
<RunOutputs run_id={run.id} /> <RunOutputs run_id={run.id} />
</Suspense> */}
{view}
</DialogContent> </DialogContent>
</Dialog> </Dialog>
); );

View File

@ -1,7 +1,5 @@
"use client";
import { OutputRender } from "./RunDisplay"; import { OutputRender } from "./RunDisplay";
import { callServerPromise } from "@/components/MachineList"; import { CodeBlock } from "@/components/CodeBlock";
import { import {
Table, Table,
TableBody, TableBody,
@ -11,22 +9,24 @@ import {
TableRow, TableRow,
} from "@/components/ui/table"; } from "@/components/ui/table";
import { getRunsOutput } from "@/server/getRunsOutput"; import { getRunsOutput } from "@/server/getRunsOutput";
import { useEffect, useState } from "react";
export function RunOutputs({ run_id }: { run_id: string }) { export async function RunOutputs({ run_id }: { run_id: string }) {
const [outputs, setOutputs] = const outputs = await getRunsOutput(run_id);
useState<Awaited<ReturnType<typeof getRunsOutput>>>(); console.log("Getting runs out put");
useEffect(() => { // const [outputs, setOutputs] =
if (!run_id) return; // useState<Awaited<ReturnType<typeof getRunsOutput>>>();
// fetch(`/api/run?run_id=${run_id}`)
// .then((x) => x.json()) // useEffect(() => {
// .then((x) => setOutputs(x)); // if (!run_id) return;
callServerPromise(getRunsOutput(run_id).then((x) => setOutputs(x))); // // fetch(`/api/run?run_id=${run_id}`)
}, [run_id]); // // .then((x) => x.json())
// // .then((x) => setOutputs(x));
// callServerPromise(getRunsOutput(run_id).then((x) => setOutputs(x)));
// }, [run_id]);
return ( return (
<Table> <Table className="table-fixed">
{/* <TableCaption>A list of your recent runs.</TableCaption> */} {/* <TableCaption>A list of your recent runs.</TableCaption> */}
<TableHeader className="bg-background top-0 sticky"> <TableHeader className="bg-background top-0 sticky">
<TableRow> <TableRow>
@ -36,11 +36,25 @@ export function RunOutputs({ run_id }: { run_id: string }) {
</TableHeader> </TableHeader>
<TableBody> <TableBody>
{outputs?.map((run) => { {outputs?.map((run) => {
const fileName = run.data.images[0].filename; const fileName = run.data.images?.[0].filename;
if (!fileName)
return (
<TableRow key={run.id}>
<TableCell>Output</TableCell>
<TableCell className="max-h-44">
<CodeBlock
code={JSON.stringify(run.data, null, 2)}
lang="json"
/>
</TableCell>
</TableRow>
);
// const filePath // const filePath
return ( return (
<TableRow key={run.id}> <TableRow key={run.id}>
<TableCell>{fileName}</TableCell> <TableCell className="break-words">{fileName}</TableCell>
<TableCell> <TableCell>
<OutputRender run_id={run_id} filename={fileName} /> <OutputRender run_id={run_id} filename={fileName} />
</TableCell> </TableCell>

View File

@ -60,6 +60,8 @@ export async function createRun(
} }
} }
console.log(workflow_api);
// Sending to comfyui // Sending to comfyui
const result = await fetch(comfyui_endpoint, { const result = await fetch(comfyui_endpoint, {
method: "POST", method: "POST",

View File

@ -1,9 +1,14 @@
"use server"; "use server";
import { RunOutputs } from "@/components/RunOutputs";
import { db } from "@/db/db"; import { db } from "@/db/db";
import { workflowRunOutputs, workflowRunsTable } from "@/db/schema"; import { workflowRunOutputs, workflowRunsTable } from "@/db/schema";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
export async function getRunsOutputDisplay(run_id: string) {
return <RunOutputs run_id={run_id} />;
}
export async function getRunsOutput(run_id: string) { export async function getRunsOutput(run_id: string) {
// throw new Error("Not implemented"); // throw new Error("Not implemented");
return await db return await db