Skip to content

perf(committees): eliminate N+1 upstream count calls in groups list#1060

Open
MRashad26 wants to merge 3 commits into
mainfrom
perf/LFXV2-2120
Open

perf(committees): eliminate N+1 upstream count calls in groups list#1060
MRashad26 wants to merge 3 commits into
mainfrom
perf/LFXV2-2120

Conversation

@MRashad26

Copy link
Copy Markdown
Contributor

Summary

  • Root cause: GET /api/committees and GET /api/committees/my-committees fired 2 upstream API calls per committee (member count + mailing-list count) after the initial list query. For a large foundation like AAIF with many groups, this created a burst of 2N simultaneous upstream requests on every page load — the primary cause of slow load times in ED view.

  • Fix 1 — total_members: The committee-service already indexes total_members as part of CommitteeBaseWithReadonlyAttributes (confirmed in upstream Goa design). Dropped the per-committee getCommitteeMembersCount count call and used the field already present in the indexed resource.

  • Fix 2 — has_mailing_list: Replaced N individual groupsio_mailing_list count calls with a single batched query using the query service tags: ArrayOf(String) OR-semantic parameter. Cost drops from O(N) to O(1) upstream requests per page load, chunked at 100 UIDs per request.

Before: getCommittees(N committees) → 1 list query + 2N count calls + 1 access check
After: getCommittees(N committees) → 1 list query + 1 mailing-list batch query + 1 access check

Same improvement applies to getMyCommittees.

Test plan

  • Navigate to Groups page as ED on AAIF — confirm it loads significantly faster
  • Confirm total_members count displays correctly on committee cards
  • Confirm mailing-list icon still shows correctly for committees that have a mailing list
  • Navigate to Groups page as a regular member — confirm no regression
  • Confirm me-lens (My Groups) also loads faster for users with many memberships

Fixes LFXV2-2120

🤖 Generated with Claude Code

…FXV2-2120)

GET /api/committees and my-committees previously fired 2 upstream API calls per
committee (getCommitteeMembersCount + getMailingListCountByCommittee). For a
foundation like AAIF with many groups this created a burst of 2N simultaneous
count requests on every page load, causing the slowness reported in ED view.

Fix:
- Trust the committee-service-indexed `total_members` field that is already
  present in each committee resource returned by the query service
  (CommitteeBaseWithReadonlyAttributes in the upstream Goa design) — no
  separate count call needed.
- Replace N individual mailing-list count calls with a single batched query
  using the query service `tags` array parameter (OR semantics), chunked at
  100 UIDs per request. Cost drops from O(N) to O(1) upstream requests for
  both getCommittees and getMyCommittees.

The old getMailingListCountByCommittee private helper is retained for
potential future use but is no longer called from the list paths.

Signed-off-by: Mohammed Rashad <mrashad@contractor.linuxfoundation.org>
Signed-off-by: Rashad <mrashad@contractor.linuxfoundation.org>
Copilot AI review requested due to automatic review settings July 2, 2026 16:05
@MRashad26 MRashad26 requested a review from a team as a code owner July 2, 2026 16:05
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9de95efe-13a3-460e-a41f-48f5c22a1859

📥 Commits

Reviewing files that changed from the base of the PR and between 6578700 and 17ce56a.

📒 Files selected for processing (1)
  • apps/lfx-one/src/server/services/committee.service.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/lfx-one/src/server/services/committee.service.ts

Walkthrough

Committee data loading now uses batched mailing-list lookup and indexed member totals, the dashboard fetches committee UIDs through a lightweight endpoint for non-Me scope, and project metadata lookup batches are larger.

Changes

Committee enrichment and UID loading

Layer / File(s) Summary
Batched mailing-list helper
apps/lfx-one/src/server/services/committee.service.ts
Adds getCommitteesWithMailingList, which chunks committee UIDs, queries groupsio_mailing_list in batches with OR-tag semantics, and returns a Set of found committee_uid values while logging and falling back on error.
Committee enrichment paths
apps/lfx-one/src/server/services/committee.service.ts
Updates getCommittees and getMyCommittees to replace per-committee fan-outs with the batched mailing-list lookup, use indexed committee.total_members, and derive has_mailing_list from the returned UID set.
UID endpoint and dashboard loading
apps/lfx-one/src/server/controllers/committee.controller.ts, apps/lfx-one/src/server/routes/committees.route.ts, apps/lfx-one/src/app/shared/services/committee.service.ts, apps/lfx-one/src/app/modules/committees/committee-dashboard/committee-dashboard.component.ts
Adds a /my-committee-uids endpoint and client method, then changes the dashboard to load UID sets separately for non-Me scope while keeping Me-lens UID derivation from enriched committees.

Project metadata batching

Layer / File(s) Summary
Project lookup batch size
apps/lfx-one/src/server/services/project.service.ts
Changes enrichWithProjectData to chunk projectUids into batches of 50 before running parallel getProjectById lookups.

Estimated code review effort: 3 (Moderate) | ~25 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: removing N+1 upstream count calls from committee listings.
Description check ✅ Passed The description matches the changeset and explains the performance fix and test plan for committee list loading.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/LFXV2-2120

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration.


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

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

🚀 Deployment Status

Your branch has been deployed to: https://ui-pr-1060.dev.v2.cluster.linuxfound.info

Deployment Details:

  • Environment: Development
  • Namespace: ui-pr-1060
  • ArgoCD App: ui-pr-1060

The deployment will be automatically removed when this PR is closed.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (4)
apps/lfx-one/src/server/services/committee.service.ts (4)

1674-1680: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Inline object type used as generic argument instead of a named interface.

{ committee_uid?: string } is repeated as an inline type literal for both fetchAllQueryResources and QueryServiceResponse. Extracting a small named interface (e.g. interface MailingListResource { committee_uid?: string }) would satisfy the project's TS convention and avoid duplicating the shape.

As per coding guidelines, "Use interfaces for object shape definitions in TypeScript."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/lfx-one/src/server/services/committee.service.ts` around lines 1674 -
1680, The mailing list query uses the same inline object shape twice in
`committee.service.ts`, which violates the TypeScript convention to prefer
interfaces for object shapes. Extract `{ committee_uid?: string }` into a named
interface (for example, a small resource type used by `fetchAllQueryResources`
and `QueryServiceResponse`) and update the `mailingLists` fetch in
`committee.service.ts` to reference that interface instead of repeating the
literal.

Source: Coding guidelines


1653-1663: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Stale leftover JSDoc block before the new method's own docstring.

Lines 1653-1656 ("Fetches count of mailing lists associated with a specific committee...") describe getMailingListCountByCommittee's old per-committee approach, but they now sit directly above getCommitteesWithMailingList's own JSDoc (1657-1663), which documents the new batched approach. This orphaned comment block should be removed to avoid confusing future readers about which method it describes.

🧹 Proposed fix
-  /**
-   * Fetches count of mailing lists associated with a specific committee.
-   * Used to determine the has_mailing_list flag for committee list views.
-   */
   /**
    * Returns the subset of the provided committee UIDs that have at least one associated
    * `groupsio_mailing_list` resource. Uses a single batched query with OR-tag semantics
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/lfx-one/src/server/services/committee.service.ts` around lines 1653 -
1663, Remove the stale JSDoc block in committee.service.ts that still describes
the old getMailingListCountByCommittee behavior and leave only the docstring for
getCommitteesWithMailingList. This orphaned comment sits directly before the new
method’s own documentation, so delete the outdated “Fetches count of mailing
lists...” lines to keep the comment accurately attached to
getCommitteesWithMailingList and avoid confusion.

964-993: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Run the two independent batched lookups concurrently.

getCommitteesByIds(committeeUids) (line 969) and getCommitteesWithMailingList(committeeUids) (line 973) both depend only on committeeUids, not on each other's result, yet they're awaited sequentially. Running them in parallel shaves one round-trip off the exact path this PR is optimizing.

⚡ Proposed fix
-    const committeeUids = Array.from(membershipMap.keys());
-    const committees = await this.getCommitteesByIds(req, committeeUids);
-
-    // Batch check mailing-list presence for all committee UIDs in one query instead of N
-    // per-committee count calls. total_members is already indexed by the committee-service.
-    const committeesWithMailingList = committeeUids.length > 0 ? await this.getCommitteesWithMailingList(req, committeeUids) : new Set<string>();
+    const committeeUids = Array.from(membershipMap.keys());
+
+    // Fetch committee resources and mailing-list presence in parallel — both depend only
+    // on committeeUids, not on each other's result.
+    const [committees, committeesWithMailingList] = await Promise.all([
+      this.getCommitteesByIds(req, committeeUids),
+      committeeUids.length > 0 ? this.getCommitteesWithMailingList(req, committeeUids) : Promise.resolve(new Set<string>()),
+    ]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/lfx-one/src/server/services/committee.service.ts` around lines 964 -
993, The two batched lookups in committee.service’s get_my_committees flow are
independent but currently awaited one after the other. Update the logic around
getCommitteesByIds and getCommitteesWithMailingList so both requests are started
together and then awaited together, keeping the existing empty-list guard for
mailing lists. Preserve the rest of the enrichment path that uses committeeUids,
committees, and committeesWithMailingList unchanged.

1697-1711: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the unused getMailingListCountByCommittee helper. It has no remaining call sites, so deleting it will reduce dead code and keep the service easier to maintain.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/lfx-one/src/server/services/committee.service.ts` around lines 1697 -
1711, Remove the dead helper getMailingListCountByCommittee from
committee.service.ts since it has no remaining callers. Delete the private
method entirely, and make sure nothing else in CommitteeService references it or
depends on its logger/microserviceProxy logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/lfx-one/src/server/services/committee.service.ts`:
- Around line 1664-1696: The batching in getCommitteesWithMailingList currently
wraps the entire loop in one try/catch, so one failing batch stops all later
batches and hides partial results; refactor it so each batch handles its own
failure and other batches still run, ideally using the same
Promise.all/per-batch error-handling approach as getCommitteesByIds. Also update
the recoverable failure log in getCommitteesWithMailingList from logger.debug to
logger.warning so the fallback is visible while still returning the found Set.

---

Nitpick comments:
In `@apps/lfx-one/src/server/services/committee.service.ts`:
- Around line 1674-1680: The mailing list query uses the same inline object
shape twice in `committee.service.ts`, which violates the TypeScript convention
to prefer interfaces for object shapes. Extract `{ committee_uid?: string }`
into a named interface (for example, a small resource type used by
`fetchAllQueryResources` and `QueryServiceResponse`) and update the
`mailingLists` fetch in `committee.service.ts` to reference that interface
instead of repeating the literal.
- Around line 1653-1663: Remove the stale JSDoc block in committee.service.ts
that still describes the old getMailingListCountByCommittee behavior and leave
only the docstring for getCommitteesWithMailingList. This orphaned comment sits
directly before the new method’s own documentation, so delete the outdated
“Fetches count of mailing lists...” lines to keep the comment accurately
attached to getCommitteesWithMailingList and avoid confusion.
- Around line 964-993: The two batched lookups in committee.service’s
get_my_committees flow are independent but currently awaited one after the
other. Update the logic around getCommitteesByIds and
getCommitteesWithMailingList so both requests are started together and then
awaited together, keeping the existing empty-list guard for mailing lists.
Preserve the rest of the enrichment path that uses committeeUids, committees,
and committeesWithMailingList unchanged.
- Around line 1697-1711: Remove the dead helper getMailingListCountByCommittee
from committee.service.ts since it has no remaining callers. Delete the private
method entirely, and make sure nothing else in CommitteeService references it or
depends on its logger/microserviceProxy logic.
🪄 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: f141c51a-6767-483d-a8bf-c1c087c37280

📥 Commits

Reviewing files that changed from the base of the PR and between 0ff8d11 and b85256b.

📒 Files selected for processing (1)
  • apps/lfx-one/src/server/services/committee.service.ts

Comment thread apps/lfx-one/src/server/services/committee.service.ts

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR is a backend performance fix for the committees ("Groups") list endpoints in the Express BFF. Previously, GET /api/committees and GET /api/committees/my-committees fired 2 upstream count calls per committee (member count + mailing-list count) after the initial list query, producing a burst of 2N upstream requests per page load and slow load times (notably in ED view for large foundations). The change replaces those per-committee calls with the already-indexed total_members field and a single batched mailing-list presence query.

Changes:

  • Drop per-committee getCommitteeMembersCount calls in getCommittees and getMyCommittees; use the indexed committee.total_members ?? 0 instead.
  • Add getCommitteesWithMailingList, a batched groupsio_mailing_list lookup (chunked at 100 UIDs, OR-tag semantics) that replaces the N individual mailing-list count calls.
  • Enrich each committee/MyCommittee with has_mailing_list derived from the batched result set.
Comments suppressed due to low confidence (1)

apps/lfx-one/src/server/services/committee.service.ts:1711

  • getMailingListCountByCommittee is now dead code — this change removed its only caller, and a repository search finds no other references. The public getCommitteeMembersCount (around line 452) is similarly unused after this change. Consider removing both helpers (and the stray JSDoc above) to avoid leaving unused query paths behind.

  private async getMailingListCountByCommittee(req: Request, committeeId: string): Promise<number> {
    try {
      const { count } = await this.microserviceProxy.proxyRequest<QueryServiceCountResponse>(req, 'LFX_V2_SERVICE', '/query/resources/count', 'GET', {
        type: 'groupsio_mailing_list',
        tags: `committee_uid:${committeeId}`,
      });
      return count;
    } catch (error) {
      logger.debug(req, 'get_mailing_list_count_by_committee', 'Failed to fetch mailing list count, defaulting to 0', {
        committee_uid: committeeId,
        error: error instanceof Error ? error.message : 'Unknown error',
      });
      return 0;
    }
  }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread apps/lfx-one/src/server/services/committee.service.ts Outdated
Comment thread apps/lfx-one/src/server/services/committee.service.ts Outdated
…groups (LFXV2-2120)

Three follow-up improvements to the groups page in ED/project view:

- committee-dashboard: non-me-lens skips full getMyCommittees enrichment; member
  badge UIDs are now fetched via a new lightweight /my-committee-uids endpoint that
  only reads committee_member records (no committee detail or project fan-out)
- committee.controller/route: add GET /committees/my-committee-uids backed by the
  existing committeeService.getMyCommitteeUids — returns string[] of UIDs
- project.service: raise enrichWithProjectData batchSize from 10 to 50, collapsing
  sequential upstream rounds from ceil(N/10) to ceil(N/50) for project enrichment

Signed-off-by: Rashad <mrashad@contractor.linuxfoundation.org>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
apps/lfx-one/src/app/modules/committees/committee-dashboard/committee-dashboard.component.ts (1)

319-345: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Consider scoping getMyCommitteeUids() by project when in 'project' mode.

For non-Me lens, getMyCommitteeUids() is called without a projectUid, so it always fetches the full set of the user's committee memberships across every project rather than just the ones relevant to the active project. This is functionally correct (the Set is only used via .has(uid)), but for orgs where a user belongs to many committees org-wide, it fetches more data than needed. The sibling initializeMyCommittees() already derives a project/foundation scope$ for this same branch — reusing scope.uid when scope.mode === 'project' (foundation mode can't be scoped this way since the endpoint filters by a single project_uid tag and would incorrectly exclude sub-project memberships) would tighten the query.

♻️ Proposed refactor to scope by project when applicable
   private initializeMyCommitteeUids(): Signal<Set<string>> {
     const fromFull$ = toObservable(computed(() => new Set(this.myCommittees().map((c) => c.uid))));
     const isMeLens$ = toObservable(this.isMeLens);
     const refresh$ = toObservable(this.refresh);
+    const project$ = toObservable(this.project);
+    const isFoundationContext$ = toObservable(this.isFoundationContext);

     return toSignal(
-      combineLatest([isMeLens$, refresh$]).pipe(
-        switchMap(([isMeLens]) => {
+      combineLatest([isMeLens$, refresh$, project$, isFoundationContext$]).pipe(
+        switchMap(([isMeLens, , project, isFoundation]) => {
           if (isMeLens) {
             return fromFull$;
           }
-          return this.committeeService.getMyCommitteeUids().pipe(
+          const projectUid = !isFoundation ? (project?.uid ?? undefined) : undefined;
+          return this.committeeService.getMyCommitteeUids(projectUid).pipe(
             map((uids) => new Set(uids)),
             catchError(() => of(new Set<string>()))
           );
         })
       ),
       { initialValue: new Set<string>() }
     );
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/lfx-one/src/app/modules/committees/committee-dashboard/committee-dashboard.component.ts`
around lines 319 - 345, The non-Me branch in initializeMyCommitteeUids currently
calls committeeService.getMyCommitteeUids() without any scope, so it fetches all
committee memberships org-wide. Reuse the same scope logic already used in
initializeMyCommittees, and when scope.mode is project pass scope.uid into
getMyCommitteeUids() so the membership Set is limited to the active project;
keep foundation mode unscoped because the endpoint would filter out sub-project
memberships. Preserve the existing catchError and Set<string> handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@apps/lfx-one/src/app/modules/committees/committee-dashboard/committee-dashboard.component.ts`:
- Around line 319-345: The non-Me branch in initializeMyCommitteeUids currently
calls committeeService.getMyCommitteeUids() without any scope, so it fetches all
committee memberships org-wide. Reuse the same scope logic already used in
initializeMyCommittees, and when scope.mode is project pass scope.uid into
getMyCommitteeUids() so the membership Set is limited to the active project;
keep foundation mode unscoped because the endpoint would filter out sub-project
memberships. Preserve the existing catchError and Set<string> handling.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f2136db2-3126-4b28-81a1-de885a293828

📥 Commits

Reviewing files that changed from the base of the PR and between b85256b and 6578700.

📒 Files selected for processing (5)
  • apps/lfx-one/src/app/modules/committees/committee-dashboard/committee-dashboard.component.ts
  • apps/lfx-one/src/app/shared/services/committee.service.ts
  • apps/lfx-one/src/server/controllers/committee.controller.ts
  • apps/lfx-one/src/server/routes/committees.route.ts
  • apps/lfx-one/src/server/services/project.service.ts

Address review comments from @copilot-pull-request-reviewer, @coderabbitai:

- committee.service.ts: fix getCommitteesWithMailingList — ml.committee_uid is
  always undefined; committee UIDs live in ml.committees[].uid per the
  GroupsIOMailingList interface (per @copilot-pull-request-reviewer)
- committee.service.ts: convert sequential batch loop to Promise.allSettled so
  one failing chunk does not suppress mailing-list flags for unrelated batches;
  move recoverable-failure log from logger.debug to logger.warning
  (per @coderabbitai, @copilot-pull-request-reviewer)
- committee.service.ts: remove stray duplicate JSDoc block left above
  getCommitteesWithMailingList from the prior method (per @copilot-pull-request-reviewer)

Resolves 3 review threads.

Signed-off-by: Rashad <mrashad@contractor.linuxfoundation.org>
Copilot AI review requested due to automatic review settings July 3, 2026 08:16
@MRashad26

Copy link
Copy Markdown
Contributor Author

Review Feedback Addressed

Commit: 17ce56a

Changes Made

  • committee.service.ts: Fixed getCommitteesWithMailingListml.committee_uid is always undefined; committee UIDs live in ml.committees[].uid per the GroupsIOMailingList interface. Changed generic type and iterate ml.committees ?? [] to populate the set. (per @copilot-pull-request-reviewer)
  • committee.service.ts: Converted sequential batch loop to Promise.allSettled so concurrent batches run independently; a failure in one chunk no longer suppresses mailing-list flags for unrelated batches. Moved recoverable-failure log from logger.debuglogger.warning. (per @coderabbitai, @copilot-pull-request-reviewer)
  • committee.service.ts: Removed stray duplicate JSDoc block that was left above getCommitteesWithMailingList when the method was inserted. (per @copilot-pull-request-reviewer)

Threads Resolved

3 of 3 unresolved threads addressed.

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
fd committee.service.ts apps/lfx-one/src/server/services --exec cat -n {} \; | sed -n '1,400p' | grep -n "getCommitteesWithMailingList\|Promise.allSettled\|logger.warning\|committee_uid\|ml.committees"

Length of output: 927


🏁 Script executed:

#!/bin/bash
FILE=$(fd committee.service.ts apps/lfx-one/src/server/services)
wc -l "$FILE"
grep -n "getCommitteesWithMailingList\|Promise.allSettled\|logger.warning\|logger.debug\|committee_uid\|ml.committees\|GroupsIOMailingList" "$FILE"
echo "---"
sed -n '/getCommitteesWithMailingList/,/^  }/p' "$FILE" | head -100

Length of output: 944


FILE="apps/lfx-one/src/server/services/committee.service.ts"
wc -l "$FILE"
grep -n "getCommitteesWithMailingList|Promise.allSettled|logger.warning|logger.debug|committee_uid|ml.committees|GroupsIOMailingList" "$FILE"
echo "---"
sed -n '/getCommitteesWithMailingList/,/^ }/p' "$FILE" | head -100

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (1)

apps/lfx-one/src/server/services/committee.service.ts:1708

  • getMailingListCountByCommittee is now unused (the list views switched to getCommitteesWithMailingList, and this method is private, so nothing outside the class can call it). Removing it will avoid dead code and reduce future confusion about which approach is canonical.
  private async getMailingListCountByCommittee(req: Request, committeeId: string): Promise<number> {
    try {
      const { count } = await this.microserviceProxy.proxyRequest<QueryServiceCountResponse>(req, 'LFX_V2_SERVICE', '/query/resources/count', 'GET', {
        type: 'groupsio_mailing_list',
        tags: `committee_uid:${committeeId}`,

Comment on lines +170 to +172
// Enrich with mailing-list presence via a single batched query (OR-tag semantics).
// total_members is already indexed by the committee-service as part of
// CommitteeBaseWithReadonlyAttributes — no separate per-committee count call needed.
Comment on lines +1655 to +1659
* Returns the subset of the provided committee UIDs that have at least one associated
* `groupsio_mailing_list` resource. Uses a single batched query with OR-tag semantics
* (the query service `tags` parameter is ArrayOf(String) with OR logic) instead of one
* count call per committee — cost is O(1) upstream requests regardless of list size,
* chunked at 100 UIDs per request for URL-length safety.
Comment on lines +337 to +340
return this.committeeService.getMyCommitteeUids().pipe(
map((uids) => new Set(uids)),
catchError(() => of(new Set<string>()))
);
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.

2 participants