Skip to content

fix(ddp): populate reaction user names when UI_Use_Real_Name is enabled#40254

Open
divyanshu-patil wants to merge 11 commits intoRocketChat:developfrom
divyanshu-patil:fix/reaction-names
Open

fix(ddp): populate reaction user names when UI_Use_Real_Name is enabled#40254
divyanshu-patil wants to merge 11 commits intoRocketChat:developfrom
divyanshu-patil:fix/reaction-names

Conversation

@divyanshu-patil
Copy link
Copy Markdown
Contributor

@divyanshu-patil divyanshu-patil commented Apr 22, 2026

Proposed changes (including videos or screenshots)

When UI_Use_Real_Name is enabled, the getMessageToBroadcast function was already enriching the message sender's name and mentioned users' names before broadcasting. However, it was not doing the same for reaction user names — only usernames were present in the broadcasted payload, leaving names empty.

This PR adds a loop inside getMessageToBroadcast that iterates over all reactions in a message and populates reaction.names[i] by calling the memoized getUserNameByUsernameCached lookup for each username in reaction.usernames. This mirrors the existing pattern used for mentions.

Issue(s)

N/A (discovered during mobile testing)

Linked PR

RocketChat/Rocket.Chat.ReactNative#7204

Screenshots

Before

Screenshot 2026-04-22 at 8 05 11 PM

After (UI_Use_Real_Name is true)

Screenshot 2026-04-22 at 8 06 52 PM

Steps to test or reproduce

  1. Enable UI_Use_Real_Name in Admin → General settings
  2. Open the mobile app
  3. Navigate to any room with messages that have reactions
  4. Long-press a reaction on any message to open the "Reactions" bottom sheet
  5. Tap any emoji tab

Before: user names in each tab are blank
After: user real names are correctly displayed under each emoji tab

Further comments

The fix follows the same memoized lookup pattern already used for message.u and message.mentions in getMessageToBroadcast. A new cached helper getUserNameByUsernameCached (keyed by username rather than user ID) is introduced alongside the existing getUserNameCached to avoid redundant DB calls when multiple users react with the same emoji. The maxAge is kept consistent at 10 seconds.

Summary by CodeRabbit

  • Bug Fixes
    • Real names now appear correctly in message reactions when "Use Real Name" is enabled. Reaction entries display corresponding real names (or remain blank when unavailable), matching how user and mention names are shown.

@dionisio-bot
Copy link
Copy Markdown
Contributor

dionisio-bot Bot commented Apr 22, 2026

Looks like this PR is not ready to merge, because of the following issues:

  • This PR is missing the 'stat: QA assured' label
  • This PR is missing the required milestone or project

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 22, 2026

⚠️ No Changeset found

Latest commit: 220c2ba

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 22, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

getMessageToBroadcast now resolves real names for users in message.reactions when UI_Use_Real_Name is enabled: it collects unique reaction usernames, performs a single Users lookup, builds a username→display-name map, and fills each reaction's names array accordingly.

Changes

Cohort / File(s) Summary
Reaction Real Names Processing
apps/meteor/app/lib/server/lib/notifyListener.ts
Added logic to aggregate unique usernames from message.reactions, perform a bulk Users.findByUsernames lookup, create a username→display-name mapping, and populate each reaction object's names array (defaults to empty string for missing users).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Suggested labels

type: bug

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: populating reaction user names when UI_Use_Real_Name is enabled, which matches the core functionality added in the PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/meteor/app/lib/server/lib/notifyListener.ts`:
- Around line 479-489: The loop currently skips reactions that have
reaction.usernames but no reaction.names, leaving legacy/imported reactions
without populated display names; update the logic in the notify listener where
reactions are enriched (the block using "for (const [, reaction] of
Object.entries(message.reactions))" and calling getUserNameByUsernameCached) to
initialize reaction.names when missing (e.g., seed it from reaction.usernames or
create an array of the same length) before the inner index loop, then continue
to call getUserNameByUsernameCached(username) and overwrite each index with the
resolved real name when available.

In `@apps/meteor/app/reactions/server/setReaction.ts`:
- Around line 80-84: When initializing a missing names array in setReaction, pad
it to match the current usernames length so indices stay aligned: if
message.reactions[reaction].names is falsy, set it to
Array(message.reactions[reaction].usernames.length).fill('') before appending
the new username and its placeholder; then push the new username to
message.reactions[reaction].usernames and push an empty string to
message.reactions[reaction].names so both arrays remain the same length and
index-aligned.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cea5aa94-e568-4acb-bf87-494801cf9202

📥 Commits

Reviewing files that changed from the base of the PR and between 6cd73b0 and 2ff4a59.

📒 Files selected for processing (2)
  • apps/meteor/app/lib/server/lib/notifyListener.ts
  • apps/meteor/app/reactions/server/setReaction.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
  • apps/meteor/app/reactions/server/setReaction.ts
🧠 Learnings (8)
📚 Learning: 2026-03-11T22:04:20.529Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 39545
File: apps/meteor/client/views/room/body/hooks/useHasNewMessages.ts:59-61
Timestamp: 2026-03-11T22:04:20.529Z
Learning: In `apps/meteor/client/views/room/body/hooks/useHasNewMessages.ts`, the `msg.u._id === uid` early-return in the `streamNewMessage` handler is intentional: the "New messages" indicator is designed to notify about messages from other users only. Self-sent messages — including those sent from a different session/device — are always skipped, by design. Do not flag this as a multi-session regression.

Applied to files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
📚 Learning: 2026-03-09T18:39:21.178Z
Learnt from: Harxhit
Repo: RocketChat/Rocket.Chat PR: 39476
File: apps/meteor/server/methods/addAllUserToRoom.ts:0-0
Timestamp: 2026-03-09T18:39:21.178Z
Learning: In apps/meteor/server/methods/addAllUserToRoom.ts, the implementation uses a single cursor pass (Users.find(userFilter).batchSize(100)) that collects both the full user objects (collectedUsers: IUser[]) and their usernames (usernames: string[]) in one iteration. `beforeAddUserToRoom` is then called once with the full usernames batch (preserving batch-validation semantics), and the subsequent subscription/message processing loop iterates over the same stable `collectedUsers` array — no second DB query is made. This avoids any race condition between validation and processing while preserving the original batch-validation behavior.

Applied to files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
  • apps/meteor/app/reactions/server/setReaction.ts
📚 Learning: 2026-01-17T01:51:47.764Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 38219
File: packages/core-typings/src/cloud/Announcement.ts:5-6
Timestamp: 2026-01-17T01:51:47.764Z
Learning: In packages/core-typings/src/cloud/Announcement.ts, the AnnouncementSchema.createdBy field intentionally overrides IBannerSchema.createdBy (object with _id and optional username) with a string enum ['cloud', 'system'] to match existing runtime behavior. This is documented as technical debt with a FIXME comment at apps/meteor/app/cloud/server/functions/syncWorkspace/handleCommsSync.ts:53 and should not be flagged as an error until the runtime behavior is corrected.

Applied to files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
📚 Learning: 2026-01-19T18:17:46.433Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38262
File: apps/meteor/client/lib/utils/normalizeMessagePreview/getMessagePreview.ts:24-33
Timestamp: 2026-01-19T18:17:46.433Z
Learning: In the Rocket.Chat repository, usernames (lastMessage.u.username) and display names (lastMessage.u.name) are sanitized/escaped centrally elsewhere in the system, so individual display functions like getMessagePreview do not need to escape these values before interpolating them into strings.

Applied to files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In the Rocket.Chat repository, do not reference Biome lint rules in code review feedback. Biome is not used even if biome.json exists; only reference Biome rules if there is explicit, project-wide usage documented. For TypeScript files, review lint implications without Biome guidance unless the project enables Biome rules.

Applied to files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
  • apps/meteor/app/reactions/server/setReaction.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In this repository (RocketChat/Rocket.Chat), Biome lint rules are not used even if a biome.json exists. When reviewing TypeScript files (e.g., packages/ui-voip/src/providers/useMediaSession.ts), ensure lint suggestions do not reference Biome-specific rules. Rely on general ESLint/TypeScript lint rules and project conventions instead.

Applied to files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
  • apps/meteor/app/reactions/server/setReaction.ts
📚 Learning: 2026-03-20T13:51:23.302Z
Learnt from: ggazzo
Repo: RocketChat/Rocket.Chat PR: 39553
File: apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts:179-181
Timestamp: 2026-03-20T13:51:23.302Z
Learning: In `apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts`, the truthiness guards `...(integration.avatar && { avatar })`, `...(integration.emoji && { emoji })`, `...(integration.alias && { alias })`, and `...(integration.script && { script })` in the `$set` payload of `updateIncomingIntegration` are intentional. Empty-string values for these fields should NOT overwrite the stored value — only truthy values are persisted. Do not flag these as bugs preventing explicit clears.

Applied to files:

  • apps/meteor/app/reactions/server/setReaction.ts
📚 Learning: 2026-04-18T12:32:53.425Z
Learnt from: rodrigok
Repo: RocketChat/Rocket.Chat PR: 38623
File: apps/meteor/app/lib/server/functions/cleanRoomHistory.ts:146-149
Timestamp: 2026-04-18T12:32:53.425Z
Learning: In `apps/meteor/app/lib/server/functions/cleanRoomHistory.ts` (PR `#38623`), the read-receipt cleanup (both `ReadReceipts.removeByMessageIds` and `ReadReceiptsArchive.removeByMessageIds`) is intentionally only performed in the limited prune path (`limit && selectedMessageIds`). The unlimited/delete-all path (`limit === 0`) deliberately skips cleaning up orphaned read receipts in both hot and cold storage — this is by design. Do not flag this as a bug or missing cleanup in future reviews.

Applied to files:

  • apps/meteor/app/reactions/server/setReaction.ts
🔇 Additional comments (2)
apps/meteor/app/lib/server/lib/notifyListener.ts (1)

432-438: LGTM: cached username lookup is scoped and consistent.

The helper mirrors the existing user-id lookup and only projects name, which keeps repeated reaction enrichment cheap.

apps/meteor/app/reactions/server/setReaction.ts (1)

27-28: LGTM: removal keeps normalized arrays aligned.

Splicing names at the same index as usernames preserves the parallel array contract for reactions that already have names.

Comment thread apps/meteor/app/lib/server/lib/notifyListener.ts
Comment thread apps/meteor/app/reactions/server/setReaction.ts Outdated
@divyanshu-patil divyanshu-patil changed the title fix(mobile): populate reaction user names when UI_Use_Real_Name is enabled fix(ddp): populate reaction user names when UI_Use_Real_Name is enabled Apr 22, 2026
@coderabbitai coderabbitai Bot removed the type: bug label Apr 22, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/meteor/app/reactions/server/setReaction.ts (1)

80-87: Drop the inline implementation comment.

The padding logic is clear from the code, and Line 84 adds an implementation comment against the repository guideline. As per coding guidelines, "Avoid code comments in the implementation".

♻️ Proposed cleanup
-
-		// Pad to match current usernames length before appending
 		while (message.reactions[reaction].names.length < message.reactions[reaction].usernames.length) {
 			message.reactions[reaction].names.push('');
 		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/app/reactions/server/setReaction.ts` around lines 80 - 87, Remove
the inline implementation comment "// Pad to match current usernames length
before appending" and keep the existing padding logic intact that ensures
message.reactions[reaction].names is initialized and while its length is less
than message.reactions[reaction].usernames.length push(''); leave the variable
checks and loop (the code inside setReaction handling
message.reactions[reaction].names and usernames) as-is but delete that
single-line comment to comply with the "avoid code comments in the
implementation" guideline.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/meteor/app/reactions/server/setReaction.ts`:
- Around line 89-93: In setReaction.ts the code for appending a user's reaction
is duplicated: message.reactions[reaction].usernames.push(user.username as
string) and message.reactions[reaction].names.push('') are called twice, causing
duplicate entries; remove the second pair so you only push the username and
placeholder name once when adding a reaction (i.e., keep a single push to
message.reactions[reaction].usernames and a single push to
message.reactions[reaction].names in the add-reaction branch).

---

Nitpick comments:
In `@apps/meteor/app/reactions/server/setReaction.ts`:
- Around line 80-87: Remove the inline implementation comment "// Pad to match
current usernames length before appending" and keep the existing padding logic
intact that ensures message.reactions[reaction].names is initialized and while
its length is less than message.reactions[reaction].usernames.length push('');
leave the variable checks and loop (the code inside setReaction handling
message.reactions[reaction].names and usernames) as-is but delete that
single-line comment to comply with the "avoid code comments in the
implementation" guideline.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ceddb9b5-657d-4174-8c15-ea5978a637b6

📥 Commits

Reviewing files that changed from the base of the PR and between 2ff4a59 and 2440593.

📒 Files selected for processing (2)
  • apps/meteor/app/lib/server/lib/notifyListener.ts
  • apps/meteor/app/reactions/server/setReaction.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/meteor/app/lib/server/lib/notifyListener.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/app/reactions/server/setReaction.ts
🧠 Learnings (6)
📓 Common learnings
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38262
File: apps/meteor/client/lib/utils/normalizeMessagePreview/getMessagePreview.ts:24-33
Timestamp: 2026-01-19T18:17:46.433Z
Learning: In the Rocket.Chat repository, usernames (lastMessage.u.username) and display names (lastMessage.u.name) are sanitized/escaped centrally elsewhere in the system, so individual display functions like getMessagePreview do not need to escape these values before interpolating them into strings.
📚 Learning: 2026-04-18T12:32:53.425Z
Learnt from: rodrigok
Repo: RocketChat/Rocket.Chat PR: 38623
File: apps/meteor/app/lib/server/functions/cleanRoomHistory.ts:146-149
Timestamp: 2026-04-18T12:32:53.425Z
Learning: In `apps/meteor/app/lib/server/functions/cleanRoomHistory.ts` (PR `#38623`), the read-receipt cleanup (both `ReadReceipts.removeByMessageIds` and `ReadReceiptsArchive.removeByMessageIds`) is intentionally only performed in the limited prune path (`limit && selectedMessageIds`). The unlimited/delete-all path (`limit === 0`) deliberately skips cleaning up orphaned read receipts in both hot and cold storage — this is by design. Do not flag this as a bug or missing cleanup in future reviews.

Applied to files:

  • apps/meteor/app/reactions/server/setReaction.ts
📚 Learning: 2026-03-20T13:51:23.302Z
Learnt from: ggazzo
Repo: RocketChat/Rocket.Chat PR: 39553
File: apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts:179-181
Timestamp: 2026-03-20T13:51:23.302Z
Learning: In `apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts`, the truthiness guards `...(integration.avatar && { avatar })`, `...(integration.emoji && { emoji })`, `...(integration.alias && { alias })`, and `...(integration.script && { script })` in the `$set` payload of `updateIncomingIntegration` are intentional. Empty-string values for these fields should NOT overwrite the stored value — only truthy values are persisted. Do not flag these as bugs preventing explicit clears.

Applied to files:

  • apps/meteor/app/reactions/server/setReaction.ts
📚 Learning: 2026-03-09T18:39:21.178Z
Learnt from: Harxhit
Repo: RocketChat/Rocket.Chat PR: 39476
File: apps/meteor/server/methods/addAllUserToRoom.ts:0-0
Timestamp: 2026-03-09T18:39:21.178Z
Learning: In apps/meteor/server/methods/addAllUserToRoom.ts, the implementation uses a single cursor pass (Users.find(userFilter).batchSize(100)) that collects both the full user objects (collectedUsers: IUser[]) and their usernames (usernames: string[]) in one iteration. `beforeAddUserToRoom` is then called once with the full usernames batch (preserving batch-validation semantics), and the subsequent subscription/message processing loop iterates over the same stable `collectedUsers` array — no second DB query is made. This avoids any race condition between validation and processing while preserving the original batch-validation behavior.

Applied to files:

  • apps/meteor/app/reactions/server/setReaction.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In the Rocket.Chat repository, do not reference Biome lint rules in code review feedback. Biome is not used even if biome.json exists; only reference Biome rules if there is explicit, project-wide usage documented. For TypeScript files, review lint implications without Biome guidance unless the project enables Biome rules.

Applied to files:

  • apps/meteor/app/reactions/server/setReaction.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In this repository (RocketChat/Rocket.Chat), Biome lint rules are not used even if a biome.json exists. When reviewing TypeScript files (e.g., packages/ui-voip/src/providers/useMediaSession.ts), ensure lint suggestions do not reference Biome-specific rules. Rely on general ESLint/TypeScript lint rules and project conventions instead.

Applied to files:

  • apps/meteor/app/reactions/server/setReaction.ts
🔇 Additional comments (2)
apps/meteor/app/reactions/server/setReaction.ts (2)

27-28: LGTM — removal keeps reaction arrays aligned.

Line 28 correctly removes the matching names entry at the same index as usernames.


74-78: LGTM — new reactions now initialize names.

This keeps the stored reaction shape ready for the broadcast real-name population path.

Comment thread apps/meteor/app/reactions/server/setReaction.ts Outdated
@coderabbitai coderabbitai Bot removed the type: bug label Apr 23, 2026
@divyanshu-patil
Copy link
Copy Markdown
Contributor Author

divyanshu-patil commented Apr 23, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 23, 2026

🧩 Analysis chain

I'll pull the relevant code before writing up my review.


🏁 Script executed:

#!/bin/bash
# Get the diff for this PR
gh pr diff 40254 --repo RocketChat/Rocket.Chat

echo "---FILE CONTENT---"
# Get the full notifyListener.ts file
cat apps/meteor/app/lib/server/lib/notifyListener.ts

Length of output: 21099


PR Description Images:

  • Image 1 (before): Shows the emoji reactions modal with tabs (All, 😊 2, 😔 1, 🏑 1) and a completely blank content area — the bug being fixed.
  • Image 2 (after): Shows the same modal with the :slight_smile: section header and two users ("Divyanshu Patil", "divyanshuuu") correctly listed — confirming the fix works.

@divyanshu-patil Here is my review of PR #40254.


Review: fix(ddp): populate reaction user names when UI_Use_Real_Name is enabled

✅ What's done well

  • Efficient batching: All unique usernames are collected into a Set first, then resolved with a single Users.findByUsernames(...) call and a Map lookup — much better than one DB hit per username.
  • Correct placement: The logic lives entirely inside the useRealName guard, consistent with the existing handling for message.u and message.mentions.
  • Minimal mutation footprint: Only reaction.names is written; nothing else is touched.

🔶 Issues

1. Unnecessary DB call when all reactions are empty (medium)

If message.reactions exists but every reaction has an empty usernames array, allUsernames will be an empty Set and findByUsernames([]) is still executed. This is a wasted round-trip.

if (message.reactions) {
    const allUsernames = new Set<string>();
    Object.values(message.reactions).forEach((reaction) => {
        reaction.usernames?.forEach((username) => allUsernames.add(username));
    });

+   if (!allUsernames.size) {
+       // nothing to resolve
+   } else {
        const users = await Users.findByUsernames([...allUsernames], {
            projection: { username: 1, name: 1 },
        }).toArray();

        const nameByUsername = new Map(users.map((u) => [u.username, u.name]));

        for (const [, reaction] of Object.entries(message.reactions)) {
            if (!reaction.usernames?.length) continue;
            reaction.names = reaction.usernames.map((username) => nameByUsername.get(username) ?? '');
        }
+   }
}

2. Use ?? instead of || for the empty-string fallback (minor)

|| '' will incorrectly substitute '' even if nameByUsername.get(username) returns 0 or any other falsy value (unlikely for a name, but semantically imprecise). The nullish coalescing operator is the right tool here:

- reaction.names = reaction.usernames.map((username) => nameByUsername.get(username) || '');
+ reaction.names = reaction.usernames.map((username) => nameByUsername.get(username) ?? '');

3. Double traversal of message.reactions (minor)

The current code walks message.reactions twice — once with Object.values to build the Set, then again with Object.entries to write names. These can be merged into a single pass, simplifying the logic:

if (message.reactions) {
    const allUsernames = new Set<string>();
    for (const reaction of Object.values(message.reactions)) {
        reaction.usernames?.forEach((username) => allUsernames.add(username));
    }

    if (allUsernames.size) {
        const users = await Users.findByUsernames([...allUsernames], {
            projection: { username: 1, name: 1 },
        }).toArray();

        const nameByUsername = new Map(users.map((u) => [u.username, u.name]));

        for (const reaction of Object.values(message.reactions)) {
            if (!reaction.usernames?.length) continue;
            reaction.names = reaction.usernames.map((username) => nameByUsername.get(username) ?? '');
        }
    }
}

4. Missing unit tests (medium)

There are no tests covering the new reaction-name population path. At minimum, a test for getMessageToBroadcast should assert:

  • When UI_Use_Real_Name is true and message.reactions contains entries with usernames, reaction.names is populated with the corresponding real names.
  • When a username has no matching user document, the slot is ''.
  • When UI_Use_Real_Name is false, reaction.names is not touched.

5. PR description mentions a non-existent getUserNameByUsernameCached helper (minor)

"A new cached helper getUserNameByUsernameCached (keyed by username, maxAge 10s) is introduced…"

The actual implementation does not introduce this memoized helper. Instead it uses a direct batch query. The batch approach is correct and arguably better here (one query regardless of how many emojis exist), but the description should be updated to reflect what was actually implemented, to avoid confusion for reviewers and future readers.


Summary

# Severity Item
1 🔶 Medium Guard against findByUsernames([]) when all reactions are empty
2 🔹 Minor `
3 🔹 Minor Two traversals of message.reactions can be one
4 🔶 Medium No unit tests for the new logic
5 🔹 Minor PR description references a helper that doesn't exist in the diff

The core approach is sound. Addressing items 1 and 4 before merge would be ideal.


🧠 Learnings used
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38262
File: apps/meteor/client/lib/utils/normalizeMessagePreview/getMessagePreview.ts:24-33
Timestamp: 2026-01-19T18:17:46.433Z
Learning: In the Rocket.Chat repository, usernames (lastMessage.u.username) and display names (lastMessage.u.name) are sanitized/escaped centrally elsewhere in the system, so individual display functions like getMessagePreview do not need to escape these values before interpolating them into strings.
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/meteor/app/lib/server/lib/notifyListener.ts (1)

478-488: Consider falling back to username instead of empty string.

When a reacting user has no name set (or the user record is missing — e.g., deleted account), nameByUsername.get(username) || '' yields '', which will render as a blank entry in the Reactions sheet (the very symptom this PR fixes). Falling back to username preserves a meaningful label and matches the prior behavior before UI_Use_Real_Name enrichment.

Also worth noting: an empty allUsernames set (all reactions have empty usernames arrays — unlikely but possible) will still issue a findByUsernames([]) query; a quick if (!allUsernames.size) { ... skip block } avoids it.

♻️ Proposed fix
-			const users = await Users.findByUsernames([...allUsernames], {
-				projection: { username: 1, name: 1 },
-			}).toArray();
-
-			const nameByUsername = new Map(users.map((u) => [u.username, u.name]));
-
-			for (const [, reaction] of Object.entries(message.reactions)) {
-				if (!reaction.usernames?.length) {
-					continue;
-				}
-				reaction.names = reaction.usernames.map((username) => nameByUsername.get(username) || '');
-			}
+			if (allUsernames.size) {
+				const users = await Users.findByUsernames([...allUsernames], {
+					projection: { username: 1, name: 1 },
+				}).toArray();
+
+				const nameByUsername = new Map(users.map((u) => [u.username, u.name]));
+
+				for (const [, reaction] of Object.entries(message.reactions)) {
+					if (!reaction.usernames?.length) {
+						continue;
+					}
+					reaction.names = reaction.usernames.map((username) => nameByUsername.get(username) || username);
+				}
+			}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/app/lib/server/lib/notifyListener.ts` around lines 478 - 488, The
reactions rendering code currently maps reaction.usernames to names using
nameByUsername.get(username) || '' which yields empty strings when a real name
is missing; change it to fall back to the username (e.g.,
nameByUsername.get(username) || username) inside the loop that assigns
reaction.names, and guard the Users.findByUsernames call by skipping the DB
query when the collected allUsernames set is empty (if (!allUsernames.size)
return/continue) so you don't call findByUsernames([]); update references around
Users.findByUsernames, the nameByUsername Map, and the for (const [, reaction]
of Object.entries(message.reactions)) block accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/meteor/app/lib/server/lib/notifyListener.ts`:
- Line 472: Remove the implementation comment "// Collect all unique usernames
across all reactions" from apps/meteor/app/lib/server/lib/notifyListener.ts;
locate the comment inside the notification/reactions processing block (look for
variables like reactions or uniqueUsernames within the notify listener function)
and delete that line so the code remains self-explanatory and follows the
guideline to avoid implementation comments.

---

Nitpick comments:
In `@apps/meteor/app/lib/server/lib/notifyListener.ts`:
- Around line 478-488: The reactions rendering code currently maps
reaction.usernames to names using nameByUsername.get(username) || '' which
yields empty strings when a real name is missing; change it to fall back to the
username (e.g., nameByUsername.get(username) || username) inside the loop that
assigns reaction.names, and guard the Users.findByUsernames call by skipping the
DB query when the collected allUsernames set is empty (if (!allUsernames.size)
return/continue) so you don't call findByUsernames([]); update references around
Users.findByUsernames, the nameByUsername Map, and the for (const [, reaction]
of Object.entries(message.reactions)) block accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 314c3473-5580-4e06-bbf3-8c3a8e58f0bf

📥 Commits

Reviewing files that changed from the base of the PR and between fa5330d and c251783.

📒 Files selected for processing (1)
  • apps/meteor/app/lib/server/lib/notifyListener.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
🧠 Learnings (9)
📓 Common learnings
Learnt from: smirk-dev
Repo: RocketChat/Rocket.Chat PR: 39625
File: apps/meteor/app/api/server/v1/push.ts:85-97
Timestamp: 2026-03-14T14:58:58.834Z
Learning: In RocketChat/Rocket.Chat, the `push.token` POST/DELETE endpoints in `apps/meteor/app/api/server/v1/push.ts` were already migrated to the chained router API pattern on `develop` prior to PR `#39625`. `cleanTokenResult` (which strips `authToken` and returns `PushTokenResult`) and `isPushTokenPOSTProps`/`isPushTokenDELETEProps` validators already exist on `develop`. PR `#39625` only migrates `push.get` and `push.info` to the chained pattern. Do not flag `cleanTokenResult` or `PushTokenResult` as newly introduced behavior-breaking changes when reviewing this PR.
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38262
File: apps/meteor/client/lib/utils/normalizeMessagePreview/getMessagePreview.ts:24-33
Timestamp: 2026-01-19T18:17:46.433Z
Learning: In the Rocket.Chat repository, usernames (lastMessage.u.username) and display names (lastMessage.u.name) are sanitized/escaped centrally elsewhere in the system, so individual display functions like getMessagePreview do not need to escape these values before interpolating them into strings.
📚 Learning: 2026-03-11T22:04:20.529Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 39545
File: apps/meteor/client/views/room/body/hooks/useHasNewMessages.ts:59-61
Timestamp: 2026-03-11T22:04:20.529Z
Learning: In `apps/meteor/client/views/room/body/hooks/useHasNewMessages.ts`, the `msg.u._id === uid` early-return in the `streamNewMessage` handler is intentional: the "New messages" indicator is designed to notify about messages from other users only. Self-sent messages — including those sent from a different session/device — are always skipped, by design. Do not flag this as a multi-session regression.

Applied to files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
📚 Learning: 2026-03-09T18:39:21.178Z
Learnt from: Harxhit
Repo: RocketChat/Rocket.Chat PR: 39476
File: apps/meteor/server/methods/addAllUserToRoom.ts:0-0
Timestamp: 2026-03-09T18:39:21.178Z
Learning: In apps/meteor/server/methods/addAllUserToRoom.ts, the implementation uses a single cursor pass (Users.find(userFilter).batchSize(100)) that collects both the full user objects (collectedUsers: IUser[]) and their usernames (usernames: string[]) in one iteration. `beforeAddUserToRoom` is then called once with the full usernames batch (preserving batch-validation semantics), and the subsequent subscription/message processing loop iterates over the same stable `collectedUsers` array — no second DB query is made. This avoids any race condition between validation and processing while preserving the original batch-validation behavior.

Applied to files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
📚 Learning: 2026-01-19T18:17:46.433Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38262
File: apps/meteor/client/lib/utils/normalizeMessagePreview/getMessagePreview.ts:24-33
Timestamp: 2026-01-19T18:17:46.433Z
Learning: In the Rocket.Chat repository, usernames (lastMessage.u.username) and display names (lastMessage.u.name) are sanitized/escaped centrally elsewhere in the system, so individual display functions like getMessagePreview do not need to escape these values before interpolating them into strings.

Applied to files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
📚 Learning: 2026-04-18T12:32:53.425Z
Learnt from: rodrigok
Repo: RocketChat/Rocket.Chat PR: 38623
File: apps/meteor/app/lib/server/functions/cleanRoomHistory.ts:146-149
Timestamp: 2026-04-18T12:32:53.425Z
Learning: In `apps/meteor/app/lib/server/functions/cleanRoomHistory.ts` (PR `#38623`), the read-receipt cleanup (both `ReadReceipts.removeByMessageIds` and `ReadReceiptsArchive.removeByMessageIds`) is intentionally only performed in the limited prune path (`limit && selectedMessageIds`). The unlimited/delete-all path (`limit === 0`) deliberately skips cleaning up orphaned read receipts in both hot and cold storage — this is by design. Do not flag this as a bug or missing cleanup in future reviews.

Applied to files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
📚 Learning: 2026-01-17T01:51:47.764Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 38219
File: packages/core-typings/src/cloud/Announcement.ts:5-6
Timestamp: 2026-01-17T01:51:47.764Z
Learning: In packages/core-typings/src/cloud/Announcement.ts, the AnnouncementSchema.createdBy field intentionally overrides IBannerSchema.createdBy (object with _id and optional username) with a string enum ['cloud', 'system'] to match existing runtime behavior. This is documented as technical debt with a FIXME comment at apps/meteor/app/cloud/server/functions/syncWorkspace/handleCommsSync.ts:53 and should not be flagged as an error until the runtime behavior is corrected.

Applied to files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
📚 Learning: 2026-03-20T13:51:23.302Z
Learnt from: ggazzo
Repo: RocketChat/Rocket.Chat PR: 39553
File: apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts:179-181
Timestamp: 2026-03-20T13:51:23.302Z
Learning: In `apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts`, the truthiness guards `...(integration.avatar && { avatar })`, `...(integration.emoji && { emoji })`, `...(integration.alias && { alias })`, and `...(integration.script && { script })` in the `$set` payload of `updateIncomingIntegration` are intentional. Empty-string values for these fields should NOT overwrite the stored value — only truthy values are persisted. Do not flag these as bugs preventing explicit clears.

Applied to files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In the Rocket.Chat repository, do not reference Biome lint rules in code review feedback. Biome is not used even if biome.json exists; only reference Biome rules if there is explicit, project-wide usage documented. For TypeScript files, review lint implications without Biome guidance unless the project enables Biome rules.

Applied to files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In this repository (RocketChat/Rocket.Chat), Biome lint rules are not used even if a biome.json exists. When reviewing TypeScript files (e.g., packages/ui-voip/src/providers/useMediaSession.ts), ensure lint suggestions do not reference Biome-specific rules. Rely on general ESLint/TypeScript lint rules and project conventions instead.

Applied to files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
🔇 Additional comments (1)
apps/meteor/app/lib/server/lib/notifyListener.ts (1)

471-490: Summary description is out of sync with the implementation.

The PR summary describes a new memoized helper getUserNameByUsernameCached (maxAge 10s) alongside getUserNameCached. The actual implementation takes a better approach: one batched Users.findByUsernames per message rather than per-username cached lookups. The implementation is preferable — please update the PR description (and any mobile-PR linkage notes) so reviewers/backporters aren't misled.

Comment thread apps/meteor/app/lib/server/lib/notifyListener.ts Outdated
@coderabbitai coderabbitai Bot removed the type: bug label Apr 23, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/meteor/app/lib/server/lib/notifyListener.ts`:
- Around line 471-490: Collecting usernames into allUsernames and then calling
Users.findByUsernames when the set is empty causes an unnecessary DB query;
before invoking Users.findByUsernames([...allUsernames], ...) inside the
message.reactions handling, guard on allUsernames.size (or length of the spread
array) and skip the DB call and mapping if it's zero, ensuring you still iterate
reactions to set reaction.names (to empty arrays) as needed; update the logic
around Users.findByUsernames, nameByUsername, and reaction.names to only perform
the DB round-trip when there are usernames to look up.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: dd9db920-b815-49c0-a4bb-e7cdd8fa1199

📥 Commits

Reviewing files that changed from the base of the PR and between fa5330d and c251783.

📒 Files selected for processing (1)
  • apps/meteor/app/lib/server/lib/notifyListener.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
🧠 Learnings (11)
📓 Common learnings
Learnt from: smirk-dev
Repo: RocketChat/Rocket.Chat PR: 39625
File: apps/meteor/app/api/server/v1/push.ts:85-97
Timestamp: 2026-03-14T14:58:58.834Z
Learning: In RocketChat/Rocket.Chat, the `push.token` POST/DELETE endpoints in `apps/meteor/app/api/server/v1/push.ts` were already migrated to the chained router API pattern on `develop` prior to PR `#39625`. `cleanTokenResult` (which strips `authToken` and returns `PushTokenResult`) and `isPushTokenPOSTProps`/`isPushTokenDELETEProps` validators already exist on `develop`. PR `#39625` only migrates `push.get` and `push.info` to the chained pattern. Do not flag `cleanTokenResult` or `PushTokenResult` as newly introduced behavior-breaking changes when reviewing this PR.
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38262
File: apps/meteor/client/lib/utils/normalizeMessagePreview/getMessagePreview.ts:24-33
Timestamp: 2026-01-19T18:17:46.433Z
Learning: In the Rocket.Chat repository, usernames (lastMessage.u.username) and display names (lastMessage.u.name) are sanitized/escaped centrally elsewhere in the system, so individual display functions like getMessagePreview do not need to escape these values before interpolating them into strings.
📚 Learning: 2026-03-11T22:04:20.529Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 39545
File: apps/meteor/client/views/room/body/hooks/useHasNewMessages.ts:59-61
Timestamp: 2026-03-11T22:04:20.529Z
Learning: In `apps/meteor/client/views/room/body/hooks/useHasNewMessages.ts`, the `msg.u._id === uid` early-return in the `streamNewMessage` handler is intentional: the "New messages" indicator is designed to notify about messages from other users only. Self-sent messages — including those sent from a different session/device — are always skipped, by design. Do not flag this as a multi-session regression.

Applied to files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
📚 Learning: 2026-01-17T01:51:47.764Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 38219
File: packages/core-typings/src/cloud/Announcement.ts:5-6
Timestamp: 2026-01-17T01:51:47.764Z
Learning: In packages/core-typings/src/cloud/Announcement.ts, the AnnouncementSchema.createdBy field intentionally overrides IBannerSchema.createdBy (object with _id and optional username) with a string enum ['cloud', 'system'] to match existing runtime behavior. This is documented as technical debt with a FIXME comment at apps/meteor/app/cloud/server/functions/syncWorkspace/handleCommsSync.ts:53 and should not be flagged as an error until the runtime behavior is corrected.

Applied to files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
📚 Learning: 2026-01-19T18:17:46.433Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38262
File: apps/meteor/client/lib/utils/normalizeMessagePreview/getMessagePreview.ts:24-33
Timestamp: 2026-01-19T18:17:46.433Z
Learning: In the Rocket.Chat repository, usernames (lastMessage.u.username) and display names (lastMessage.u.name) are sanitized/escaped centrally elsewhere in the system, so individual display functions like getMessagePreview do not need to escape these values before interpolating them into strings.

Applied to files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
📚 Learning: 2026-04-18T12:32:53.425Z
Learnt from: rodrigok
Repo: RocketChat/Rocket.Chat PR: 38623
File: apps/meteor/app/lib/server/functions/cleanRoomHistory.ts:146-149
Timestamp: 2026-04-18T12:32:53.425Z
Learning: In `apps/meteor/app/lib/server/functions/cleanRoomHistory.ts` (PR `#38623`), the read-receipt cleanup (both `ReadReceipts.removeByMessageIds` and `ReadReceiptsArchive.removeByMessageIds`) is intentionally only performed in the limited prune path (`limit && selectedMessageIds`). The unlimited/delete-all path (`limit === 0`) deliberately skips cleaning up orphaned read receipts in both hot and cold storage — this is by design. Do not flag this as a bug or missing cleanup in future reviews.

Applied to files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
📚 Learning: 2026-03-20T13:51:23.302Z
Learnt from: ggazzo
Repo: RocketChat/Rocket.Chat PR: 39553
File: apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts:179-181
Timestamp: 2026-03-20T13:51:23.302Z
Learning: In `apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts`, the truthiness guards `...(integration.avatar && { avatar })`, `...(integration.emoji && { emoji })`, `...(integration.alias && { alias })`, and `...(integration.script && { script })` in the `$set` payload of `updateIncomingIntegration` are intentional. Empty-string values for these fields should NOT overwrite the stored value — only truthy values are persisted. Do not flag these as bugs preventing explicit clears.

Applied to files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
📚 Learning: 2026-03-09T18:39:21.178Z
Learnt from: Harxhit
Repo: RocketChat/Rocket.Chat PR: 39476
File: apps/meteor/server/methods/addAllUserToRoom.ts:0-0
Timestamp: 2026-03-09T18:39:21.178Z
Learning: In apps/meteor/server/methods/addAllUserToRoom.ts, the implementation uses a single cursor pass (Users.find(userFilter).batchSize(100)) that collects both the full user objects (collectedUsers: IUser[]) and their usernames (usernames: string[]) in one iteration. `beforeAddUserToRoom` is then called once with the full usernames batch (preserving batch-validation semantics), and the subsequent subscription/message processing loop iterates over the same stable `collectedUsers` array — no second DB query is made. This avoids any race condition between validation and processing while preserving the original batch-validation behavior.

Applied to files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
📚 Learning: 2026-03-04T14:16:49.202Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 39304
File: packages/ui-contexts/src/ActionManagerContext.ts:26-26
Timestamp: 2026-03-04T14:16:49.202Z
Learning: In `packages/ui-contexts/src/ActionManagerContext.ts` (TypeScript, RocketChat/Rocket.Chat), the `disposeView` method in `IActionManager` uses an intentionally explicit union `UiKit.ModalView['id'] | UiKit.BannerView['viewId'] | UiKit.ContextualBarView['id']` to document which view types are accepted, even though all constituents resolve to the same primitive. The inline `// eslint-disable-next-line typescript-eslint/no-duplicate-type-constituents` comment is intentional and should not be flagged or removed.

Applied to files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to **/*.{ts,tsx,js} : Avoid code comments in the implementation

Applied to files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In the Rocket.Chat repository, do not reference Biome lint rules in code review feedback. Biome is not used even if biome.json exists; only reference Biome rules if there is explicit, project-wide usage documented. For TypeScript files, review lint implications without Biome guidance unless the project enables Biome rules.

Applied to files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In this repository (RocketChat/Rocket.Chat), Biome lint rules are not used even if a biome.json exists. When reviewing TypeScript files (e.g., packages/ui-voip/src/providers/useMediaSession.ts), ensure lint suggestions do not reference Biome-specific rules. Rely on general ESLint/TypeScript lint rules and project conventions instead.

Applied to files:

  • apps/meteor/app/lib/server/lib/notifyListener.ts
🔇 Additional comments (1)
apps/meteor/app/lib/server/lib/notifyListener.ts (1)

472-472: Remove implementation comment.

As per coding guidelines (**/*.{ts,tsx,js}: "Avoid code comments in the implementation"), drop this self-explanatory comment.

♻️ Proposed fix
 		if (message.reactions) {
-			// Collect all unique usernames across all reactions
 			const allUsernames = new Set<string>();

Comment thread apps/meteor/app/lib/server/lib/notifyListener.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant