44// This sample demonstrates retry and error handling in the Durable Task SDK:
55// 1. RetryPolicy — declarative retry with exponential backoff
66// 2. handleFailure predicate — selectively retry based on error type
7- // 3. AsyncRetryHandler — imperative retry logic with custom delays
7+ // 3. RetryHandler — imperative retry logic with custom control
88// 4. Sub-orchestration retry — retry an entire sub-orchestration
99// 5. raiseIfFailed() — convenient error checking on orchestration state
1010
@@ -24,7 +24,7 @@ import {
2424 RetryPolicy ,
2525 OrchestrationStatus ,
2626} from "@microsoft/durabletask-js" ;
27- import type { AsyncRetryHandler , RetryContext , TaskRetryOptions } from "@microsoft/durabletask-js" ;
27+ import type { RetryHandler , RetryContext } from "@microsoft/durabletask-js" ;
2828
2929// ---------------------------------------------------------------------------
3030// Activities
@@ -105,24 +105,28 @@ const handleFailureOrchestrator: TOrchestrator = async function* (ctx: Orchestra
105105} ;
106106
107107/**
108- * 3. AsyncRetryHandler — custom imperative retry logic.
109- * Implements a custom delay strategy: 100ms, 200ms, 400ms, then gives up.
108+ * 3. RetryHandler — custom imperative retry logic.
109+ * Uses a sync handler that retries up to maxAttempts times.
110+ * Returns true for immediate retry, or false to stop.
110111 */
111112const customRetryHandlerOrchestrator : TOrchestrator = async function * ( ctx : OrchestrationContext ) : any {
112113 const maxAttempts = 4 ;
113114
114- const customRetryHandler : AsyncRetryHandler = async ( retryCtx : RetryContext ) => {
115+ const customRetryHandler : RetryHandler = ( retryCtx : RetryContext ) => {
115116 if ( retryCtx . lastAttemptNumber >= maxAttempts ) {
116117 return false ; // give up
117118 }
118- // Exponential delay: 100ms, 200ms, 400ms
119- return 100 * Math . pow ( 2 , retryCtx . lastAttemptNumber - 1 ) ;
119+ // Only retry transient errors
120+ if ( ! retryCtx . lastFailure . message ?. includes ( "TransientError" ) ) {
121+ return false ;
122+ }
123+ return true ; // retry immediately
120124 } ;
121125
122126 const result : string = yield ctx . callActivity (
123127 unreliableActivity ,
124128 { key : `custom-handler-${ ctx . instanceId } ` , failCount : 2 } ,
125- { retry : customRetryHandler as TaskRetryOptions } ,
129+ { retry : customRetryHandler } ,
126130 ) ;
127131
128132 return result ;
@@ -206,8 +210,8 @@ const alwaysFailOrchestrator: TOrchestrator = async function* (ctx: Orchestratio
206210 console . log ( `Status: ${ OrchestrationStatus [ state2 ! . runtimeStatus ] } ` ) ;
207211 console . log ( `Result: ${ state2 ?. serializedOutput } ` ) ;
208212
209- // --- 3. Custom AsyncRetryHandler ---
210- console . log ( "\n=== 3. Custom AsyncRetryHandler ===" ) ;
213+ // --- 3. Custom RetryHandler ---
214+ console . log ( "\n=== 3. Custom RetryHandler ===" ) ;
211215 const id3 = await client . scheduleNewOrchestration ( customRetryHandlerOrchestrator ) ;
212216 const state3 = await client . waitForOrchestrationCompletion ( id3 , true , 60 ) ;
213217 console . log ( `Status: ${ OrchestrationStatus [ state3 ! . runtimeStatus ] } ` ) ;
@@ -233,7 +237,7 @@ const alwaysFailOrchestrator: TOrchestrator = async function* (ctx: Orchestratio
233237 }
234238 if ( state5 ?. failureDetails ) {
235239 console . log ( `Failure type: ${ state5 . failureDetails . errorType } ` ) ;
236- console . log ( `Failure message: ${ state5 . failureDetails . errorMessage ?. substring ( 0 , 80 ) } ` ) ;
240+ console . log ( `Failure message: ${ state5 . failureDetails . message ?. substring ( 0 , 80 ) } ` ) ;
237241 }
238242
239243 console . log ( "\n=== All retry/error demos completed successfully! ===" ) ;
0 commit comments