-
Notifications
You must be signed in to change notification settings - Fork 279
Fix group member count #2524
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
Fix group member count #2524
Conversation
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughThe Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
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. Comment |
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.
Actionable comments posted: 5
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
models/discordactions.js
🧰 Additional context used
🪛 GitHub Actions: Tests
models/discordactions.js
[error] 1-1: Failed to parse URL from DISCORD_BASE_URL/discord-members during enrichGroupDataWithMembershipInfo.
[warning] 338-338: Generic Object Injection Sink security/detect-object-injection.
🪛 GitHub Check: build (22.10.0)
models/discordactions.js
[warning] 338-338:
Generic Object Injection Sink
[warning] 338-338:
Generic Object Injection Sink
| // Discord live role membership (used for memberCount) | ||
| const discordMembers = await getDiscordMembers(); | ||
| const liveRoleIdToCountMap = {}; | ||
|
|
||
| discordMembers.forEach((member) => { | ||
| if (!member.roles) return; | ||
|
|
||
| member.roles.forEach((roleId) => { | ||
| liveRoleIdToCountMap[roleId] = (liveRoleIdToCountMap[roleId] || 0) + 1; | ||
| }); | ||
| }); |
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.
Missing error handling for Discord API call causes pipeline failure.
The pipeline is failing with Failed to parse URL from DISCORD_BASE_URL/discord-members because getDiscordMembers() is called without error handling. If the Discord API is unavailable or misconfigured, the entire function fails with no fallback.
Consider wrapping this in a try/catch and falling back to the Firestore-based count (roleIdToCountMap) when Discord is unreachable:
🔎 Proposed fix with graceful degradation
// Discord live role membership (used for memberCount)
- const discordMembers = await getDiscordMembers();
const liveRoleIdToCountMap = {};
+ let useFirestoreFallback = false;
- discordMembers.forEach((member) => {
- if (!member.roles) return;
+ try {
+ const discordMembers = await getDiscordMembers();
+ discordMembers.forEach((member) => {
+ if (!member.roles) return;
- member.roles.forEach((roleId) => {
- liveRoleIdToCountMap[roleId] = (liveRoleIdToCountMap[roleId] || 0) + 1;
+ member.roles.forEach((roleId) => {
+ liveRoleIdToCountMap[roleId] = (liveRoleIdToCountMap[roleId] || 0) + 1;
+ });
});
- });
+ } catch (error) {
+ logger.warn("Failed to fetch Discord members, falling back to Firestore counts", error);
+ useFirestoreFallback = true;
+ }Then update line 352:
- memberCount: liveRoleIdToCountMap[group.roleid] || 0,
+ memberCount: useFirestoreFallback
+ ? (roleIdToCountMap[group.roleid] || 0)
+ : (liveRoleIdToCountMap[group.roleid] || 0),🧰 Tools
🪛 GitHub Actions: Tests
[warning] 338-338: Generic Object Injection Sink security/detect-object-injection.
🪛 GitHub Check: build (22.10.0)
[warning] 338-338:
Generic Object Injection Sink
[warning] 338-338:
Generic Object Injection Sink
🤖 Prompt for AI Agents
In models/discordactions.js around lines 330 to 340, the call to
getDiscordMembers() has no error handling so any Discord API failure crashes the
flow; wrap the await getDiscordMembers() in a try/catch, on success populate
liveRoleIdToCountMap as shown, and on error log the error and set
liveRoleIdToCountMap = {} (or leave undefined) so the later code falls back to
the Firestore-derived roleIdToCountMap; ensure the catch does not rethrow and
that subsequent merges/use of liveRoleIdToCountMap check for its presence before
overriding Firestore counts.
models/discordactions.js
Outdated
| // This says how many users we have for a given roleId | ||
| roleIdToCountMap[groupToUserMapping.roleid] = (roleIdToCountMap[groupToUserMapping.roleid] ?? 0) + 1; | ||
| // Discord live role membership (used for memberCount) | ||
| const discordMembers = await getDiscordMembers(); |
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.
🧹 Nitpick | 🔵 Trivial
Consider caching Discord member data to reduce API calls.
getDiscordMembers() is now called on every invocation of enrichGroupDataWithMembershipInfo. If this function is called frequently (e.g., on group listing pages), this could:
- Increase latency due to network round-trips
- Hit Discord API rate limits
- Cause failures if Discord is temporarily unavailable
Consider implementing a short-lived cache (e.g., 1-5 minutes) for the Discord members data, or fetching it at a higher level and passing it as a parameter.
| member.roles.forEach((roleId) => { | ||
| liveRoleIdToCountMap[roleId] = (liveRoleIdToCountMap[roleId] || 0) + 1; | ||
| }); |
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.
🧹 Nitpick | 🔵 Trivial
Consider using Map instead of plain object to avoid prototype pollution risk.
Static analysis flagged this as a "Generic Object Injection Sink." While Discord role IDs are safe numeric strings, using a Map would eliminate the warning and provide better type safety:
🔎 Alternative using Map
- const liveRoleIdToCountMap = {};
+ const liveRoleIdToCountMap = new Map();
discordMembers.forEach((member) => {
if (!member.roles) return;
member.roles.forEach((roleId) => {
- liveRoleIdToCountMap[roleId] = (liveRoleIdToCountMap[roleId] || 0) + 1;
+ liveRoleIdToCountMap.set(roleId, (liveRoleIdToCountMap.get(roleId) || 0) + 1);
});
});Then update line 352:
- memberCount: liveRoleIdToCountMap[group.roleid] || 0,
+ memberCount: liveRoleIdToCountMap.get(group.roleid) || 0,Committable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 GitHub Actions: Tests
[warning] 338-338: Generic Object Injection Sink security/detect-object-injection.
🪛 GitHub Check: build (22.10.0)
[warning] 338-338:
Generic Object Injection Sink
[warning] 338-338:
Generic Object Injection Sink
🤖 Prompt for AI Agents
In models/discordactions.js around lines 337-339, replace the plain object usage
for liveRoleIdToCountMap with a Map to avoid prototype pollution warnings:
initialize liveRoleIdToCountMap as new Map(), then inside the loop read the
current count with liveRoleIdToCountMap.get(roleId) || 0 and update it with
liveRoleIdToCountMap.set(roleId, count + 1). Also update any later code that
expects a plain object to either accept a Map or convert the Map to an object
via Object.fromEntries(liveRoleIdToCountMap) where needed.
…MembershipInfo to Tells NYC: don’t enforce coverage here
services/discordMembersService.js
Outdated
|
|
||
| const rawBaseUrl = config.get("services.discordBot.baseUrl"); | ||
| const DISCORD_BASE_URL = rawBaseUrl && rawBaseUrl !== "DISCORD_BASE_URL" ? rawBaseUrl : "http://localhost:8080"; |
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.
why is this change required? isn't the config file already handling fallback value?
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.
undone the changes as the config file was already handling the fallback value
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.
the use of adding fetchStub here is unclear, test changes in this file don't seem to be using it, can you point me where is it being used?
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.
The fetch stub isn’t used directly in this test. The request hits /discord-actions/groups, which internally calls getDiscordMembers().
The stub ensures that call doesn’t make a real Discord API request and keeps the integration test deterministic.
models/discordactions.js
Outdated
| * @returns {Promise<Array<object>>} - An array of group objects with enriched information. | ||
| */ | ||
|
|
||
| /* istanbul ignore next */ |
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.
please remove unnecessary comments from this file
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.
/* istanbul ignore next */ was added to exclude a defensive error path that depends on external Discord failures and isn’t reliably testable. Without this, coverage reports false negatives even though the core logic is already covered.
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.
@Kavyashri217 please remove this
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.
Removed the comment
|
Date: 23-12-2025
Developer Name: Kavyashri K R
Issue Ticket Number
Description
Changes made:
What this changes:
Scope:
Backend
Documentation Updated?
Under Feature Flag
Database Changes
Breaking Changes
Development Tested?
Screenshots
Screenshot 1
Test Coverage
Screenshot 1
Additional Notes