-
Notifications
You must be signed in to change notification settings - Fork 209
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix a rare issue with incorrect message order when sending messages offline #3316
Conversation
Generated by 🚫 Danger |
85cee3b
to
a05ad79
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good 👍 Added few questions, and also e2e tests need to be checked before merging.
Sources/StreamChat/APIClient/Endpoints/EndpointPath+OfflineRequest.swift
Outdated
Show resolved
Hide resolved
a05ad79
to
f058c43
Compare
f058c43
to
ed70b02
Compare
After a longer discussion we'll change the direction a bit. |
…essages while offline
ed70b02
to
45f360d
Compare
StreamChat XCMetrics
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code wise for now it looks good, but I'm going to request changes, since while doing QA it is introducing some regressions 👍
@@ -88,6 +88,47 @@ class MessageRepository { | |||
}) | |||
} | |||
} | |||
|
|||
/// Marks the message's local status to failed and adds it to the offline retry which sends the message when connection comes back. | |||
func scheduleOfflineRetry(for messageId: MessageId, completion: @escaping (Result<ChatMessage, MessageRepositoryError>) -> Void) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MessageSender uses this to send queued messages directly to offline repo when it sees that there is connection issue.
// Run offline actions requests as the first thing | ||
if config.isLocalStorageEnabled { | ||
operations.append(ExecutePendingOfflineActions(offlineRequestsRepository: offlineRequestsRepository)) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved it to the first item on the syncing list so that we retry more quickly rather than waiting after other stuff.
Quality Gate passedIssues Measures |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! ✅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍
🔗 Issue Links
Resolves PBE-4319
🎯 Goal
Fix the issue of incorrect order of messages when multiple messages are in the pending send state and connection comes back.
📝 Summary
OfflineRequestsRepository
for retrying on the next web-socket connect event (otherwise we have a race between it andMessageSender
). Message statuses are set to.sendingFailed
.MessageSender
is waiting for connection, it sends all the requests to the offline repository until it is notified connection status change (ensures thatMessageSender
andOfflineRequestsRepository
are not sending messages for the came channel at the same time).OfflineRequestsRepository
removes duplicate send message requests (in case or manual retries while offline)🛠 Implementation
APIClient
sends failed API requests toSyncRepository
here. This will then be passed toOfflineRequestsRepository
which uses the shouldBeQueuedOffline for deciding if it should retry the failed request.When this happens, we have
MessageSender
andOfflineRequestsRepository
both trying to send messages on connect. This PR eliminates this race and makesOfflineRequestsRepository
to be solely responsible of sending messages when connection status changes. When we have connected,MessageSender
is allowed to send messages again if user does so. But all the previous ones, are handled byOfflineRequestsRepository
.🎨 Showcase
Recorded from the point where the first request has failed with a connection issue.
🧪 Manual Testing Notes
Test case 1:
Test case 2
Messages are sent one by one. Currently order changes because server gives updated timestamps. Can be improved if we would like to, but I did not want to include more changes to this PR. Solution would be to update local timestamps after each message send.
☑️ Contributor Checklist