From fbc22b4cb73398b34ce7237d2fcf6ed8848f3245 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Fri, 20 Jun 2025 11:06:52 -0300 Subject: [PATCH 1/8] fix: multiple stream subscribe after reconnection --- apps/meteor/client/lib/cachedCollections/CachedCollection.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/meteor/client/lib/cachedCollections/CachedCollection.ts b/apps/meteor/client/lib/cachedCollections/CachedCollection.ts index c9664d46364f4..ab4c84c5b3591 100644 --- a/apps/meteor/client/lib/cachedCollections/CachedCollection.ts +++ b/apps/meteor/client/lib/cachedCollections/CachedCollection.ts @@ -296,6 +296,10 @@ export abstract class CachedCollection { } async init() { + if (this.ready.get()) { + return; + } + if (await this.loadFromCache()) { this.trySync(); } else { From ace9838721e7d011f90807df64c8a7bb28110997 Mon Sep 17 00:00:00 2001 From: Tasso Date: Fri, 20 Jun 2025 12:57:00 -0300 Subject: [PATCH 2/8] Throttle initialization --- .../lib/cachedCollections/CachedCollection.ts | 34 ++++++++++++++----- .../PrivateSettingsCachedCollection.ts | 16 +++++---- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/apps/meteor/client/lib/cachedCollections/CachedCollection.ts b/apps/meteor/client/lib/cachedCollections/CachedCollection.ts index ab4c84c5b3591..1559a770f463f 100644 --- a/apps/meteor/client/lib/cachedCollections/CachedCollection.ts +++ b/apps/meteor/client/lib/cachedCollections/CachedCollection.ts @@ -199,8 +199,8 @@ export abstract class CachedCollection { this.collection.state.replaceAll([]); } - protected async setupListener() { - sdk.stream(this.eventType, [this.eventName], (async (action: 'removed' | 'changed', record: U) => { + protected setupListener() { + return sdk.stream(this.eventType, [this.eventName], (async (action: 'removed' | 'changed', record: U) => { this.log('record received', action, record); await this.handleRecordEvent(action, record); }) as (...args: unknown[]) => void); @@ -295,11 +295,7 @@ export abstract class CachedCollection { return true; } - async init() { - if (this.ready.get()) { - return; - } - + private async performInitialization() { if (await this.loadFromCache()) { this.trySync(); } else { @@ -322,7 +318,29 @@ export abstract class CachedCollection { } }); - return this.setupListener(); + this.setupListener(); + } + + private initializationPromise: Promise | undefined; + + init() { + if (this.initializationPromise) { + return this.initializationPromise; + } + + this.initializationPromise = this.performInitialization().finally(() => { + this.initializationPromise = undefined; + }); + + return this.initializationPromise; + } + + async release() { + if (this.initializationPromise) { + await this.initializationPromise; + } + + this.ready.set(false); } private reconnectionComputation: Tracker.Computation | undefined; diff --git a/apps/meteor/client/lib/settings/PrivateSettingsCachedCollection.ts b/apps/meteor/client/lib/settings/PrivateSettingsCachedCollection.ts index 74cb76ac9002a..95486509875fa 100644 --- a/apps/meteor/client/lib/settings/PrivateSettingsCachedCollection.ts +++ b/apps/meteor/client/lib/settings/PrivateSettingsCachedCollection.ts @@ -11,12 +11,16 @@ class PrivateSettingsCachedCollection extends PrivateCachedCollection }); } - async setupListener(): Promise { - sdk.stream('notify-logged', [this.eventName as 'private-settings-changed'], async (t: string, { _id, ...record }: { _id: string }) => { - this.log('record received', t, { _id, ...record }); - this.collection.update({ _id }, { $set: record }, { upsert: true }); - this.sync(); - }); + override setupListener() { + return sdk.stream( + 'notify-logged', + [this.eventName as 'private-settings-changed'], + async (t: string, { _id, ...record }: { _id: string }) => { + this.log('record received', t, { _id, ...record }); + this.collection.update({ _id }, { $set: record }, { upsert: true }); + this.sync(); + }, + ); } } From 85612cf215e8d40306c262a1954a80b765a4c52f Mon Sep 17 00:00:00 2001 From: Tasso Date: Fri, 20 Jun 2025 12:58:42 -0300 Subject: [PATCH 3/8] Unsubscribe listener --- .../client/lib/cachedCollections/CachedCollection.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/meteor/client/lib/cachedCollections/CachedCollection.ts b/apps/meteor/client/lib/cachedCollections/CachedCollection.ts index 1559a770f463f..17a74eaed3ef3 100644 --- a/apps/meteor/client/lib/cachedCollections/CachedCollection.ts +++ b/apps/meteor/client/lib/cachedCollections/CachedCollection.ts @@ -295,6 +295,8 @@ export abstract class CachedCollection { return true; } + private listenerUnsubscriber: (() => void) | undefined; + private async performInitialization() { if (await this.loadFromCache()) { this.trySync(); @@ -318,7 +320,11 @@ export abstract class CachedCollection { } }); - this.setupListener(); + const subscription = this.setupListener(); + this.listenerUnsubscriber = () => { + subscription.stop(); + this.listenerUnsubscriber = undefined; + }; } private initializationPromise: Promise | undefined; @@ -340,6 +346,7 @@ export abstract class CachedCollection { await this.initializationPromise; } + this.listenerUnsubscriber?.(); this.ready.set(false); } From 5d66747550f4a88dbdd604e9b924359eeacf1612 Mon Sep 17 00:00:00 2001 From: Tasso Date: Fri, 20 Jun 2025 13:26:50 -0300 Subject: [PATCH 4/8] Whoopsie! --- apps/meteor/client/lib/cachedCollections/CachedCollection.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/meteor/client/lib/cachedCollections/CachedCollection.ts b/apps/meteor/client/lib/cachedCollections/CachedCollection.ts index 17a74eaed3ef3..b1c3f37dc6d21 100644 --- a/apps/meteor/client/lib/cachedCollections/CachedCollection.ts +++ b/apps/meteor/client/lib/cachedCollections/CachedCollection.ts @@ -382,7 +382,7 @@ export class PrivateCachedCollection extends }); Accounts.onLogout(() => { - this.ready.set(false); + this.release(); }); } } From 38b508563e6ed68d7061a81af6231f1a376352fd Mon Sep 17 00:00:00 2001 From: Tasso Date: Fri, 20 Jun 2025 16:45:20 -0300 Subject: [PATCH 5/8] Fix invalidation order --- .../client/lib/cachedCollections/DocumentMapStore.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/meteor/client/lib/cachedCollections/DocumentMapStore.ts b/apps/meteor/client/lib/cachedCollections/DocumentMapStore.ts index 7ad258bce9cb0..ec848dd2cebe8 100644 --- a/apps/meteor/client/lib/cachedCollections/DocumentMapStore.ts +++ b/apps/meteor/client/lib/cachedCollections/DocumentMapStore.ts @@ -249,8 +249,9 @@ export const createDocumentMapStore = ({ const records = new Map(); for (const record of state.records.values()) { if (predicate(record)) { - if (onInvalidate) affected.push(record); - records.set(record._id, modifier(record)); + const newRecord = modifier(record); + records.set(record._id, newRecord); + if (onInvalidate) affected.push(newRecord); } else { records.set(record._id, record); } @@ -267,8 +268,9 @@ export const createDocumentMapStore = ({ for await (const record of get().records.values()) { if (predicate(record)) { - if (onInvalidate) affected.push(record); - records.set(record._id, await modifier(record)); + const newRecord = await modifier(record); + records.set(record._id, newRecord); + if (onInvalidate) affected.push(newRecord); } else { records.set(record._id, record); } From ef404126f7a7dc9ebe262da93975f8cac2592cc2 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Fri, 20 Jun 2025 16:46:13 -0300 Subject: [PATCH 6/8] fix: ensure proper cleanup of cached chat room and subscription states --- .../meteor/client/hooks/useLoadRoomForAllowedAnonymousRead.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/meteor/client/hooks/useLoadRoomForAllowedAnonymousRead.ts b/apps/meteor/client/hooks/useLoadRoomForAllowedAnonymousRead.ts index b53ed9dde343d..3e3b7e520b9c2 100644 --- a/apps/meteor/client/hooks/useLoadRoomForAllowedAnonymousRead.ts +++ b/apps/meteor/client/hooks/useLoadRoomForAllowedAnonymousRead.ts @@ -11,6 +11,10 @@ export const useLoadRoomForAllowedAnonymousRead = () => { if (!userId && accountsAllowAnonymousRead === true) { CachedChatRoom.init(); CachedChatSubscription.ready.set(true); + return () => { + CachedChatRoom.ready.set(false); + CachedChatSubscription.ready.set(false); + }; } }, [accountsAllowAnonymousRead, userId]); }; From 801085aaa16c80c8e5d74b462f61d935a75a55d9 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Fri, 20 Jun 2025 15:48:40 -0400 Subject: [PATCH 7/8] Create light-beans-sparkle.md --- .changeset/light-beans-sparkle.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/light-beans-sparkle.md diff --git a/.changeset/light-beans-sparkle.md b/.changeset/light-beans-sparkle.md new file mode 100644 index 0000000000000..5af347c9ab1c6 --- /dev/null +++ b/.changeset/light-beans-sparkle.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +Fixes and issue, were multiple reconnections would subscribe multiple times the same stream, only frontend issue, since the stream cache prevents from sending multiple times to the backend, but not prevent from runnning the callback multiple times From a4133b87c1bd5c993a998d4ad37741fa9d41b018 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Fri, 20 Jun 2025 16:37:34 -0400 Subject: [PATCH 8/8] Update .changeset/light-beans-sparkle.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .changeset/light-beans-sparkle.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/light-beans-sparkle.md b/.changeset/light-beans-sparkle.md index 5af347c9ab1c6..3bf34f4584491 100644 --- a/.changeset/light-beans-sparkle.md +++ b/.changeset/light-beans-sparkle.md @@ -2,4 +2,4 @@ "@rocket.chat/meteor": patch --- -Fixes and issue, were multiple reconnections would subscribe multiple times the same stream, only frontend issue, since the stream cache prevents from sending multiple times to the backend, but not prevent from runnning the callback multiple times +Fixes an issue, where multiple reconnections would subscribe multiple times to the same stream, only a frontend issue, since the stream cache prevents sending multiple times to the backend, but does not prevent running the callback multiple times