Open linhewinner opened 4 weeks ago
Hey @linhewinner , it would not work if getChannel
was called in useMessageNewListener
as message.new
is not delivered for a channel that is not watched. The WS is established from the beginning of the session and it is true, that WS can be sometimes faster the HTTP request completion.
In your stack trace I see the invocation of useIsChannelMuted
hook. This hook requests a channel's mute status as a reaction to notification.channel_mutes_updated
event. Do you update mutes on each member addition?
Hi @MartinCupela
Thank you for the reply.
re: The WS is established from the beginning of the session and it is true, that WS can be sometimes faster the HTTP request completion.
Thanks for the confirmation. Sounds like we are on the same page that this is a plausible race condition.
re: Do you update mutes on each member addition?
No.
re: useIsChannelMuted ... requests a channel's mute status as a reaction to notification.channel_mutes_updated event
This statement is not accurate according to my reading/debugging of the code.
This hook is used here in ChannelPreview unconditionally (as hooks must be called unconditionally):
https://github.com/GetStream/stream-chat-react/blob/afcd40fbd95cef7ec1237babb40a3460926618a8/src/components/ChannelPreview/ChannelPreview.tsx#L86
Every time a new channel is added to ChannelList
, the rendering code would call useIsChannelMuted
unconditionally.
re: it would not work if getChannel was called in useMessageNewListener as message.new is not delivered for a channel that is not watched
Not sure if I follow your logic. See the following attached screenshot. As a matter of fact, I use getChannel
inside the handler, and it works like a charm.
As a workaround, in our codebase I override the onMessageNewHandler callback. I call getChannel
, which perfectly avoids the race condition (I used console.log to verify inside this handler that race condition induced crash would have happened if I hadn't called getChannel
)
Describe the bug
The whole web page occasionally crashes if the user is added to a new channel and immediately receives a message from that channel.
To Reproduce
Steps to reproduce the behavior:
Please read my "Additional Context" to understand what's going on and why this is only a 10% repro.
Expected behavior The web page should not crash.
Package version
Additional context
I know that if I reported a bug that only reproduces 10% of the time, my bug report would probably get buried. I took it upon myself to debug the issue and found the root cause. I will explain my findings and suggest a pretty obvious fix. I hope this can speed up Stream prioritizing this bug.
The stack trace of the crash:
How the code is supposed to work:
getChannel
will call .watch() on the channel.90% of the time the events happen in the order of 1, 2, 3, 4. There is no crash because in step 4, the channel is already watched (aka initialized). But 10% of the time, the events happen in the order of 1, 2, 4, 3. In 4, an uninitialized channel is added to ChannelList, resulting in the stack trace of crash above.
Now, why would 4 happen before 3? Isn't "message.new" supposed to fire AFTER a channel is watched? The race condition happens because .watch() is asynchronous. Somewhere in the middle of that call, the web socket is established and the "message.new" event comes down BEFORE the whole .watch() is resolved.
Obviously this is a race condition that doesn't happen all the time. It really depends on how soon the message is sent after the user is added to the channel. It also depends on how much time elapses between the establishment of web socket and finishing the rest of .watch() call. In our product, every user goes through a flow in onboarding where they add themselves into a chat channel and we immediately send a message when you are added. About 10% of the times, a user's first impression of our product is a crashed web page ....
A simple fix would be to call getChannel in useMessageNewListener