WIP on Rerun/continue functionality

This commit is contained in:
Matt Aitken
2023-06-14 12:46:17 +01:00
parent 4903cfc689
commit d4e39de67e
2 changed files with 136 additions and 8 deletions
@@ -1,5 +1,5 @@
import { BoltIcon } from "@heroicons/react/24/solid";
import { Outlet, useNavigate, useRevalidator } from "@remix-run/react";
import { Form, Outlet, useNavigate, useRevalidator } from "@remix-run/react";
import { LoaderArgs } from "@remix-run/server-runtime";
import { useCallback, useEffect, useMemo } from "react";
import { redirect, typedjson, useTypedLoaderData } from "remix-typedjson";
@@ -62,7 +62,13 @@ import {
import { TaskCard } from "./TaskCard";
import { TaskCardSkeleton } from "./TaskCardSkeleton";
import { useEventSource } from "remix-utils";
import { Button } from "~/components/primitives/Buttons";
import { Button, ButtonContent } from "~/components/primitives/Buttons";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "~/components/primitives/Popover";
import { conform } from "@conform-to/react";
export const loader = async ({ request, params }: LoaderArgs) => {
const userId = await requireUserId(request);
@@ -185,10 +191,57 @@ export default function Page() {
Test run
</span>
)}
<Button variant="primary/small" shortcut="R">
Rerun Job
</Button>
{(basicStatus === "COMPLETED" || basicStatus === "FAILED") && (
<Popover>
<PopoverTrigger>
<ButtonContent variant="primary/small" shortcut="R">
Rerun Job
</ButtonContent>
</PopoverTrigger>
<PopoverContent
className="flex w-80 flex-col gap-2 p-4"
align="end"
>
{run.environment.type === "PRODUCTION" && (
<Callout variant="warning">
This will rerun this job in your Production environment.
</Callout>
)}
<Form method="post">
<div className="flex flex-col items-start gap-4 divide-y divide-slate-600">
<div>
<Paragraph variant="small" className="mb-2">
Create a new run with the same configuration and
Trigger payload.
</Paragraph>
<Button
variant="primary/small"
type="submit"
name={conform.INTENT}
value="start"
>
Rerun from the start
</Button>
</div>
<div className="pt-4">
<Paragraph variant="small" className="mb-2">
Continue this run from the last successfully completed
task, retrying where it got to.
</Paragraph>
<Button
variant="primary/small"
type="submit"
name={conform.INTENT}
value="continue"
>
Continue run
</Button>
</div>
</div>
</Form>
</PopoverContent>
</Popover>
)}
</PageButtons>
</PageTitleRow>
<PageInfoRow>
@@ -231,7 +284,7 @@ export default function Page() {
</PageHeader>
<PageBody scrollable={false}>
<div className="grid h-full grid-cols-2 gap-4">
<div className="flex flex-col gap-6 overflow-y-auto py-4 pl-4">
<div className="flex flex-col gap-6 overflow-y-auto py-4 pl-4 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-slate-700">
<div>
<Header2 className="mb-2">Trigger</Header2>
<RunPanel
@@ -356,7 +409,7 @@ export default function Page() {
</div>
{/* Detail view */}
<div className="overflow-y-auto py-4 pr-4">
<div className="overflow-y-auto py-4 pr-4 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-slate-700">
<Header2 className="mb-2">Detail</Header2>
{selectedId ? (
<Outlet />
@@ -0,0 +1,75 @@
import { EventSpecificationSchema } from "@/../../packages/internal/src";
import { PrismaClient, prisma } from "~/db.server";
import { CreateRunService } from "../runs/createRun.server";
export class ReRunService {
#prismaClient: PrismaClient;
constructor(prismaClient: PrismaClient = prisma) {
this.#prismaClient = prismaClient;
}
public async call({ runId }: { runId: string }) {
try {
return await this.#prismaClient.$transaction(async (tx) => {
//get the run info required for a rerun
const existingRun = await tx.jobRun.findUniqueOrThrow({
include: {
organization: true,
project: true,
environment: true,
version: true,
job: true,
event: true,
},
where: {
id: runId,
},
});
const eventLog = await this.#prismaClient.eventRecord.create({
data: {
organization: {
connect: {
id: existingRun.environment.organizationId,
},
},
project: {
connect: {
id: existingRun.environment.projectId,
},
},
environment: {
connect: {
id: existingRun.environment.id,
},
},
eventId: `${
existingRun.event.eventId
}:retry:${new Date().getTime()}`,
name: existingRun.event.name,
timestamp: new Date(),
payload: existingRun.event.payload ?? {},
context: existingRun.event.context ?? {},
source: existingRun.event.source,
isTest: existingRun.event.isTest,
},
});
const createRunService = new CreateRunService(tx);
return createRunService.call({
environment: {
...existingRun.environment,
organization: existingRun.organization,
project: existingRun.project,
},
eventId: eventLog.id,
job: existingRun.job,
version: existingRun.version,
});
});
} catch (error) {
throw error;
}
}
}