630e9556b0
* useSearchParams has * useSearchParams has * useSearchParams has * Consistent way to get the run filters * Consistent way to get the run filters * Consistent way to get the run filters * Initial work on the new bulk actions * Initial work on the new bulk actions * Initial work on the new bulk actions * WIP actions and filtering * WIP actions and filtering * WIP actions and filtering * Empty filter arrays are set to undefined * Empty filter arrays are set to undefined * Empty filter arrays are set to undefined * WIP prisma schema Removed extra runtimeEnvironmentId * WIP prisma schema Removed extra runtimeEnvironmentId * WIP prisma schema Removed extra runtimeEnvironmentId * Migrations * Migrations * Migrations * BulkActionGroup changed some columns around * BulkActionGroup changed some columns around * BulkActionGroup changed some columns around * New badge variant, removed unused ones * New badge variant, removed unused ones * New badge variant, removed unused ones * Bulk action button * Bulk action button * Bulk action button * Make the next runs page the default now * Make the next runs page the default now * Make the next runs page the default now * Improved the RadioButton style * Improved the RadioButton style * Improved the RadioButton style * Remove the old bulk action bar * Remove the old bulk action bar * Remove the old bulk action bar * More UI progress * More UI progress * More UI progress * Lots of UI changes to the Runs page * Lots of UI changes to the Runs page * Lots of UI changes to the Runs page * Fixed period filter resetting everything * Fixed period filter resetting everything * Fixed period filter resetting everything * Improved the Switch secondary style * Improved the Switch secondary style * Improved the Switch secondary style * Buggy filter fixes * Buggy filter fixes * Buggy filter fixes * Improved the filter display and fixed a bug with search param from object * Improved the filter display and fixed a bug with search param from object * Improved the filter display and fixed a bug with search param from object * Clear button is minimal * Clear button is minimal * Clear button is minimal * Using a presenter now * Using a presenter now * Using a presenter now * Bulk actions are created, but not actually processed (yet) * Bulk actions are created, but not actually processed (yet) * Bulk actions are created, but not actually processed (yet) * Bulk replay/cancel is working * Bulk replay/cancel is working * Bulk replay/cancel is working * Multiple fixes, added bulk column to PG * Multiple fixes, added bulk column to PG * Multiple fixes, added bulk column to PG * Bulk action run filtering working using CH * Bulk action run filtering working using CH * Bulk action run filtering working using CH * Replay setting the bulk id on the runs * Replay setting the bulk id on the runs * Replay setting the bulk id on the runs * Properly cap the time when doing a bulk action * Properly cap the time when doing a bulk action * Properly cap the time when doing a bulk action * If the bulk action isn't recent, add it to the dropdown anyway * If the bulk action isn't recent, add it to the dropdown anyway * If the bulk action isn't recent, add it to the dropdown anyway * Blank version of the bulk actions page * Blank version of the bulk actions page * Blank version of the bulk actions page * Individually selected runs working * Individually selected runs working * Individually selected runs working * Use selected mode if runs are checked * Use selected mode if runs are checked * Use selected mode if runs are checked * Added the modal * Added the modal * Added the modal * Marked the old bulk actions stuff as deprecated * Marked the old bulk actions stuff as deprecated * Marked the old bulk actions stuff as deprecated * Renamed bulk action file * Renamed bulk action file * Renamed bulk action file * Bulk run filter with the name and a default * Bulk run filter with the name and a default * Bulk run filter with the name and a default * WIP on bulk actions page * WIP on bulk actions page * WIP on bulk actions page * Updated panel, added new truncated id component * Updated panel, added new truncated id component * Updated panel, added new truncated id component * Style improvements to the radio buttons * Style improvements to the radio buttons * Style improvements to the radio buttons * Added an option action completion email * Added an option action completion email * Added an option action completion email * Adds a blank state for the bulk actions page * Adds a blank state for the bulk actions page * Adds a blank state for the bulk actions page * Nicer completed email * Nicer completed email * Nicer completed email * Don't open the bulk action panel if there are no runs * Don't open the bulk action panel if there are no runs * Don't open the bulk action panel if there are no runs * Runs blank state and bulk action accordion * Runs blank state and bulk action accordion * Runs blank state and bulk action accordion * Updates secondary/small switch style * Updates secondary/small switch style * Updates secondary/small switch style * Pagination buttons no longer split in twain (WIP) * Pagination buttons no longer split in twain (WIP) * Pagination buttons no longer split in twain (WIP) * Aborting working * Aborting working * Aborting working * Bulk action live reloading * Bulk action live reloading * Bulk action live reloading * ListPagination works correctly in all states * ListPagination works correctly in all states * ListPagination works correctly in all states * Run page, show friendlyId instead of number * Run page, show friendlyId instead of number * Run page, show friendlyId instead of number * Bulk action help open by default if you have none * Bulk action help open by default if you have none * Bulk action help open by default if you have none * Extra status filtering step because of replication delay * Extra status filtering step because of replication delay * Extra status filtering step because of replication delay * Wider bulk action onboarding * Wider bulk action onboarding * Wider bulk action onboarding * More sensible widths on the bulk action side panel * More sensible widths on the bulk action side panel * More sensible widths on the bulk action side panel * Border color tweak to the RadioButton * Border color tweak to the RadioButton * Border color tweak to the RadioButton * Improved the accordion component hover states * Improved the accordion component hover states * Improved the accordion component hover states * Updates the bulk action blank state images to the latest UI * Updates the bulk action blank state images to the latest UI * Updates the bulk action blank state images to the latest UI * Added R and C shortcuts back in * Added R and C shortcuts back in * Added R and C shortcuts back in * Fix for selecting a single run * Fix for selecting a single run * Fix for selecting a single run * Improved exit icon, added shortcut to modal * Improved exit icon, added shortcut to modal * Improved exit icon, added shortcut to modal * Tidy imports * Tidy imports * Tidy imports * Tidy imports * Tidy imports * Tidy imports * Tidy imports * Tidy imports * Tidy imports * Tidy imports * Fix for grid layout when 1 page of bulk actions visible * Fix for grid layout when 1 page of bulk actions visible * Fix for grid layout when 1 page of bulk actions visible * Removed the ... on the abort button * Removed the ... on the abort button * Removed the ... on the abort button * Removed the ... on the abort button * Animate the progress bar * Set TZ="UTC" in the env example * Filter summary in the bulk inspector * Improves the pagination styling * Improves the pagination styling * Delete old bulk action routes * Removed old Postgres RunListPresenter * Retry any replication error where the message contains "timeout" * Increase wait to make test less flaky * The test was using run id instead of friendly id * Safer array access * Remove error log if there's a bad status * Nicer frontend type safety with the bulk action and mode * Switched a log to a debug log * Retry replication unless the error is a known non-retry error Flip the strategy to retry by default * Make ClickHouse required * Backfill run replication admin API endpoint * Set a CLICKHOUSE_URL for unit tests --------- Co-authored-by: James Ritchie <james@trigger.dev>
346 lines
12 KiB
TypeScript
346 lines
12 KiB
TypeScript
import { ZodWorker } from "@internal/zod-worker";
|
|
import { DeliverEmailSchema } from "emails";
|
|
import { z } from "zod";
|
|
import { $replica, prisma } from "~/db.server";
|
|
import { env } from "~/env.server";
|
|
import {
|
|
BatchProcessingOptions as RunEngineBatchProcessingOptions,
|
|
RunEngineBatchTriggerService,
|
|
} from "~/runEngine/services/batchTrigger.server";
|
|
import { MarqsConcurrencyMonitor } from "~/v3/marqs/concurrencyMonitor.server";
|
|
import { scheduleEngine } from "~/v3/scheduleEngine.server";
|
|
import { DeliverAlertService } from "~/v3/services/alerts/deliverAlert.server";
|
|
import { PerformDeploymentAlertsService } from "~/v3/services/alerts/performDeploymentAlerts.server";
|
|
import { PerformTaskRunAlertsService } from "~/v3/services/alerts/performTaskRunAlerts.server";
|
|
import { BatchProcessingOptions, BatchTriggerV3Service } from "~/v3/services/batchTriggerV3.server";
|
|
import { PerformBulkActionService } from "~/v3/services/bulk/performBulkAction.server";
|
|
import {
|
|
CancelDevSessionRunsService,
|
|
CancelDevSessionRunsServiceOptions,
|
|
} from "~/v3/services/cancelDevSessionRuns.server";
|
|
import { CancelTaskAttemptDependenciesService } from "~/v3/services/cancelTaskAttemptDependencies.server";
|
|
import { EnqueueDelayedRunService } from "~/v3/services/enqueueDelayedRun.server";
|
|
import { ExecuteTasksWaitingForDeployService } from "~/v3/services/executeTasksWaitingForDeploy";
|
|
import { ExpireEnqueuedRunService } from "~/v3/services/expireEnqueuedRun.server";
|
|
import { ResumeBatchRunService } from "~/v3/services/resumeBatchRun.server";
|
|
import { ResumeTaskDependencyService } from "~/v3/services/resumeTaskDependency.server";
|
|
import { RetryAttemptService } from "~/v3/services/retryAttempt.server";
|
|
import { TimeoutDeploymentService } from "~/v3/services/timeoutDeployment.server";
|
|
import { GraphileMigrationHelperService } from "./db/graphileMigrationHelper.server";
|
|
import { sendEmail } from "./email.server";
|
|
import { logger } from "./logger.server";
|
|
|
|
const workerCatalog = {
|
|
// @deprecated, moved to commonWorker.server.ts
|
|
scheduleEmail: DeliverEmailSchema,
|
|
// @deprecated, but still used when resuming batch runs in a transaction
|
|
"v3.resumeBatchRun": z.object({
|
|
batchRunId: z.string(),
|
|
}),
|
|
// @deprecated, moved to commonWorker.server.ts
|
|
"v3.resumeTaskDependency": z.object({
|
|
dependencyId: z.string(),
|
|
sourceTaskAttemptId: z.string(),
|
|
}),
|
|
// @deprecated, moved to commonWorker.server.ts
|
|
"v3.timeoutDeployment": z.object({
|
|
deploymentId: z.string(),
|
|
fromStatus: z.string(),
|
|
errorMessage: z.string(),
|
|
}),
|
|
// @deprecated, moved to commonWorker.server.ts
|
|
"v3.executeTasksWaitingForDeploy": z.object({
|
|
backgroundWorkerId: z.string(),
|
|
}),
|
|
// @deprecated, moved to ScheduleEngine
|
|
"v3.triggerScheduledTask": z.object({
|
|
instanceId: z.string(),
|
|
}),
|
|
// @deprecated, moved to commonWorker.server.ts
|
|
"v3.performTaskRunAlerts": z.object({
|
|
runId: z.string(),
|
|
}),
|
|
// @deprecated, moved to commonWorker.server.ts
|
|
"v3.deliverAlert": z.object({
|
|
alertId: z.string(),
|
|
}),
|
|
// @deprecated, moved to commonWorker.server.ts
|
|
"v3.performDeploymentAlerts": z.object({
|
|
deploymentId: z.string(),
|
|
}),
|
|
"v3.performBulkAction": z.object({
|
|
bulkActionGroupId: z.string(),
|
|
}),
|
|
"v3.performBulkActionItem": z.object({
|
|
bulkActionItemId: z.string(),
|
|
}),
|
|
// @deprecated, moved to legacyRunEngineWorker.server.ts
|
|
"v3.requeueTaskRun": z.object({
|
|
runId: z.string(),
|
|
}),
|
|
// @deprecated, moved to commonWorker.server.ts
|
|
"v3.retryAttempt": z.object({
|
|
runId: z.string(),
|
|
}),
|
|
// @deprecated, moved to commonWorker.server.ts
|
|
"v3.enqueueDelayedRun": z.object({
|
|
runId: z.string(),
|
|
}),
|
|
// @deprecated, moved to commonWorker.server.ts
|
|
"v3.expireRun": z.object({
|
|
runId: z.string(),
|
|
}),
|
|
// @deprecated, moved to commonWorker.server.ts
|
|
"v3.cancelTaskAttemptDependencies": z.object({
|
|
attemptId: z.string(),
|
|
}),
|
|
// @deprecated, moved to commonWorker.server.ts
|
|
"v3.cancelDevSessionRuns": CancelDevSessionRunsServiceOptions,
|
|
// @deprecated, moved to commonWorker.server.ts
|
|
"v3.processBatchTaskRun": BatchProcessingOptions,
|
|
// @deprecated, moved to commonWorker.server.ts
|
|
"runengine.processBatchTaskRun": RunEngineBatchProcessingOptions,
|
|
};
|
|
|
|
let workerQueue: ZodWorker<typeof workerCatalog>;
|
|
|
|
declare global {
|
|
var __worker__: ZodWorker<typeof workerCatalog>;
|
|
}
|
|
|
|
// this is needed because in development we don't want to restart
|
|
// the server with every change, but we want to make sure we don't
|
|
// create a new connection to the DB with every change either.
|
|
// in production we'll have a single connection to the DB.
|
|
if (env.NODE_ENV === "production") {
|
|
workerQueue = getWorkerQueue();
|
|
} else {
|
|
if (!global.__worker__) {
|
|
global.__worker__ = getWorkerQueue();
|
|
}
|
|
workerQueue = global.__worker__;
|
|
}
|
|
|
|
export async function init() {
|
|
const migrationHelper = new GraphileMigrationHelperService();
|
|
await migrationHelper.call();
|
|
|
|
if (env.WORKER_ENABLED === "true") {
|
|
await workerQueue.initialize();
|
|
}
|
|
}
|
|
|
|
function getWorkerQueue() {
|
|
return new ZodWorker({
|
|
name: "workerQueue",
|
|
prisma,
|
|
replica: $replica,
|
|
runnerOptions: {
|
|
connectionString: env.DATABASE_URL,
|
|
concurrency: env.WORKER_CONCURRENCY,
|
|
pollInterval: env.WORKER_POLL_INTERVAL,
|
|
noPreparedStatements: env.DATABASE_URL !== env.DIRECT_URL,
|
|
schema: env.WORKER_SCHEMA,
|
|
maxPoolSize: env.WORKER_CONCURRENCY + 1,
|
|
},
|
|
logger: logger,
|
|
shutdownTimeoutInMs: env.GRACEFUL_SHUTDOWN_TIMEOUT,
|
|
schema: workerCatalog,
|
|
recurringTasks: {
|
|
"marqs.v3.queueConcurrencyMonitor": {
|
|
// run every 5 minutes
|
|
match: "*/5 * * * *",
|
|
handler: async (payload, job, helpers) => {
|
|
await MarqsConcurrencyMonitor.initiateV3Monitoring(helpers.abortSignal);
|
|
},
|
|
},
|
|
},
|
|
tasks: {
|
|
// @deprecated, moved to commonWorker.server.ts
|
|
scheduleEmail: {
|
|
priority: 0,
|
|
maxAttempts: 3,
|
|
handler: async (payload, job) => {
|
|
await sendEmail(payload);
|
|
},
|
|
},
|
|
// @deprecated, moved to commonWorker.server.ts but still used when resuming batch runs in a transaction
|
|
"v3.resumeBatchRun": {
|
|
priority: 0,
|
|
maxAttempts: 5,
|
|
handler: async (payload, job) => {
|
|
const service = new ResumeBatchRunService();
|
|
|
|
await service.call(payload.batchRunId);
|
|
},
|
|
},
|
|
// @deprecated, moved to commonWorker.server.ts
|
|
"v3.resumeTaskDependency": {
|
|
priority: 0,
|
|
maxAttempts: 5,
|
|
handler: async (payload, job) => {
|
|
const service = new ResumeTaskDependencyService();
|
|
|
|
return await service.call(payload.dependencyId, payload.sourceTaskAttemptId);
|
|
},
|
|
},
|
|
// @deprecated, moved to commonWorker.server.ts
|
|
"v3.timeoutDeployment": {
|
|
priority: 0,
|
|
maxAttempts: 5,
|
|
handler: async (payload, job) => {
|
|
const service = new TimeoutDeploymentService();
|
|
|
|
return await service.call(payload.deploymentId, payload.fromStatus, payload.errorMessage);
|
|
},
|
|
},
|
|
// @deprecated, moved to commonWorker.server.ts
|
|
"v3.executeTasksWaitingForDeploy": {
|
|
priority: 0,
|
|
maxAttempts: 5,
|
|
handler: async (payload, job) => {
|
|
const service = new ExecuteTasksWaitingForDeployService();
|
|
|
|
return await service.call(payload.backgroundWorkerId);
|
|
},
|
|
},
|
|
// @deprecated, moved to ScheduleEngine
|
|
"v3.triggerScheduledTask": {
|
|
priority: 0,
|
|
maxAttempts: 3, // total delay of 30 seconds
|
|
handler: async (payload, job) => {
|
|
await scheduleEngine.triggerScheduledTask({
|
|
instanceId: payload.instanceId,
|
|
finalAttempt: job.attempts === job.max_attempts,
|
|
});
|
|
},
|
|
},
|
|
// @deprecated, moved to alertsWorker.server.ts
|
|
"v3.performTaskRunAlerts": {
|
|
priority: 0,
|
|
maxAttempts: 3,
|
|
handler: async (payload, job) => {
|
|
const service = new PerformTaskRunAlertsService();
|
|
return await service.call(payload.runId);
|
|
},
|
|
},
|
|
// @deprecated, moved to alertsWorker.server.ts
|
|
"v3.deliverAlert": {
|
|
priority: 0,
|
|
maxAttempts: 8,
|
|
handler: async (payload, job) => {
|
|
const service = new DeliverAlertService();
|
|
|
|
return await service.call(payload.alertId);
|
|
},
|
|
},
|
|
// @deprecated, moved to alertsWorker.server.ts
|
|
"v3.performDeploymentAlerts": {
|
|
priority: 0,
|
|
maxAttempts: 3,
|
|
handler: async (payload, job) => {
|
|
const service = new PerformDeploymentAlertsService();
|
|
|
|
return await service.call(payload.deploymentId);
|
|
},
|
|
},
|
|
// @deprecated, new bulk actions use the new bulk actions worker
|
|
"v3.performBulkAction": {
|
|
priority: 0,
|
|
maxAttempts: 3,
|
|
handler: async (payload, job) => {
|
|
const service = new PerformBulkActionService();
|
|
|
|
return await service.call(payload.bulkActionGroupId);
|
|
},
|
|
},
|
|
// @deprecated, new bulk actions use the new bulk actions worker
|
|
"v3.performBulkActionItem": {
|
|
priority: 0,
|
|
maxAttempts: 3,
|
|
handler: async (payload, job) => {
|
|
const service = new PerformBulkActionService();
|
|
|
|
await service.performBulkActionItem(payload.bulkActionItemId);
|
|
},
|
|
},
|
|
"v3.requeueTaskRun": {
|
|
priority: 0,
|
|
maxAttempts: 3,
|
|
handler: async (payload, job) => {}, // This is now handled by redisWorker
|
|
},
|
|
// @deprecated, moved to commonWorker.server.ts
|
|
"v3.retryAttempt": {
|
|
priority: 0,
|
|
maxAttempts: 3,
|
|
handler: async (payload, job) => {
|
|
const service = new RetryAttemptService();
|
|
|
|
return await service.call(payload.runId);
|
|
},
|
|
},
|
|
// @deprecated, moved to commonWorker.server.ts
|
|
"v3.enqueueDelayedRun": {
|
|
priority: 0,
|
|
maxAttempts: 8,
|
|
handler: async (payload, job) => {
|
|
const service = new EnqueueDelayedRunService();
|
|
|
|
return await service.call(payload.runId);
|
|
},
|
|
},
|
|
// @deprecated, moved to commonWorker.server.ts
|
|
"v3.expireRun": {
|
|
priority: 0,
|
|
maxAttempts: 8,
|
|
handler: async (payload, job) => {
|
|
const service = new ExpireEnqueuedRunService();
|
|
|
|
return await service.call(payload.runId);
|
|
},
|
|
},
|
|
// @deprecated, moved to commonWorker.server.ts
|
|
"v3.cancelTaskAttemptDependencies": {
|
|
priority: 0,
|
|
maxAttempts: 8,
|
|
handler: async (payload, job) => {
|
|
const service = new CancelTaskAttemptDependenciesService();
|
|
|
|
return await service.call(payload.attemptId);
|
|
},
|
|
},
|
|
// @deprecated, moved to commonWorker.server.ts
|
|
"v3.cancelDevSessionRuns": {
|
|
priority: 0,
|
|
maxAttempts: 5,
|
|
handler: async (payload, job) => {
|
|
const service = new CancelDevSessionRunsService();
|
|
|
|
return await service.call(payload);
|
|
},
|
|
},
|
|
// @deprecated, moved to commonWorker.server.ts
|
|
"v3.processBatchTaskRun": {
|
|
priority: 0,
|
|
maxAttempts: 5,
|
|
handler: async (payload, job) => {
|
|
const service = new BatchTriggerV3Service(payload.strategy);
|
|
|
|
await service.processBatchTaskRun(payload);
|
|
},
|
|
},
|
|
// @deprecated, moved to commonWorker.server.ts
|
|
"runengine.processBatchTaskRun": {
|
|
priority: 0,
|
|
maxAttempts: 5,
|
|
handler: async (payload, job) => {
|
|
const service = new RunEngineBatchTriggerService(payload.strategy);
|
|
|
|
await service.processBatchTaskRun(payload);
|
|
},
|
|
},
|
|
},
|
|
});
|
|
}
|
|
export { workerQueue };
|