@@ -22,6 +22,7 @@ import '../notifications/receive.dart';
2222import 'autocomplete.dart' ;
2323import 'database.dart' ;
2424import 'emoji.dart' ;
25+ import 'localizations.dart' ;
2526import 'message.dart' ;
2627import 'message_list.dart' ;
2728import 'recent_dm_conversations.dart' ;
@@ -912,10 +913,28 @@ class UpdateMachine {
912913 }());
913914 }
914915
916+ /// This controls when we start to report transient errors to the user when
917+ /// polling.
918+ ///
919+ /// At the 6th failure, the expected time elapsed since the first failure
920+ /// will be 1.55 seocnds.
921+ static const transientFailureCountNotifyThreshold = 5 ;
922+
915923 void poll () async {
916924 assert (! _disposed);
917925
918926 BackoffMachine ? backoffMachine;
927+ int accumulatedTransientFailureCount = 0 ;
928+
929+ /// This only reports transient errors after reaching
930+ /// a pre-defined threshold of retries.
931+ void maybeReportTransientError (String ? message, {String ? details}) {
932+ accumulatedTransientFailureCount++ ;
933+ if (accumulatedTransientFailureCount > transientFailureCountNotifyThreshold) {
934+ reportErrorToUserBriefly (message, details: details);
935+ }
936+ }
937+
919938 while (true ) {
920939 if (_debugLoopSignal != null ) {
921940 await _debugLoopSignal! .future;
@@ -935,6 +954,8 @@ class UpdateMachine {
935954 if (_disposed) return ;
936955
937956 store.isLoading = true ;
957+ final localizations = GlobalLocalizations .zulipLocalizations;
958+ final serverUrl = store.connection.realmUrl.origin;
938959 switch (e) {
939960 case ZulipApiException (code: 'BAD_EVENT_QUEUE_ID' ):
940961 assert (debugLog ('Lost event queue for $store . Replacing…' ));
@@ -946,15 +967,22 @@ class UpdateMachine {
946967 case Server5xxException () || NetworkException ():
947968 assert (debugLog ('Transient error polling event queue for $store : $e \n '
948969 'Backing off, then will retry…' ));
949- // TODO tell user if transient polling errors persist
970+ maybeReportTransientError (
971+ localizations.errorConnectingToServerShort,
972+ details: localizations.errorConnectingToServerDetails (
973+ serverUrl, e.toString ()));
950974 await (backoffMachine ?? = BackoffMachine ()).wait ();
951975 assert (debugLog ('… Backoff wait complete, retrying poll.' ));
952976 continue ;
953977
954978 default :
955979 assert (debugLog ('Error polling event queue for $store : $e \n '
956980 'Backing off and retrying even though may be hopeless…' ));
957- // TODO tell user on non-transient error in polling
981+ // TODO(#186): Handle unrecoverable failures
982+ reportErrorToUserBriefly (
983+ localizations.errorConnectingToServerShort,
984+ details: localizations.errorConnectingToServerDetails (
985+ serverUrl, e.toString ()));
958986 await (backoffMachine ?? = BackoffMachine ()).wait ();
959987 assert (debugLog ('… Backoff wait complete, retrying poll.' ));
960988 continue ;
@@ -978,6 +1006,9 @@ class UpdateMachine {
9781006 // and failures, the successes themselves should space out the requests.
9791007 backoffMachine = null ;
9801008 store.isLoading = false ;
1009+ // Dismiss existing errors, if any.
1010+ reportErrorToUserBriefly (null );
1011+ accumulatedTransientFailureCount = 0 ;
9811012
9821013 final events = result.events;
9831014 for (final event in events) {
0 commit comments