Decouple adding a channel to a channel list from the watch() call - #6660
Draft
VelikovPetar wants to merge 5 commits into
Draft
Decouple adding a channel to a channel list from the watch() call#6660VelikovPetar wants to merge 5 commits into
watch() call#6660VelikovPetar wants to merge 5 commits into
Conversation
…all on `notification.added_to_channel` event
Contributor
PR checklist ✅All required conditions are satisfied:
🎉 Great job! This PR is ready for review. |
watch() call
Contributor
SDK Size Comparison 📏
|
|
| internal suspend fun addAndWatchChannel(cid: String, channel: Channel? = null) { | ||
| if (channel != null) { | ||
| // Add the channel to the list, regardless of the `watch` outcome | ||
| addChannel(channel) |
Contributor
There was a problem hiding this comment.
Should this be trackChannel rather than addChannel — since addChannel writes the event payload through to shared per-channel state and nulls membership, which GroupAwareChatEventHandler later reads as "not a member" and removes the channel?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Goal
EventHandlingResult.WatchAndAddis the only way a channel the client has never seen can enter a channel list. It is produced bynotification.added_to_channel,notification.message_newandchannel.visible, and it was implemented as:This makes list membership conditional on a network round-trip, and silently discards the channel when that call fails.
It is worse than a transient miss, because
watchalso subscribes the user to the channel server-side. Once subscribed, the server stops sending that usernotification.*events for the channel and sends only channel-scoped ones, which cannot introduce a channel the client does not already know about. A failedwatchtherefore leaves the user subscribed to a channel that is in no list, with no event able to repair it until the next query — i.e. until the app is restarted.Android is the only SDK that works this way. iOS links the channel into the query straight from the event payload (
ChannelListLinker) and treats the watch as a non-gating follow-up whose failure is a warning log; stream-chat-js promotes not-yet-loaded channels (allowNotLoadedChannelPromotionForEvent, all four flags defaulttrue); Flutter re-queries the list.Related: AND-1447.
Implementation
Invert the order — seed the list from the event's own channel payload, then watch as a refresh:
The event payload is sufficient to build the list entry — verified over the wire that
notification.added_to_channelcarries a fully populated channel (config,members,own_capabilities, custom fields).To reach the payload at the call site,
parseChatEventResultsnow returnsList<Pair<ChatEvent, EventHandlingResult>>andEventHandlerSequential.handleChatEventspasses(event as? HasChannel)?.channel. Both areinternal, so there is no public API change and noapiDumpneeded.All three
WatchAndAddproducers implementHasChannel. A customChatEventHandlerreturningWatchAndAddfor some other event still works —channelis null and the previous behaviour applies.Re-adding the same channel on success is idempotent:
QueryChannelsSpec.cidsis aSet,rawChannelsis keyed by cid,joinMessagesends indistinctBy { it.id }andjoinMembersmerges viaassociateBy { getUserId() }.UI Changes
No UI changes.
Testing
Unit tests added to
QueryChannelsLogicTest:watchfailswatchfails and the event carried no channel:stream-chat-android-state:testDebugUnitTest,:stream-chat-android-state:detektand:stream-chat-android-state:spotlessCheckall pass.Manual verification on device with a simulated
watchfailure (failing at theResultlevel, so the failure path is actually reached):notification.added_to_channelarrives — the channel now appears in the list despite the failedwatch. Previously it did not appear at all.notification.message_new.Note when reproducing: forcing the failure with a malformed cid does not exercise this path.
ChatClient.channel(cid)callscidToTypeAndId()eagerly, whichcheck()s the format and throws, so theResult.Failurebranch is never reached and the exception aborts the whole event batch.