@@ -12,6 +12,7 @@ import type { ExecuteSchedulesResponse } from '@/lib/api/contracts/schedules'
1212import { verifyCronAuth } from '@/lib/auth/internal'
1313import { getJobQueue , shouldExecuteInline } from '@/lib/core/async-jobs'
1414import { JOB_STATUS , type Job } from '@/lib/core/async-jobs/types'
15+ import { isRetryableInfrastructureError } from '@/lib/core/errors/retryable-infrastructure'
1516import { getMaxExecutionTimeout } from '@/lib/core/execution-limits'
1617import { generateRequestId } from '@/lib/core/utils/request'
1718import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
@@ -400,6 +401,33 @@ async function deferClaimedScheduleAfterQueueFailure(
400401 } )
401402}
402403
404+ async function handleClaimedScheduleSetupFailure (
405+ schedule : ClaimedSchedule ,
406+ requestId : string ,
407+ expectedLastQueuedAt : Date ,
408+ error : unknown ,
409+ retryContext : string ,
410+ failureContext : string
411+ ) : Promise < void > {
412+ if ( isRetryableInfrastructureError ( error ) ) {
413+ await deferClaimedScheduleAfterQueueFailure (
414+ schedule ,
415+ requestId ,
416+ expectedLastQueuedAt ,
417+ error ,
418+ retryContext
419+ )
420+ return
421+ }
422+
423+ logger . error ( `[${ requestId } ] Non-retryable schedule setup failure` , {
424+ scheduleId : schedule . id ,
425+ workflowId : schedule . workflowId ,
426+ error : toError ( error ) . message ,
427+ } )
428+ await markClaimedScheduleFailed ( schedule , requestId , expectedLastQueuedAt , failureContext )
429+ }
430+
403431async function recoverStaleDatabaseScheduleJobs ( now : Date ) : Promise < void > {
404432 const staleStartedBefore = getStaleScheduleExecutionCutoff ( now )
405433
@@ -721,7 +749,8 @@ async function processScheduleItem(
721749 schedule : ClaimedSchedule ,
722750 queuedAt : Date ,
723751 requestId : string ,
724- jobQueue : JobQueue
752+ jobQueue : JobQueue ,
753+ useDatabaseFallback : boolean
725754) {
726755 const queueTime = schedule . lastQueuedAt ?? queuedAt
727756 const executionId = generateId ( )
@@ -756,7 +785,6 @@ async function processScheduleItem(
756785 let enqueuedJobId : string | null = null
757786
758787 try {
759- const useDatabaseFallback = shouldExecuteInline ( )
760788 const delayMs = Math . floor ( Math . random ( ) * SCHEDULE_JITTER_MAX_MS )
761789
762790 const scheduleJobId = buildScheduleExecutionJobId ( schedule )
@@ -908,12 +936,13 @@ async function processScheduleItem(
908936 `[${ requestId } ] Failed to enqueue schedule execution for workflow ${ schedule . workflowId } ` ,
909937 error
910938 )
911- await deferClaimedScheduleAfterQueueFailure (
939+ await handleClaimedScheduleSetupFailure (
912940 schedule ,
913941 requestId ,
914942 queueTime ,
915943 error ,
916- `Failed to defer schedule ${ schedule . id } after enqueue failure`
944+ `Failed to defer schedule ${ schedule . id } after enqueue failure` ,
945+ `Failed to mark schedule ${ schedule . id } failed after non-retryable enqueue failure`
917946 )
918947 return
919948 }
@@ -1004,12 +1033,13 @@ async function processScheduleItem(
10041033 error
10051034 )
10061035 if ( ! enqueuedJobId ) {
1007- await deferClaimedScheduleAfterQueueFailure (
1036+ await handleClaimedScheduleSetupFailure (
10081037 schedule ,
10091038 requestId ,
10101039 queueTime ,
10111040 error ,
1012- `Failed to defer schedule ${ schedule . id } after pre-enqueue failure`
1041+ `Failed to defer schedule ${ schedule . id } after pre-enqueue failure` ,
1042+ `Failed to mark schedule ${ schedule . id } failed after non-retryable setup failure`
10131043 )
10141044 }
10151045 }
@@ -1117,7 +1147,7 @@ export const GET = withRouteHandler(async (request: NextRequest) => {
11171147 const schedulePromises =
11181148 dueSchedules . length > 0
11191149 ? dueSchedules . map ( ( schedule ) =>
1120- processScheduleItem ( schedule , queuedAt , requestId , jobQueue )
1150+ processScheduleItem ( schedule , queuedAt , requestId , jobQueue , useDatabaseFallback )
11211151 )
11221152 : [ ]
11231153
0 commit comments