chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
import { type ActionFunctionArgs, json } from "@remix-run/server-runtime";
|
||||
import { EnvironmentPauseSource } from "@trigger.dev/database";
|
||||
import { z } from "zod";
|
||||
import { prisma } from "~/db.server";
|
||||
import { requireAdminApiRequest } from "~/services/personalAccessToken.server";
|
||||
import { controlPlaneResolver } from "~/v3/runOpsMigration/controlPlaneResolver.server";
|
||||
import { PauseEnvironmentService } from "~/v3/services/pauseEnvironment.server";
|
||||
|
||||
const ParamsSchema = z.object({
|
||||
organizationId: z.string(),
|
||||
});
|
||||
|
||||
const BodySchema = z.object({
|
||||
enable: z.boolean(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Enable or disable runs for an organization and pause/resume its non-dev environments.
|
||||
*
|
||||
* Billing-limit-paused environments are left unchanged when enabling or disabling runs;
|
||||
* they are reported in `skipped`, not counted in the update total. Other per-environment
|
||||
* failures are returned in `failures` (HTTP 409 when every environment fails, otherwise
|
||||
* HTTP 200).
|
||||
*/
|
||||
export async function action({ request, params }: ActionFunctionArgs) {
|
||||
await requireAdminApiRequest(request);
|
||||
|
||||
const { organizationId } = ParamsSchema.parse(params);
|
||||
const body = BodySchema.safeParse(await request.json());
|
||||
if (!body.success) {
|
||||
return json({ error: "Invalid request body", details: body.error }, { status: 400 });
|
||||
}
|
||||
|
||||
const organization = await prisma.organization.update({
|
||||
where: {
|
||||
id: organizationId,
|
||||
},
|
||||
data: {
|
||||
runsEnabled: body.data.enable,
|
||||
},
|
||||
});
|
||||
|
||||
if (!organization) {
|
||||
return json({ error: "Organization not found" }, { status: 404 });
|
||||
}
|
||||
|
||||
// `runsEnabled` is embedded in every env of the org; drop all its cached env rows. The
|
||||
// per-env pause writes below invalidate their own envs via PauseEnvironmentService.
|
||||
controlPlaneResolver.invalidateOrganization(organizationId);
|
||||
|
||||
const environments = await prisma.runtimeEnvironment.findMany({
|
||||
where: {
|
||||
organizationId,
|
||||
type: {
|
||||
not: "DEVELOPMENT",
|
||||
},
|
||||
},
|
||||
include: {
|
||||
organization: true,
|
||||
project: true,
|
||||
},
|
||||
});
|
||||
|
||||
const pauseEnvironmentService = new PauseEnvironmentService();
|
||||
const pauseAction = body.data.enable ? "resumed" : "paused";
|
||||
const failures: Array<{ environmentId: string; error: string }> = [];
|
||||
const skipped: Array<{ environmentId: string; reason: string }> = [];
|
||||
let updatedCount = 0;
|
||||
|
||||
for (const environment of environments) {
|
||||
if (environment.pauseSource === EnvironmentPauseSource.BILLING_LIMIT) {
|
||||
if (!body.data.enable) {
|
||||
skipped.push({
|
||||
environmentId: environment.id,
|
||||
reason: "Environment is already paused due to billing limit and was left unchanged.",
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
skipped.push({
|
||||
environmentId: environment.id,
|
||||
reason:
|
||||
"Environment is paused due to billing limit and was left unchanged. Resolve the billing limit to resume.",
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
const result = await pauseEnvironmentService.call(
|
||||
{ ...environment, organization },
|
||||
pauseAction
|
||||
);
|
||||
if (result.success) {
|
||||
updatedCount++;
|
||||
} else {
|
||||
failures.push({ environmentId: environment.id, error: result.error });
|
||||
}
|
||||
}
|
||||
|
||||
const stateLabel = body.data.enable ? "enabled" : "disabled";
|
||||
const message = `${updatedCount} of ${environments.length} environments updated to ${stateLabel}`;
|
||||
|
||||
if (failures.length > 0) {
|
||||
return json(
|
||||
{
|
||||
success: false,
|
||||
message,
|
||||
failures,
|
||||
...(skipped.length > 0 ? { skipped } : {}),
|
||||
},
|
||||
{ status: updatedCount === 0 ? 409 : 200 }
|
||||
);
|
||||
}
|
||||
|
||||
return json({
|
||||
success: true,
|
||||
message,
|
||||
...(skipped.length > 0 ? { skipped } : {}),
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user