Files
2026-07-13 13:32:57 +08:00

101 lines
2.7 KiB
TypeScript

import { $transaction, type PrismaClientOrTransaction, prisma } from "~/db.server";
import { type AuthenticatedEnvironment } from "~/services/apiAuth.server";
import { logger } from "~/services/logger.server";
import { isCancellableRunStatus } from "../taskStatus";
import { BaseService } from "./baseService.server";
import { FinalizeTaskRunService } from "./finalizeTaskRun.server";
export class CancelAttemptService extends BaseService {
public async call(
attemptId: string,
taskRunId: string,
cancelledAt: Date,
reason: string,
env?: AuthenticatedEnvironment
) {
let environment: AuthenticatedEnvironment | undefined = env;
if (!environment) {
environment = await getAuthenticatedEnvironmentFromAttempt(attemptId);
if (!environment) {
return;
}
}
return await this.traceWithEnv("call()", environment, async (span) => {
span.setAttribute("taskRunId", taskRunId);
span.setAttribute("attemptId", attemptId);
const taskRunAttempt = await this._prisma.taskRunAttempt.findFirst({
where: {
friendlyId: attemptId,
},
include: {
taskRun: true,
},
});
if (!taskRunAttempt) {
return;
}
if (taskRunAttempt.status === "CANCELED") {
logger.warn("Task run attempt is already cancelled", {
attemptId,
});
return;
}
await $transaction(this._prisma, "cancel attempt", async (tx) => {
await tx.taskRunAttempt.update({
where: {
friendlyId: attemptId,
},
data: {
status: "CANCELED",
completedAt: cancelledAt,
},
});
const isCancellable = isCancellableRunStatus(taskRunAttempt.taskRun.status);
const finalizeService = new FinalizeTaskRunService(tx);
await finalizeService.call({
id: taskRunId,
status: isCancellable ? "INTERRUPTED" : undefined,
completedAt: isCancellable ? cancelledAt : undefined,
attemptStatus: isCancellable ? "CANCELED" : undefined,
error: isCancellable ? { type: "STRING_ERROR", raw: reason } : undefined,
});
});
});
}
}
async function getAuthenticatedEnvironmentFromAttempt(
friendlyId: string,
prismaClient?: PrismaClientOrTransaction
) {
const taskRunAttempt = await (prismaClient ?? prisma).taskRunAttempt.findFirst({
where: {
friendlyId,
},
include: {
runtimeEnvironment: {
include: {
organization: true,
project: true,
},
},
},
});
if (!taskRunAttempt) {
return;
}
return taskRunAttempt?.runtimeEnvironment;
}