From 1b14e7f2234e0ad407fd7b791d711d9c1dc1b5ac Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 3 Dec 2021 14:51:11 +0100 Subject: [PATCH 1/7] fix(llc): fix retry queue mechanism --- .../lib/src/client/retry_queue.dart | 35 +++++++++---------- .../lib/src/message_widget.dart | 4 +-- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/packages/stream_chat/lib/src/client/retry_queue.dart b/packages/stream_chat/lib/src/client/retry_queue.dart index c441b5fb..f00f12ed 100644 --- a/packages/stream_chat/lib/src/client/retry_queue.dart +++ b/packages/stream_chat/lib/src/client/retry_queue.dart @@ -71,14 +71,15 @@ class RetryQueue { /// Add a list of messages void add(List messages) { if (messages.isEmpty) return; - if (_messageQueue.containsAllMessage(messages)) return; + if (!_messageQueue.containsAllMessage(messages)) { + logger?.info('Adding ${messages.length} messages'); + final messageList = _messageQueue.toList(); + // we should not add message if already available in the queue + _messageQueue.addAll(messages.where( + (it) => !messageList.any((m) => m.id == it.id), + )); + } - logger?.info('Adding ${messages.length} messages'); - final messageList = _messageQueue.toList(); - // we should not add message if already available in the queue - _messageQueue.addAll(messages.where( - (it) => !messageList.any((m) => m.id == it.id), - )); _startRetrying(); } @@ -87,9 +88,9 @@ class RetryQueue { _isRetrying = true; logger?.info('Started retrying failed messages'); - while (_messageQueue.isNotEmpty) { + for (var i = 0; i < _messageQueue.length; ++i) { logger?.info('${_messageQueue.length} messages remaining in the queue'); - final message = _messageQueue.first; + final message = _messageQueue.toList()[i]; await _runAndRetry(message); } _isRetrying = false; @@ -109,8 +110,12 @@ class RetryQueue { await _retryMessage(message); logger?.info('Message (${message.id}) sent successfully'); _messageQueue.removeMessage(message); - break; - } on StreamChatError catch (e) { + return; + } catch (e) { + if (e is! StreamChatNetworkError || !e.isRetriable) { + _messageQueue.removeMessage(message); + return; + } // retry logic final maxAttempt = _retryPolicy.maxRetryAttempts; if (attempt < maxAttempt) { @@ -143,14 +148,6 @@ class RetryQueue { _sendFailedEvent(message); break; } - } catch (e) { - logger?.info( - 'API call failed due to unknown error (attempt $attempt). ' - 'Giving up for now, will retry when connection recovers. ' - 'Error was $e', - ); - _sendFailedEvent(message); - break; } } } diff --git a/packages/stream_chat_flutter/lib/src/message_widget.dart b/packages/stream_chat_flutter/lib/src/message_widget.dart index 6182df54..4010b11b 100644 --- a/packages/stream_chat_flutter/lib/src/message_widget.dart +++ b/packages/stream_chat_flutter/lib/src/message_widget.dart @@ -832,8 +832,8 @@ class _MessageWidgetState extends State ), if (isFailedState) Positioned( - left: widget.reverse ? 0 : null, - right: widget.reverse ? null : 0, + right: widget.reverse ? 0 : null, + left: widget.reverse ? null : 0, bottom: showBottomRow ? 18 : -2, child: StreamSvgIcon.error(size: 20), ), From 7547bd6b86cc5b7b09dbac2376ed0b570404315a Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 3 Dec 2021 15:38:23 +0100 Subject: [PATCH 2/7] fix(llc): retry queue now follows the creation date --- .../stream_chat/lib/src/client/channel.dart | 2 +- .../lib/src/client/retry_queue.dart | 19 ++++++++++++------- .../lib/src/message_actions_modal.dart | 6 +----- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/packages/stream_chat/lib/src/client/channel.dart b/packages/stream_chat/lib/src/client/channel.dart index 657b8617..51034d3a 100644 --- a/packages/stream_chat/lib/src/client/channel.dart +++ b/packages/stream_chat/lib/src/client/channel.dart @@ -1698,7 +1698,7 @@ class ChannelClientState { } _channelState = _channelState.copyWith( - messages: newMessages, + messages: newMessages..sort(_sortByCreatedAt), channel: _channelState.channel?.copyWith( lastMessageAt: message.createdAt, ), diff --git a/packages/stream_chat/lib/src/client/retry_queue.dart b/packages/stream_chat/lib/src/client/retry_queue.dart index f00f12ed..e1b6df70 100644 --- a/packages/stream_chat/lib/src/client/retry_queue.dart +++ b/packages/stream_chat/lib/src/client/retry_queue.dart @@ -88,20 +88,24 @@ class RetryQueue { _isRetrying = true; logger?.info('Started retrying failed messages'); - for (var i = 0; i < _messageQueue.length; ++i) { + while (_messageQueue.isNotEmpty) { logger?.info('${_messageQueue.length} messages remaining in the queue'); - final message = _messageQueue.toList()[i]; - await _runAndRetry(message); + final message = _messageQueue.first; + final succeeded = await _runAndRetry(message); + if (!succeeded) { + _messageQueue.toList().forEach(_sendFailedEvent); + break; + } } _isRetrying = false; } - Future _runAndRetry(Message message) async { + Future _runAndRetry(Message message) async { var attempt = 1; final maxAttempt = _retryPolicy.maxRetryAttempts; // early return in case maxAttempt is less than 0 - if (attempt > maxAttempt) return; + if (attempt > maxAttempt) return false; // ignore: literal_only_boolean_expressions while (true) { @@ -110,11 +114,11 @@ class RetryQueue { await _retryMessage(message); logger?.info('Message (${message.id}) sent successfully'); _messageQueue.removeMessage(message); - return; + return true; } catch (e) { if (e is! StreamChatNetworkError || !e.isRetriable) { _messageQueue.removeMessage(message); - return; + return true; } // retry logic final maxAttempt = _retryPolicy.maxRetryAttempts; @@ -150,6 +154,7 @@ class RetryQueue { } } } + return false; } void _sendFailedEvent(Message message) { diff --git a/packages/stream_chat_flutter/lib/src/message_actions_modal.dart b/packages/stream_chat_flutter/lib/src/message_actions_modal.dart index a67004af..23f3a096 100644 --- a/packages/stream_chat_flutter/lib/src/message_actions_modal.dart +++ b/packages/stream_chat_flutter/lib/src/message_actions_modal.dart @@ -533,11 +533,7 @@ class _MessageActionsModalState extends State { onTap: () { Navigator.pop(context); final channel = StreamChannel.of(context).channel; - if (isUpdateFailed) { - channel.updateMessage(widget.message); - } else { - channel.sendMessage(widget.message); - } + channel.state?.retryFailedMessages(); }, child: Padding( padding: const EdgeInsets.symmetric(vertical: 11, horizontal: 16), From 06b090dac2b4caa89fea136b09f87c83db4744e2 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 3 Dec 2021 15:43:49 +0100 Subject: [PATCH 3/7] fix(llc): revert message action --- .../lib/src/message_actions_modal.dart | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/stream_chat_flutter/lib/src/message_actions_modal.dart b/packages/stream_chat_flutter/lib/src/message_actions_modal.dart index 23f3a096..e85e7cd8 100644 --- a/packages/stream_chat_flutter/lib/src/message_actions_modal.dart +++ b/packages/stream_chat_flutter/lib/src/message_actions_modal.dart @@ -533,7 +533,11 @@ class _MessageActionsModalState extends State { onTap: () { Navigator.pop(context); final channel = StreamChannel.of(context).channel; - channel.state?.retryFailedMessages(); + if (isUpdateFailed) { + channel.updateMessage(widget.message); + } else { + channel.sendMessage(widget.message); + } }, child: Padding( padding: const EdgeInsets.symmetric(vertical: 11, horizontal: 16), @@ -606,7 +610,9 @@ class _MessageActionsModalState extends State { widget.editMessageInputBuilder!(context, widget.message) else MessageInput( - editMessage: widget.message, + messageInputController: MessageInputController( + message: widget.message, + ), preMessageSending: (m) { FocusScope.of(context).unfocus(); Navigator.pop(context); From 37738461019ceded89ad49d5da32fd9311d8c7e0 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 3 Dec 2021 15:45:13 +0100 Subject: [PATCH 4/7] fix(llc): revert message action --- .../stream_chat_flutter/lib/src/message_actions_modal.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/stream_chat_flutter/lib/src/message_actions_modal.dart b/packages/stream_chat_flutter/lib/src/message_actions_modal.dart index e85e7cd8..ca062388 100644 --- a/packages/stream_chat_flutter/lib/src/message_actions_modal.dart +++ b/packages/stream_chat_flutter/lib/src/message_actions_modal.dart @@ -610,9 +610,6 @@ class _MessageActionsModalState extends State { widget.editMessageInputBuilder!(context, widget.message) else MessageInput( - messageInputController: MessageInputController( - message: widget.message, - ), preMessageSending: (m) { FocusScope.of(context).unfocus(); Navigator.pop(context); From 48e8ac25975f4d82c07297ddc66a98aa64026143 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 3 Dec 2021 15:45:39 +0100 Subject: [PATCH 5/7] fix(llc): revert message action --- packages/stream_chat_flutter/lib/src/message_actions_modal.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/stream_chat_flutter/lib/src/message_actions_modal.dart b/packages/stream_chat_flutter/lib/src/message_actions_modal.dart index ca062388..a67004af 100644 --- a/packages/stream_chat_flutter/lib/src/message_actions_modal.dart +++ b/packages/stream_chat_flutter/lib/src/message_actions_modal.dart @@ -610,6 +610,7 @@ class _MessageActionsModalState extends State { widget.editMessageInputBuilder!(context, widget.message) else MessageInput( + editMessage: widget.message, preMessageSending: (m) { FocusScope.of(context).unfocus(); Navigator.pop(context); From 14cd59f11b198c63ea840a9446e6647b347b67f3 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 3 Dec 2021 15:54:30 +0100 Subject: [PATCH 6/7] chore(llc): update changelog --- packages/stream_chat/CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/stream_chat/CHANGELOG.md b/packages/stream_chat/CHANGELOG.md index d27ac852..3f20271f 100644 --- a/packages/stream_chat/CHANGELOG.md +++ b/packages/stream_chat/CHANGELOG.md @@ -3,7 +3,8 @@ 🐞 Fixed - [[#799]](https://github.com/GetStream/stream-chat-flutter/issues/799) Fixed `totalUnreadCount` is not updating when - app is resumed from background mode + app is resumed from background mode. +- Fix retry mechanism failing in some cases. ## 3.3.0 From 5e91e1f501a55b5e75e229e3fae3214af4bed297 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 3 Dec 2021 16:11:31 +0100 Subject: [PATCH 7/7] chore(repo): remove prefer-match-file-name --- analysis_options.yaml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index e5eaf7ca..03a4220e 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -154,18 +154,6 @@ dart_code_metrics: # Dart Specific - binary-expression-operand-order - double-literal-format - - prefer-match-file-name: - exclude: - - packages/*/test/** - - packages/*/example/** - - packages/**/util/** - - packages/**/utils.dart - - packages/stream_chat/lib/src/client/client.dart - - packages/stream_chat/lib/src/core/api/responses.dart - - packages/stream_chat/lib/src/core/api/requests.dart - - packages/stream_chat/lib/src/core/platform_detector/** - - packages/stream_chat_persistence/lib/src/db/shared/** - - packages/stream_chat_localizations/lib/src/stream_chat_localizations.dart - no-boolean-literal-compare - no-equal-then-else - no-empty-block: