@@ -8,8 +8,10 @@ import {
88} from "@opennextjs/aws/utils/error.js" ;
99import { DurableObject } from "cloudflare:workers" ;
1010
11- const MAX_REVALIDATION_BY_DURABLE_OBJECT = 5 ;
11+ const DEFAULT_MAX_REVALIDATION_BY_DURABLE_OBJECT = 5 ;
1212const DEFAULT_REVALIDATION_TIMEOUT_MS = 10_000 ;
13+ const DEFAULT_REVALIDATION_RETRY_INTERVAL_MS = 2_000 ;
14+ const DEFAULT_MAX_REVALIDATION_ATTEMPTS = 6 ;
1315
1416interface FailedState {
1517 msg : QueueMessage ;
@@ -29,8 +31,11 @@ export class DurableObjectQueueHandler extends DurableObject<CloudflareEnv> {
2931
3032 service : NonNullable < CloudflareEnv [ "NEXT_CACHE_REVALIDATION_WORKER" ] > ;
3133
32- // TODO: allow this to be configurable - How do we want todo that? env variable? passed down from the queue override ?
33- maxRevalidations = MAX_REVALIDATION_BY_DURABLE_OBJECT ;
34+ // Configurable params
35+ maxRevalidations = DEFAULT_MAX_REVALIDATION_BY_DURABLE_OBJECT ;
36+ revalidationTimeout = DEFAULT_REVALIDATION_TIMEOUT_MS ;
37+ revalidationRetryInterval = DEFAULT_REVALIDATION_RETRY_INTERVAL_MS ;
38+ maxRevalidationAttempts = DEFAULT_MAX_REVALIDATION_ATTEMPTS ;
3439
3540 constructor ( ctx : DurableObjectState , env : CloudflareEnv ) {
3641 super ( ctx , env ) ;
@@ -42,6 +47,22 @@ export class DurableObjectQueueHandler extends DurableObject<CloudflareEnv> {
4247
4348 // We restore the state
4449 ctx . blockConcurrencyWhile ( ( ) => this . initState ( ) ) ;
50+
51+ this . maxRevalidations = env . MAX_REVALIDATION_BY_DURABLE_OBJECT
52+ ? parseInt ( env . MAX_REVALIDATION_BY_DURABLE_OBJECT )
53+ : DEFAULT_MAX_REVALIDATION_BY_DURABLE_OBJECT ;
54+
55+ this . revalidationTimeout = env . REVALIDATION_TIMEOUT_MS
56+ ? parseInt ( env . REVALIDATION_TIMEOUT_MS )
57+ : DEFAULT_REVALIDATION_TIMEOUT_MS ;
58+
59+ this . revalidationRetryInterval = env . REVALIDATION_RETRY_INTERVAL_MS
60+ ? parseInt ( env . REVALIDATION_RETRY_INTERVAL_MS )
61+ : DEFAULT_REVALIDATION_RETRY_INTERVAL_MS ;
62+
63+ this . maxRevalidationAttempts = env . MAX_REVALIDATION_ATTEMPTS
64+ ? parseInt ( env . MAX_REVALIDATION_ATTEMPTS )
65+ : DEFAULT_MAX_REVALIDATION_ATTEMPTS ;
4566 }
4667
4768 async revalidate ( msg : QueueMessage ) {
@@ -55,7 +76,7 @@ export class DurableObjectQueueHandler extends DurableObject<CloudflareEnv> {
5576 // We don't need to revalidate in this case
5677 if ( this . checkSyncTable ( msg ) ) return ;
5778
58- if ( this . ongoingRevalidations . size >= MAX_REVALIDATION_BY_DURABLE_OBJECT ) {
79+ if ( this . ongoingRevalidations . size >= this . maxRevalidations ) {
5980 const ongoingRevalidations = this . ongoingRevalidations . values ( ) ;
6081 // When there is more than the max revalidations, we block concurrency until one of the revalidations finishes
6182 // We still await the promise to ensure the revalidation is completed
@@ -86,7 +107,7 @@ export class DurableObjectQueueHandler extends DurableObject<CloudflareEnv> {
86107 "x-prerender-revalidate" : process . env . __NEXT_PREVIEW_MODE_ID ! ,
87108 "x-isr" : "1" ,
88109 } ,
89- signal : AbortSignal . timeout ( DEFAULT_REVALIDATION_TIMEOUT_MS ) ,
110+ signal : AbortSignal . timeout ( this . revalidationTimeout ) ,
90111 } ) ;
91112 // Now we need to handle errors from the fetch
92113 if ( response . status === 200 && response . headers . get ( "x-nextjs-cache" ) !== "REVALIDATED" ) {
@@ -158,20 +179,21 @@ export class DurableObjectQueueHandler extends DurableObject<CloudflareEnv> {
158179
159180 async addToFailedState ( msg : QueueMessage ) {
160181 const existingFailedState = this . routeInFailedState . get ( msg . MessageDeduplicationId ) ;
161- let nextAlarm = Date . now ( ) + 2_000 ;
182+ let nextAlarm = Date . now ( ) + this . revalidationRetryInterval ;
162183
163184 let updatedFailedState : FailedState ;
164185
165186 if ( existingFailedState ) {
166- if ( existingFailedState . retryCount >= 6 ) {
187+ if ( existingFailedState . retryCount >= this . maxRevalidationAttempts ) {
167188 // We give up after 6 retries and log the error
168189 error (
169190 `The revalidation for ${ msg . MessageBody . host } ${ msg . MessageBody . url } has failed after 6 retries. It will not be tried again, but subsequent ISR requests will retry.`
170191 ) ;
171192 this . routeInFailedState . delete ( msg . MessageDeduplicationId ) ;
172193 return ;
173194 }
174- nextAlarm = Date . now ( ) + Math . pow ( 2 , existingFailedState . retryCount + 1 ) * 2_000 ;
195+ nextAlarm =
196+ Date . now ( ) + Math . pow ( 2 , existingFailedState . retryCount + 1 ) * this . revalidationRetryInterval ;
175197 updatedFailedState = {
176198 ...existingFailedState ,
177199 retryCount : existingFailedState . retryCount + 1 ,
@@ -206,7 +228,7 @@ export class DurableObjectQueueHandler extends DurableObject<CloudflareEnv> {
206228 ) ;
207229 if ( nextAlarmToSetup < Date . now ( ) ) {
208230 // We don't want to set an alarm in the past
209- nextAlarmToSetup = Date . now ( ) + 2_000 ;
231+ nextAlarmToSetup = Date . now ( ) + this . revalidationRetryInterval ;
210232 }
211233 await this . ctx . storage . setAlarm ( nextAlarmToSetup ) ;
212234 }
0 commit comments