diff --git a/apps/webapp/app/v3/services/createBackgroundWorker.server.ts b/apps/webapp/app/v3/services/createBackgroundWorker.server.ts index 435b6f0f32..f93d6848c4 100644 --- a/apps/webapp/app/v3/services/createBackgroundWorker.server.ts +++ b/apps/webapp/app/v3/services/createBackgroundWorker.server.ts @@ -521,6 +521,18 @@ export async function syncDeclarativeSchedules( for (const task of tasksWithDeclarativeSchedules) { if (task.schedule === undefined) continue; + // Check if this schedule should be created in the current environment + if (task.schedule.environments && task.schedule.environments.length > 0) { + if (!task.schedule.environments.includes(environment.type)) { + logger.debug("Skipping schedule creation due to environment filter", { + taskId: task.id, + environmentType: environment.type, + allowedEnvironments: task.schedule.environments, + }); + continue; + } + } + const existingSchedule = existingDeclarativeSchedules.find( (schedule) => schedule.taskIdentifier === task.id && diff --git a/packages/core/src/v3/schemas/schemas.ts b/packages/core/src/v3/schemas/schemas.ts index 40ab6116ad..31667a01ad 100644 --- a/packages/core/src/v3/schemas/schemas.ts +++ b/packages/core/src/v3/schemas/schemas.ts @@ -176,6 +176,7 @@ export type QueueManifest = z.infer; export const ScheduleMetadata = z.object({ cron: z.string(), timezone: z.string(), + environments: z.array(EnvironmentType).optional(), }); const taskMetadata = { diff --git a/packages/trigger-sdk/src/v3/schedules/index.ts b/packages/trigger-sdk/src/v3/schedules/index.ts index eb38c9922f..1f87ed83e2 100644 --- a/packages/trigger-sdk/src/v3/schedules/index.ts +++ b/packages/trigger-sdk/src/v3/schedules/index.ts @@ -28,11 +28,12 @@ export type ScheduleOptions< * "0 0 * * *" * ``` * - * 2. Or an object with a pattern and an optional timezone (default is "UTC") + * 2. Or an object with a pattern, optional timezone, and optional environments * ```ts * { * pattern: "0 0 * * *", - * timezone: "America/Los_Angeles" + * timezone: "America/Los_Angeles", + * environments: ["PRODUCTION", "STAGING"] * } * ``` * @@ -43,6 +44,20 @@ export type ScheduleOptions< | { pattern: string; timezone?: string; + /** You can optionally specify which environments this schedule should run in. + * When not specified, the schedule will run in all environments. + * + * @example + * ```ts + * environments: ["PRODUCTION", "STAGING"] + * ``` + * + * @example + * ```ts + * environments: ["PRODUCTION"] // Only run in production + * ``` + */ + environments?: Array<"DEVELOPMENT" | "STAGING" | "PRODUCTION" | "PREVIEW">; }; }; @@ -58,6 +73,8 @@ export function task { const distanceInMs = payload.timestamp.getTime() - (payload.lastTimestamp ?? new Date()).getTime(); @@ -22,10 +25,11 @@ export const firstScheduledTask = schedules.task({ export const secondScheduledTask = schedules.task({ id: "second-scheduled-task", - // cron: { - // pattern: "0 5 * * *", - // timezone: "Asia/Tokyo", - // }, + cron: { + pattern: "0 5 * * *", + timezone: "Asia/Tokyo", + environments: ["PRODUCTION"], // Only run in production + }, run: async (payload) => {}, });