From 5c33b9a36f234c927cb98c04ee2f50999a7b66bb Mon Sep 17 00:00:00 2001 From: Daniel Lee Date: Thu, 13 Nov 2025 19:40:14 -0800 Subject: [PATCH 1/3] feat: add attemptDeadlineSeconds support to v2 scheduled functions Adds attemptDeadlineSeconds to ScheduleOptions and ManifestEndpoint. Updates onSchedule to pass attemptDeadlineSeconds to the manifest. Adds tests for attemptDeadlineSeconds. --- spec/runtime/manifest.spec.ts | 1 + spec/v2/providers/scheduler.spec.ts | 5 +++++ src/runtime/manifest.ts | 11 +++++++++-- src/v2/providers/scheduler.ts | 7 ++++++- 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/spec/runtime/manifest.spec.ts b/spec/runtime/manifest.spec.ts index 7534ba2ee..8f520a210 100644 --- a/spec/runtime/manifest.spec.ts +++ b/spec/runtime/manifest.spec.ts @@ -286,6 +286,7 @@ describe("initScheduleTrigger", () => { expect(st).to.deep.eq({ schedule: "every 30 minutes", timeZone: RESET_VALUE, + attemptDeadlineSeconds: RESET_VALUE, retryConfig: { retryCount: RESET_VALUE, maxDoublings: RESET_VALUE, diff --git a/spec/v2/providers/scheduler.spec.ts b/spec/v2/providers/scheduler.spec.ts index fcd03cf1f..983e2f761 100644 --- a/spec/v2/providers/scheduler.spec.ts +++ b/spec/v2/providers/scheduler.spec.ts @@ -32,6 +32,7 @@ import { runHandler } from "../../helper"; const MINIMAL_SCHEDULE_TRIGGER: ManifestEndpoint["scheduleTrigger"] = { schedule: "", timeZone: options.RESET_VALUE, + attemptDeadlineSeconds: options.RESET_VALUE, retryConfig: { retryCount: options.RESET_VALUE, maxRetrySeconds: options.RESET_VALUE, @@ -66,6 +67,7 @@ describe("schedule", () => { expect(schedule.getOpts(options)).to.deep.eq({ schedule: "* * * * *", timeZone: "utc", + attemptDeadlineSeconds: undefined, retryConfig: { retryCount: 3, maxRetrySeconds: 1, @@ -108,6 +110,7 @@ describe("schedule", () => { { schedule: "* * * * *", timeZone: "utc", + attemptDeadlineSeconds: 300, retryCount: 3, maxRetrySeconds: 10, minBackoffSeconds: 11, @@ -127,6 +130,7 @@ describe("schedule", () => { scheduleTrigger: { schedule: "* * * * *", timeZone: "utc", + attemptDeadlineSeconds: 300, retryConfig: { retryCount: 3, maxRetrySeconds: 10, @@ -159,6 +163,7 @@ describe("schedule", () => { scheduleTrigger: { schedule: "* * * * *", timeZone: undefined, + attemptDeadlineSeconds: undefined, retryConfig: { retryCount: undefined, maxRetrySeconds: undefined, diff --git a/src/runtime/manifest.ts b/src/runtime/manifest.ts index 4d52d5eaf..658fa0edb 100644 --- a/src/runtime/manifest.ts +++ b/src/runtime/manifest.ts @@ -97,6 +97,7 @@ export interface ManifestEndpoint { scheduleTrigger?: { schedule: string | Expression; timeZone?: string | Expression | ResetValue; + attemptDeadlineSeconds?: number | Expression | ResetValue; retryConfig?: { retryCount?: number | Expression | ResetValue; maxRetrySeconds?: string | Expression | ResetValue; @@ -259,12 +260,14 @@ const RESETTABLE_V1_SCHEDULE_OPTIONS: Omit< const RESETTABLE_V2_SCHEDULE_OPTIONS: Omit< ResettableKeys, "maxRetryDuration" | "maxBackoffDuration" | "minBackoffDuration" -> = { + > & + Pick, "attemptDeadlineSeconds"> = { retryCount: null, maxDoublings: null, maxRetrySeconds: null, minBackoffSeconds: null, maxBackoffSeconds: null, + attemptDeadlineSeconds: null, }; function initScheduleTrigger( @@ -278,7 +281,11 @@ function initScheduleTrigger( }; if (opts.every((opt) => !opt?.preserveExternalChanges)) { for (const key of Object.keys(resetOptions)) { - scheduleTrigger.retryConfig[key] = RESET_VALUE; + if (key === "attemptDeadlineSeconds") { + scheduleTrigger[key] = RESET_VALUE; + } else { + scheduleTrigger.retryConfig[key] = RESET_VALUE; + } } scheduleTrigger = { ...scheduleTrigger, timeZone: RESET_VALUE }; } diff --git a/src/v2/providers/scheduler.ts b/src/v2/providers/scheduler.ts index 1f8f33c31..5e7d10716 100644 --- a/src/v2/providers/scheduler.ts +++ b/src/v2/providers/scheduler.ts @@ -42,6 +42,7 @@ import { withInit } from "../../common/onInit"; interface SeparatedOpts { schedule: string | Expression; timeZone?: timezone | Expression | ResetValue; + attemptDeadlineSeconds?: number | Expression | ResetValue; retryConfig?: { retryCount?: number | Expression | ResetValue; maxRetrySeconds?: number | Expression | ResetValue; @@ -63,6 +64,7 @@ export function getOpts(args: string | ScheduleOptions): SeparatedOpts { return { schedule: args.schedule, timeZone: args.timeZone, + attemptDeadlineSeconds: args.attemptDeadlineSeconds, retryConfig: { retryCount: args.retryCount, maxRetrySeconds: args.maxRetrySeconds, @@ -111,6 +113,9 @@ export interface ScheduleOptions extends options.GlobalOptions { /** The timezone that the schedule executes in. */ timeZone?: timezone | Expression | ResetValue; + /** The deadline for job attempts. Defaults to 180 seconds. */ + attemptDeadlineSeconds?: number | Expression | ResetValue; + /** The number of retry attempts for a failed run. */ retryCount?: number | Expression | ResetValue; @@ -196,7 +201,7 @@ export function onSchedule( scheduleTrigger: initV2ScheduleTrigger(separatedOpts.schedule, globalOpts, separatedOpts.opts), }; - copyIfPresent(ep.scheduleTrigger, separatedOpts, "timeZone"); + copyIfPresent(ep.scheduleTrigger, separatedOpts, "timeZone", "attemptDeadlineSeconds"); copyIfPresent( ep.scheduleTrigger.retryConfig, separatedOpts.retryConfig, From 270c39cb8fcfd8afbdc4a248e953ce9e9ae682bf Mon Sep 17 00:00:00 2001 From: Daniel Lee Date: Thu, 13 Nov 2025 19:43:32 -0800 Subject: [PATCH 2/3] formatter --- src/runtime/manifest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/manifest.ts b/src/runtime/manifest.ts index 658fa0edb..e2c66c0ba 100644 --- a/src/runtime/manifest.ts +++ b/src/runtime/manifest.ts @@ -260,7 +260,7 @@ const RESETTABLE_V1_SCHEDULE_OPTIONS: Omit< const RESETTABLE_V2_SCHEDULE_OPTIONS: Omit< ResettableKeys, "maxRetryDuration" | "maxBackoffDuration" | "minBackoffDuration" - > & +> & Pick, "attemptDeadlineSeconds"> = { retryCount: null, maxDoublings: null, From e4f4a06d2e80eb761898ec0fa7df59e518642441 Mon Sep 17 00:00:00 2001 From: Daniel Lee Date: Fri, 14 Nov 2025 11:38:37 -0800 Subject: [PATCH 3/3] Update src/v2/providers/scheduler.ts Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- src/v2/providers/scheduler.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/v2/providers/scheduler.ts b/src/v2/providers/scheduler.ts index 5e7d10716..3b0af111f 100644 --- a/src/v2/providers/scheduler.ts +++ b/src/v2/providers/scheduler.ts @@ -113,7 +113,11 @@ export interface ScheduleOptions extends options.GlobalOptions { /** The timezone that the schedule executes in. */ timeZone?: timezone | Expression | ResetValue; - /** The deadline for job attempts. Defaults to 180 seconds. */ + /** + * The deadline for job attempts in seconds. If the request handler does not respond by this deadline, + * the request is cancelled and the attempt is marked as a `DEADLINE_EXCEEDED` failure. + * The value must be between 15 and 1800. Defaults to 180. + */ attemptDeadlineSeconds?: number | Expression | ResetValue; /** The number of retry attempts for a failed run. */