-
Notifications
You must be signed in to change notification settings - Fork 10.4k
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
refactor: Subscriptions out of DB Watcher #32540
refactor: Subscriptions out of DB Watcher #32540
Conversation
Looks like this PR is ready to merge! 🎉 |
|
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #32540 +/- ##
===========================================
- Coverage 59.43% 59.40% -0.04%
===========================================
Files 2547 2547
Lines 63265 63310 +45
Branches 14237 14248 +11
===========================================
+ Hits 37604 37611 +7
- Misses 22941 22980 +39
+ Partials 2720 2719 -1
Flags with carried forward coverage won't be shown. Click here to find out more. |
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.
not adding same comment for all, but my first look :)
- Replaced asynchronous function calls with synchronous calls followed by an if statement to check for modifiedCount before invoking the listener.
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.
there are some inline comments... I've found these broken behaviors while testing:
- when sending a message in a channel, other members' subscription were not being marked as unread.. weirdly enough, if a message has a mention to someone, it works as expected
- change a channel to a group (from public to private) was not reflected in the UI
other than that, I'd ask to not use .then()
when it is not needed, I've found it in a few different places.
apps/meteor/app/e2e/server/functions/handleSuggestedGroupKey.ts
Outdated
Show resolved
Hide resolved
apps/meteor/ee/app/livechat-enterprise/server/hooks/onCloseLivechat.ts
Outdated
Show resolved
Hide resolved
71a3a1a
to
0a012a8
Compare
…ions-model-out-of-db-watcher
…ions-model-out-of-db-watcher
…ions-model-out-of-db-watcher
…ions-model-out-of-db-watcher
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.
In some places you destructure the returned objects and in others you access them via .
, think would be nice to be consistent and stick to one way where this makes sense.
@@ -27,7 +29,10 @@ export const saveRoomEncrypted = async function (rid: string, encrypted: boolean | |||
} | |||
|
|||
if (encrypted) { | |||
await Subscriptions.disableAutoTranslateByRoomId(rid); | |||
const disableAutoTranslateResponse = await Subscriptions.disableAutoTranslateByRoomId(rid); |
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.
const disableAutoTranslateResponse = await Subscriptions.disableAutoTranslateByRoomId(rid); | |
const { modifiedCount } = await Subscriptions.disableAutoTranslateByRoomId(rid); |
|
||
// Update customFields of any user's Subscription related with this rid | ||
await Subscriptions.updateCustomFieldsByRoomId(rid, roomCustomFields); | ||
const updateCustomFields = await Subscriptions.updateCustomFieldsByRoomId(rid, roomCustomFields); |
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.
const updateCustomFields = await Subscriptions.updateCustomFieldsByRoomId(rid, roomCustomFields); | |
const { modifiedCount } = await Subscriptions.updateCustomFieldsByRoomId(rid, roomCustomFields); |
apps/meteor/app/e2e/server/functions/handleSuggestedGroupKey.ts
Outdated
Show resolved
Hide resolved
|
||
if (removedUnreadThreadsResponse.modifiedCount) { | ||
for await (const id of subscriptionIds) { | ||
await notifyOnSubscriptionChangedById(id); |
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.
Most of other calls are void
promises, is there a reason to await for them here?
|
||
if (Object.keys(insertedIds).length) { | ||
for await (const insertedId of Object.values(insertedIds)) { | ||
await notifyOnSubscriptionChangedById(insertedId, 'inserted'); |
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.
Same, any reason for await this one?
|
||
void notifyOnRoomChangedById(rid, 'removed'); | ||
(await Rooms.removeById(rid)).deletedCount && void notifyOnRoomChangedById(rid, 'removed'); |
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.
Other places are using the if (deletedCount)
, think we should keep the same standard here.
Messages.removeByRoomIds(rids), | ||
ReadReceipts.removeByRoomIds(rids), | ||
Rooms.removeByIds(rids), | ||
// no bulk deletion for files | ||
...rids.map((rid) => FileUpload.removeFilesByRoomId(rid)), |
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.
IMHO, this change is not related to the watcher changes and should be in its own PR
): Promise<void> => { | ||
const subscriptions = Subscriptions.findByUserIdAndRoomIds(uid, [rid], { projection: subscriptionFields }); | ||
|
||
for await (const subscription of subscriptions) { |
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.
for await (const subscription of subscriptions) { | |
for (const subscription of subscriptions) { |
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.
this is because of the AsyncIterator.. but in fact, we don't need to use it
projection: subscriptionFields, | ||
}); | ||
|
||
for await (const subscription of subscriptions) { |
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.
for await (const subscription of subscriptions) { | |
for (const subscription of subscriptions) { |
…ions-model-out-of-db-watcher
…ions-model-out-of-db-watcher
const subscriptionsLeft = await Subscriptions.countByRoomId(roomId); | ||
if (subscriptionsLeft) { | ||
await Subscriptions.removeByRoomId(roomId); | ||
const { deletedCount } = await Subscriptions.removeByRoomId(roomId, { |
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.
Thanks man!
As per the updates mentioned in PROJ-7, SCA-13 and ADR #74, this pull request focuses on relocating
Subscriptions
model out of DB Watcher service.Context
This modification enhances RocketChat's app by allowing it to directly call listeners through the
api.broadcast
global function, bypassing the need for MongoDB Change Stream data propagation.This change offers better control over user notifications via Web Sockets, enabling more precise management of use-cases. Instead of notifying every database change, we can now send an
api.broadcast
call only when necessary, reducing overall network messages. Additionally, this contributes to the future removal of the DB Watcher deployment, optimizing resource utilization.Proposed changes
Key changes include:
dbWatchersDisabled
flag.watch.subscriptions
listener event, subject to thedbWatchersDisabled
flag.Updated Use Cases
Steps to test or reproduce
DISABLE_DB_WATCHERS
environment variable set totrue
.Further comments
To maintain consistency and avoid potential regressions, event names and signatures have been kept unchanged on both the client and app sides. This decision streamlines efforts and mitigates the risk of unintended consequences.