@@ -302,7 +302,7 @@ async function upsert(
302
302
client . update ( service , ( err , res ) => ( err ? reject ( err ) : resolve ( res ! ) ) )
303
303
) ;
304
304
if ( inputs . waitForSteadyState ) {
305
- await waitForSteadyState (
305
+ await retryWaitForSteadyState (
306
306
client ,
307
307
serviceInfo . getEtag ( ) ,
308
308
serviceInfo . getService ( ) ! . getName ( )
@@ -357,6 +357,35 @@ function waitForSteadyState(
357
357
} ) ;
358
358
}
359
359
360
+ type GrpcError = Error & { code : grpc . status ; details : string ; metadata : any } ;
361
+
362
+ async function retryWaitForSteadyState (
363
+ client : fabric . FabricControllerClient ,
364
+ etag : string ,
365
+ service : string
366
+ ) {
367
+ while ( true ) {
368
+ try {
369
+ return await waitForSteadyState ( client , etag , service ) ;
370
+ } catch ( err ) {
371
+ switch ( ( err as GrpcError ) . code ) {
372
+ case grpc . status . INTERNAL :
373
+ // {"code":13,"details":"Received RST_STREAM with code 2 (Internal server error)","metadata":{}}
374
+ if ( debug ) pulumi . log . info ( `Retry after INTERNAL error: ${ err } ` ) ;
375
+ break ;
376
+ case grpc . status . UNAVAILABLE :
377
+ // {"code":14,"details":"unavailable","metadata":{"server":["awselb/2.0"],"date":["Fri, 18 Oct 2024 03:25:32 GMT"],"content-type":["application/grpc"],"content-length":["0"],"grpc-previous-rpc-attempts":["4"]}}
378
+ if ( debug ) pulumi . log . info ( `Retry after UNAVAILABLE error: ${ err } ` ) ;
379
+ break ;
380
+ default :
381
+ throw err ;
382
+ }
383
+ // Wait for 1s before retrying; this matches the behavior of the Defang CLI
384
+ await new Promise ( ( resolve ) => setTimeout ( resolve , 1000 ) ) ;
385
+ }
386
+ }
387
+ }
388
+
360
389
function convertProtocol ( protocol ?: Protocol ) {
361
390
switch ( protocol ) {
362
391
case "tcp" :
0 commit comments