@@ -19,6 +19,7 @@ import 'service_extensions.dart' as extensions;
1919import 'service_utils.dart' ;
2020
2121final _log = Logger ('service_extension_manager' );
22+ const _dwdsTransientRetryDelay = Duration (milliseconds: 100 );
2223
2324/// Manager that handles tracking the service extension for the main isolate.
2425final class ServiceExtensionManager with DisposerMixin {
@@ -59,6 +60,40 @@ final class ServiceExtensionManager with DisposerMixin {
5960 ConnectedApp get connectedApp => _connectedApp! ;
6061 ConnectedApp ? _connectedApp;
6162
63+ bool _shouldRetryServiceExtensionCall (Object error) {
64+ return connectedApp.isDebuggableWebApp &&
65+ error is RPCError &&
66+ error.isDwdsPromiseCollectedError;
67+ }
68+
69+ Future <Response > _callServiceExtensionWithRetry (
70+ String method, {
71+ String ? isolateId,
72+ Map <String , Object ?>? args,
73+ }) async {
74+ try {
75+ return await _service! .callServiceExtension (
76+ method,
77+ isolateId: isolateId,
78+ args: args,
79+ );
80+ } catch (error, st) {
81+ if (! _shouldRetryServiceExtensionCall (error)) rethrow ;
82+
83+ _log.info (
84+ 'Retrying transient DWDS error for service extension $method : $error ' ,
85+ error,
86+ st,
87+ );
88+ await Future <void >.delayed (_dwdsTransientRetryDelay);
89+ return await _service! .callServiceExtension (
90+ method,
91+ isolateId: isolateId,
92+ args: args,
93+ );
94+ }
95+ }
96+
6297 Future <void > _handleIsolateEvent (Event event) async {
6398 if (event.kind == EventKind .kServiceExtensionAdded) {
6499 // On hot restart, service extensions are added from here.
@@ -207,7 +242,7 @@ final class ServiceExtensionManager with DisposerMixin {
207242 _checkForFirstFrameStarted = true ;
208243
209244 try {
210- final value = await _service ! . callServiceExtension (
245+ final value = await _callServiceExtensionWithRetry (
211246 extensions.didSendFirstFrameEvent,
212247 isolateId: lastMainIsolate.id,
213248 );
@@ -317,7 +352,7 @@ final class ServiceExtensionManager with DisposerMixin {
317352 // The restore request is obsolete if the isolate has changed.
318353 if (isolateRef != _mainIsolate) return false ;
319354 try {
320- final response = await _service ! . callServiceExtension (
355+ final response = await _callServiceExtensionWithRetry (
321356 name,
322357 isolateId: isolateRef.id,
323358 );
@@ -403,7 +438,7 @@ final class ServiceExtensionManager with DisposerMixin {
403438 try {
404439 if (value is bool ) {
405440 Future <void > call (String ? isolateId, bool value) async {
406- await _service ! . callServiceExtension (
441+ await _callServiceExtensionWithRetry (
407442 name,
408443 isolateId: isolateId,
409444 args: {'enabled' : value},
@@ -423,13 +458,13 @@ final class ServiceExtensionManager with DisposerMixin {
423458 await call (mainIsolate.id, value);
424459 }
425460 } else if (value is String ) {
426- await _service ! . callServiceExtension (
461+ await _callServiceExtensionWithRetry (
427462 name,
428463 isolateId: mainIsolate.id,
429464 args: {'value' : value},
430465 );
431466 } else if (value is double ) {
432- await _service ! . callServiceExtension (
467+ await _callServiceExtensionWithRetry (
433468 name,
434469 isolateId: mainIsolate.id,
435470 // The param name for a numeric service extension will be the last part
0 commit comments