Skip to content

refactor(organization): batch joinable orgs fetch, extract helper#1652

Open
AmanGIT07 wants to merge 1 commit into
mainfrom
refactor/batch-joinable-orgs-fetch
Open

refactor(organization): batch joinable orgs fetch, extract helper#1652
AmanGIT07 wants to merge 1 commit into
mainfrom
refactor/batch-joinable-orgs-fetch

Conversation

@AmanGIT07
Copy link
Copy Markdown
Contributor

Summary

  • core/organization: add Service.GetByIDs thin wrapper over the existing repository method.
  • internal/api/v1beta1connect: expose GetByIDs on the OrganizationService interface; mocks regenerated.
  • ListOrganizationsByUser and ListOrganizationsByCurrentUser now batch-fetch joinable orgs via one GetByIDs call instead of looping orgService.Get(id) per ID.
  • Shared joinable-orgs lookup extracted into joinableOrgsForEmail helper; service-user skip stays in the current-user caller.
  • Disabled / missing joinable orgs are silently excluded by the repository SQL filter; previously, a single disabled domain-trusted org failed the whole RPC with CodeInternal.
  • Batch-error log field renamed from joinable_org_id (string, per failed iteration) to joinable_org_ids ([]string, full attempted set).

Addresses items 1 and 2 of #1637.

Test plan

  • go test ./internal/api/v1beta1connect/... ./core/organization/...
  • make lint
  • Existing TestConnectHandler_ListOrganizationsByUser / TestConnectHandler_ListOrganizationsByCurrentUser updated to expect GetByIDs.
  • New tests added: multi-ID batch fetch (single mock call), batch error path.

🤖 Generated with Claude Code

Replace per-ID orgService.Get loop in ListOrganizationsByUser and
ListOrganizationsByCurrentUser with a single orgService.GetByIDs call,
and extract the shared joinable-orgs lookup into a joinableOrgsForEmail
helper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 26, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
frontier Ready Ready Preview, Comment May 26, 2026 12:28pm

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 26, 2026

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added bulk organization fetch capability, allowing retrieval of multiple organizations by ID in a single API request, reducing overhead and improving application efficiency.
  • Tests

    • Enhanced test coverage for batch organization operations, including error handling scenarios.

Walkthrough

This PR adds a GetByIDs method to the organization service for bulk fetching, refactors the user handler to extract joinable-organization lookup into a reusable helper using batch fetching, and updates tests to validate the new bulk-fetch flow across both user-organization list endpoints.

Changes

Organization bulk-fetch capability

Layer / File(s) Summary
Service GetByIDs method and interface
core/organization/service.go, internal/api/v1beta1connect/interfaces.go, internal/api/v1beta1connect/mocks/organization_service.go
Service layer introduces GetByIDs to fetch multiple organizations by ID slice; OrganizationService interface definition and auto-generated mock are updated to support the new method signature.

Handler refactoring to use batch fetch

Layer / File(s) Summary
Handler helper and bulk fetch integration
internal/api/v1beta1connect/user.go, internal/api/v1beta1connect/user_test.go
Extracts joinable-organization domain→org resolution into joinableOrgsForEmail helper which calls orgService.GetByIDs in bulk instead of per-org loops, applies protobuf transformation, and centralizes error handling; both ListOrganizationsByUser and ListOrganizationsByCurrentUser now delegate to this helper. Test expectations updated and new cases added for single/multiple/error scenarios.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related issues

Suggested reviewers

  • rohilsurana
  • whoAbhishekSah
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
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: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 606b54db-edd3-4b12-8fd3-8acffed46da5

📥 Commits

Reviewing files that changed from the base of the PR and between f1d968b and a803328.

📒 Files selected for processing (5)
  • core/organization/service.go
  • internal/api/v1beta1connect/interfaces.go
  • internal/api/v1beta1connect/mocks/organization_service.go
  • internal/api/v1beta1connect/user.go
  • internal/api/v1beta1connect/user_test.go

Comment on lines +848 to +863
orgs, err := h.orgService.GetByIDs(ctx, joinableOrgIDs)
if err != nil {
args := append([]any{"joinable_org_ids", joinableOrgIDs}, extraCtx...)
errorLogger.LogUnexpectedError(ctx, request, operation, err, args...)
return nil, err
}

pbOrgs := make([]*frontierv1beta1.Organization, 0, len(orgs))
for _, org := range orgs {
orgPB, err := transformOrgToPB(org)
if err != nil {
errorLogger.LogTransformError(ctx, request, operation, org.ID, err)
return nil, err
}
pbOrgs = append(pbOrgs, orgPB)
}
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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Preserve deterministic joinable org ordering in batch path.

At Line 848, GetByIDs can return organizations in arbitrary DB order, so response order may now drift from joinableOrgIDs order (the previous per-ID loop preserved it).

💡 Proposed fix
 	orgs, err := h.orgService.GetByIDs(ctx, joinableOrgIDs)
 	if err != nil {
 		args := append([]any{"joinable_org_ids", joinableOrgIDs}, extraCtx...)
 		errorLogger.LogUnexpectedError(ctx, request, operation, err, args...)
 		return nil, err
 	}
 
-	pbOrgs := make([]*frontierv1beta1.Organization, 0, len(orgs))
-	for _, org := range orgs {
+	orgByID := make(map[string]organization.Organization, len(orgs))
+	for _, org := range orgs {
+		orgByID[org.ID] = org
+	}
+
+	pbOrgs := make([]*frontierv1beta1.Organization, 0, len(joinableOrgIDs))
+	for _, orgID := range joinableOrgIDs {
+		org, ok := orgByID[orgID]
+		if !ok {
+			// disabled/missing orgs are intentionally skipped
+			continue
+		}
 		orgPB, err := transformOrgToPB(org)
 		if err != nil {
 			errorLogger.LogTransformError(ctx, request, operation, org.ID, err)
 			return nil, err
 		}
 		pbOrgs = append(pbOrgs, orgPB)
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
orgs, err := h.orgService.GetByIDs(ctx, joinableOrgIDs)
if err != nil {
args := append([]any{"joinable_org_ids", joinableOrgIDs}, extraCtx...)
errorLogger.LogUnexpectedError(ctx, request, operation, err, args...)
return nil, err
}
pbOrgs := make([]*frontierv1beta1.Organization, 0, len(orgs))
for _, org := range orgs {
orgPB, err := transformOrgToPB(org)
if err != nil {
errorLogger.LogTransformError(ctx, request, operation, org.ID, err)
return nil, err
}
pbOrgs = append(pbOrgs, orgPB)
}
orgs, err := h.orgService.GetByIDs(ctx, joinableOrgIDs)
if err != nil {
args := append([]any{"joinable_org_ids", joinableOrgIDs}, extraCtx...)
errorLogger.LogUnexpectedError(ctx, request, operation, err, args...)
return nil, err
}
orgByID := make(map[string]organization.Organization, len(orgs))
for _, org := range orgs {
orgByID[org.ID] = org
}
pbOrgs := make([]*frontierv1beta1.Organization, 0, len(joinableOrgIDs))
for _, orgID := range joinableOrgIDs {
org, ok := orgByID[orgID]
if !ok {
// disabled/missing orgs are intentionally skipped
continue
}
orgPB, err := transformOrgToPB(org)
if err != nil {
errorLogger.LogTransformError(ctx, request, operation, org.ID, err)
return nil, err
}
pbOrgs = append(pbOrgs, orgPB)
}

@coveralls
Copy link
Copy Markdown

Coverage Report for CI Build 26448078626

Coverage increased (+0.04%) to 42.847%

Details

  • Coverage increased (+0.04%) from the base build.
  • Patch coverage: 10 uncovered changes across 2 files (27 of 37 lines covered, 72.97%).
  • No coverage regressions found.

Uncovered Changes

File Changed Covered %
internal/api/v1beta1connect/user.go 34 27 79.41%
core/organization/service.go 3 0 0.0%

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 37846
Covered Lines: 16216
Line Coverage: 42.85%
Coverage Strength: 12.0 hits per line

💛 - Coveralls

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants