98 lines
2.9 KiB
TypeScript
98 lines
2.9 KiB
TypeScript
import { type RunStore } from "@internal/run-store";
|
|
import { type Prisma, type ProjectAlertChannel } from "@trigger.dev/database";
|
|
import { type PrismaClientOrTransaction, type prisma } from "~/db.server";
|
|
import { alertsWorker } from "~/v3/alertsWorker.server";
|
|
import type { ControlPlaneResolver } from "~/v3/runOpsMigration/controlPlaneResolver.server";
|
|
import { controlPlaneResolver as defaultControlPlaneResolver } from "~/v3/runOpsMigration/controlPlaneResolver.server";
|
|
import { BaseService } from "../baseService.server";
|
|
import { DeliverAlertService } from "./deliverAlert.server";
|
|
|
|
// The alert hydration reads only run-ops scalars (id/projectId/runtimeEnvironmentId); the env's
|
|
// type (and its parent's) is resolved via the control-plane resolver so the run-ops DB can split
|
|
// without a cross-provider join. The prior `lockedBy` + `runtimeEnvironment` includes were unused.
|
|
type FoundRun = Prisma.Result<
|
|
typeof prisma.taskRun,
|
|
{ select: { id: true; projectId: true; runtimeEnvironmentId: true } },
|
|
"findUniqueOrThrow"
|
|
>;
|
|
|
|
export class PerformTaskRunAlertsService extends BaseService {
|
|
#controlPlaneResolver: ControlPlaneResolver;
|
|
|
|
constructor(
|
|
opts: {
|
|
prisma?: PrismaClientOrTransaction;
|
|
replica?: PrismaClientOrTransaction;
|
|
runStore?: RunStore;
|
|
controlPlaneResolver?: ControlPlaneResolver;
|
|
} = {}
|
|
) {
|
|
super(opts.prisma, opts.replica, opts.runStore);
|
|
this.#controlPlaneResolver = opts.controlPlaneResolver ?? defaultControlPlaneResolver;
|
|
}
|
|
|
|
public async call(runId: string) {
|
|
const run = await this.runStore.findRun(
|
|
{ id: runId },
|
|
{
|
|
select: {
|
|
id: true,
|
|
projectId: true,
|
|
runtimeEnvironmentId: true,
|
|
},
|
|
},
|
|
this._prisma
|
|
);
|
|
|
|
if (!run) {
|
|
return;
|
|
}
|
|
|
|
const env = await this.#controlPlaneResolver.resolveEnv(run.runtimeEnvironmentId);
|
|
|
|
if (!env) {
|
|
return;
|
|
}
|
|
|
|
const alertChannels = await this._prisma.projectAlertChannel.findMany({
|
|
where: {
|
|
projectId: run.projectId,
|
|
alertTypes: {
|
|
has: "TASK_RUN",
|
|
},
|
|
environmentTypes: {
|
|
has: env.parentEnvironmentType ?? env.type,
|
|
},
|
|
enabled: true,
|
|
},
|
|
});
|
|
|
|
for (const alertChannel of alertChannels) {
|
|
await this.#createAndSendAlert(alertChannel, run);
|
|
}
|
|
}
|
|
|
|
async #createAndSendAlert(alertChannel: ProjectAlertChannel, run: FoundRun) {
|
|
await DeliverAlertService.createAndSendAlert(
|
|
{
|
|
channelId: alertChannel.id,
|
|
channelType: alertChannel.type,
|
|
projectId: run.projectId,
|
|
environmentId: run.runtimeEnvironmentId,
|
|
alertType: "TASK_RUN",
|
|
taskRunId: run.id,
|
|
},
|
|
this._prisma
|
|
);
|
|
}
|
|
|
|
static async enqueue(runId: string, runAt?: Date) {
|
|
return await alertsWorker.enqueue({
|
|
id: `performTaskRunAlerts:${runId}`,
|
|
job: "v3.performTaskRunAlerts",
|
|
payload: { runId },
|
|
availableAt: runAt,
|
|
});
|
|
}
|
|
}
|