Skip to content

Commit 6cca07d

Browse files
authored
perf: channel state updates (#3055)
* perf: throttle message copying updates * fix: throttle all other msg copies * perf: use throttled message copying everywhere * perf: handle setting read state separately * fix: channel watching in offline state * fix: failing faulty test
1 parent e787038 commit 6cca07d

File tree

4 files changed

+56
-36
lines changed

4 files changed

+56
-36
lines changed

package/expo-package/yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4733,10 +4733,10 @@ [email protected], stream-buffers@~2.2.0:
47334733
resolved "https://registry.yarnpkg.com/stream-buffers/-/stream-buffers-2.2.0.tgz#91d5f5130d1cef96dcfa7f726945188741d09ee4"
47344734
integrity sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==
47354735

4736-
4737-
version "6.7.1"
4738-
resolved "https://registry.yarnpkg.com/stream-chat-react-native-core/-/stream-chat-react-native-core-6.7.1.tgz#37cdfbc5c7f8a5bac5634b954da4bbdcd2fb95f2"
4739-
integrity sha512-4ePEMt1W+iw3zUulSDRFO9Nt4HPa8kW6wJ3Qv+ZN+y886rvcUuTuH18MFrdrJtHYb+UxCU+X3oz++3qzq7Jzxw==
4736+
4737+
version "6.7.2"
4738+
resolved "https://registry.yarnpkg.com/stream-chat-react-native-core/-/stream-chat-react-native-core-6.7.2.tgz#955e048b80c55175db084ccbb8519f52ef4bb00c"
4739+
integrity sha512-WJFOCfQ7Xpn8Lr4AE6hUh4Qhrn1eGzsoAcKmL8eSoB/etxdNllOyZ3zrwvZgyy+KIEg9bcX4y+3OWtdKW6qfsA==
47404740
dependencies:
47414741
"@gorhom/bottom-sheet" "^5.1.1"
47424742
dayjs "1.10.5"

package/native-package/yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3409,10 +3409,10 @@ statuses@~1.5.0:
34093409
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
34103410
integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==
34113411

3412-
3413-
version "6.7.1"
3414-
resolved "https://registry.yarnpkg.com/stream-chat-react-native-core/-/stream-chat-react-native-core-6.7.1.tgz#37cdfbc5c7f8a5bac5634b954da4bbdcd2fb95f2"
3415-
integrity sha512-4ePEMt1W+iw3zUulSDRFO9Nt4HPa8kW6wJ3Qv+ZN+y886rvcUuTuH18MFrdrJtHYb+UxCU+X3oz++3qzq7Jzxw==
3412+
3413+
version "6.7.2"
3414+
resolved "https://registry.yarnpkg.com/stream-chat-react-native-core/-/stream-chat-react-native-core-6.7.2.tgz#955e048b80c55175db084ccbb8519f52ef4bb00c"
3415+
integrity sha512-WJFOCfQ7Xpn8Lr4AE6hUh4Qhrn1eGzsoAcKmL8eSoB/etxdNllOyZ3zrwvZgyy+KIEg9bcX4y+3OWtdKW6qfsA==
34163416
dependencies:
34173417
"@gorhom/bottom-sheet" "^5.1.1"
34183418
dayjs "1.10.5"

package/src/components/Channel/Channel.tsx

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -741,14 +741,33 @@ const ChannelWithContext = <
741741
channel,
742742
});
743743

744-
/**
745-
* Since we copy the current channel state all together, we need to find the greatest time among the below two and apply it as the throttling time for copying the channel state.
746-
* This is done until we remove the newMessageStateUpdateThrottleInterval prop.
747-
*/
748-
const copyChannelStateThrottlingTime =
749-
newMessageStateUpdateThrottleInterval > stateUpdateThrottleInterval
750-
? newMessageStateUpdateThrottleInterval
751-
: stateUpdateThrottleInterval;
744+
const setReadThrottled = useMemo(
745+
() =>
746+
throttle(
747+
() => {
748+
if (channel) {
749+
setRead(channel);
750+
}
751+
},
752+
stateUpdateThrottleInterval,
753+
throttleOptions,
754+
),
755+
[channel, stateUpdateThrottleInterval, setRead],
756+
);
757+
758+
const copyMessagesStateFromChannelThrottled = useMemo(
759+
() =>
760+
throttle(
761+
() => {
762+
if (channel) {
763+
copyMessagesStateFromChannel(channel);
764+
}
765+
},
766+
newMessageStateUpdateThrottleInterval,
767+
throttleOptions,
768+
),
769+
[channel, newMessageStateUpdateThrottleInterval, copyMessagesStateFromChannel],
770+
);
752771

753772
const copyChannelState = useMemo(
754773
() =>
@@ -759,10 +778,10 @@ const ChannelWithContext = <
759778
copyMessagesStateFromChannel(channel);
760779
}
761780
},
762-
copyChannelStateThrottlingTime,
781+
stateUpdateThrottleInterval,
763782
throttleOptions,
764783
),
765-
[channel, copyChannelStateThrottlingTime, copyMessagesStateFromChannel, copyStateFromChannel],
784+
[stateUpdateThrottleInterval, channel, copyStateFromChannel, copyMessagesStateFromChannel],
766785
);
767786

768787
const handleEvent: EventHandler<StreamChatGenerics> = (event) => {
@@ -819,6 +838,16 @@ const ChannelWithContext = <
819838

820839
// only update channel state if the events are not the previously subscribed useEffect's subscription events
821840
if (channel && channel.initialized) {
841+
if (event.type === 'message.new') {
842+
copyMessagesStateFromChannelThrottled();
843+
return;
844+
}
845+
846+
if (event.type === 'message.read' || event.type === 'notification.mark_read') {
847+
setReadThrottled();
848+
return;
849+
}
850+
822851
copyChannelState();
823852
}
824853
}
@@ -829,7 +858,7 @@ const ChannelWithContext = <
829858
const initChannel = async () => {
830859
setLastRead(new Date());
831860
const unreadCount = channel.countUnread();
832-
if (!channel || !shouldSyncChannel || channel.offlineMode) {
861+
if (!channel || !shouldSyncChannel) {
833862
return;
834863
}
835864
let errored = false;
@@ -900,20 +929,6 @@ const ChannelWithContext = <
900929
return unsubscribe;
901930
}, [channel?.cid, client]);
902931

903-
/**
904-
* Subscription to the Notification mark_read event.
905-
*/
906-
useEffect(() => {
907-
const handleEvent: EventHandler<StreamChatGenerics> = (event) => {
908-
if (channel.cid === event.cid) {
909-
setRead(channel);
910-
}
911-
};
912-
913-
const { unsubscribe } = client.on('notification.mark_read', handleEvent);
914-
return unsubscribe;
915-
}, [channel, client, setRead]);
916-
917932
const threadPropsExists = !!threadProps;
918933

919934
useEffect(() => {

package/src/components/Channel/__tests__/Channel.test.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ describe('Channel initial load useEffect', () => {
356356
cleanup();
357357
});
358358

359-
it('should not call channel.watch if channel is not initialized', async () => {
359+
it('should still call channel.watch if we are online and DB channels are loaded', async () => {
360360
const messages = Array.from({ length: 10 }, (_, i) => generateMessage({ id: i }));
361361
const mockedChannel = generateChannelResponse({
362362
messages,
@@ -366,13 +366,18 @@ describe('Channel initial load useEffect', () => {
366366
const channel = chatClient.channel('messaging', mockedChannel.id);
367367
await channel.watch();
368368
channel.offlineMode = true;
369-
channel.state = channelInitialState;
369+
channel.state = {
370+
...channelInitialState,
371+
messagePagination: {
372+
hasPrev: true,
373+
},
374+
};
370375
const watchSpy = jest.fn();
371376
channel.watch = watchSpy;
372377

373378
renderComponent({ channel });
374379

375-
await waitFor(() => expect(watchSpy).not.toHaveBeenCalled());
380+
await waitFor(() => expect(watchSpy).toHaveBeenCalledTimes(1));
376381
});
377382

378383
it("should call channel.watch if channel is initialized and it's not in offline mode", async () => {

0 commit comments

Comments
 (0)