Skip to content

Commit c0c3742

Browse files
committed
fix: add query to select workspaces if we find orgs that do not have any (#16962)
1 parent d9729b3 commit c0c3742

File tree

1 file changed

+46
-3
lines changed

1 file changed

+46
-3
lines changed

airbyte-commons-server/src/main/kotlin/io/airbyte/commons/server/handlers/OrganizationsHandler.kt

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@ import io.airbyte.api.model.generated.ListOrganizationSummariesRequestBody
99
import io.airbyte.api.model.generated.ListOrganizationSummariesResponse
1010
import io.airbyte.api.model.generated.ListOrganizationsByUserRequestBody
1111
import io.airbyte.api.model.generated.ListWorkspacesByUserRequestBody
12+
import io.airbyte.api.model.generated.ListWorkspacesInOrganizationRequestBody
1213
import io.airbyte.api.model.generated.OrganizationCreateRequestBody
1314
import io.airbyte.api.model.generated.OrganizationIdRequestBody
1415
import io.airbyte.api.model.generated.OrganizationInfoRead
1516
import io.airbyte.api.model.generated.OrganizationRead
1617
import io.airbyte.api.model.generated.OrganizationReadList
1718
import io.airbyte.api.model.generated.OrganizationSummary
1819
import io.airbyte.api.model.generated.OrganizationUpdateRequestBody
20+
import io.airbyte.api.model.generated.Pagination
1921
import io.airbyte.api.model.generated.WorkspaceRead
2022
import io.airbyte.api.model.generated.WorkspaceReadList
2123
import io.airbyte.config.ConfigNotFoundType
@@ -148,6 +150,25 @@ open class OrganizationsHandler(
148150
return OrganizationReadList().organizations(organizationReadList)
149151
}
150152

153+
/**
154+
* This function makes several calls and aggregates results from multiple areas to provide a more comprehensive
155+
* summary of an organizations state. This is meant to serve the org/workspace picker for the org landing page.
156+
* The logic is relatively confusing: we accept a filter value that applied to both the organization name AND
157+
* the workspace name, which can result in what appears to be missing data. I've tried to summarize some of this here:
158+
*
159+
* 1. When nameContains filters out all orgs but results in workspaces: in this case, we go through the workspace
160+
* id set and select the orgs for each workspace so we can associate them.
161+
* 2. When nameContains filters out all the workspaces but results in orgs: here, we loop through all the org results
162+
* that do not contain workspaces in their lists and select those workspaces. ***This selection respects the original
163+
* filters and page size!***
164+
* 3. We maintain a separate map of member counts, which is associated to the org id. We join this with the original org
165+
* when we create the response body.
166+
* As a result, we potentially make all the following db queries:
167+
* 1. get orgs by user id
168+
* 2. get workspaces by user id
169+
* 3. get member counts by org id
170+
* 4. get workspaces by org id
171+
*/
151172
@Trace
152173
fun getOrganizationSummaries(request: ListOrganizationSummariesRequestBody): ListOrganizationSummariesResponse {
153174
val orgListReq =
@@ -187,17 +208,39 @@ open class OrganizationsHandler(
187208
)
188209
val orgIdToMemberCount = memberCounts.associate { it.organizationId to it.count }
189210

190-
val orgIdToWorkspace = mutableMapOf<UUID, MutableList<WorkspaceRead>>()
211+
val orgIdToWorkspaceMap = mutableMapOf<UUID, MutableList<WorkspaceRead>>()
191212
for (workspace in workspaceListResp.workspaces) {
192-
orgIdToWorkspace.getOrPut(workspace.organizationId) { mutableListOf() }.add(workspace)
213+
orgIdToWorkspaceMap.getOrPut(workspace.organizationId) { mutableListOf() }.add(workspace)
193214
}
194215

216+
// It's possible, due to filtering rules, that we end up with orgs in the orgs list that do not
217+
// contain workspaces. We want to show at least some workspaces here (still respecting the original filtering/pagination rules)
218+
// so we attempt to get them here
219+
val fullyPopulatedOrgMap: Map<UUID, List<WorkspaceRead>> =
220+
orgIdToWorkspaceMap.mapValues {
221+
if (it.value.isEmpty()) {
222+
val req =
223+
ListWorkspacesInOrganizationRequestBody()
224+
.organizationId(it.key)
225+
.nameContains(request.nameContains)
226+
.pagination(
227+
Pagination()
228+
.pageSize(request.pagination.pageSize)
229+
.rowOffset(request.pagination.rowOffset),
230+
)
231+
val workspaces = workspacesHandler.listWorkspacesInOrganization(req)
232+
workspaces.workspaces
233+
} else {
234+
it.value
235+
}
236+
}
237+
195238
val orgSummaries = mutableListOf<OrganizationSummary>()
196239
for (org in orgListResp.organizations) {
197240
val summary =
198241
OrganizationSummary()
199242
.organization(org)
200-
.workspaces(orgIdToWorkspace[org.organizationId])
243+
.workspaces(fullyPopulatedOrgMap[org.organizationId])
201244
.subscription(null) // will be filled in by the caller when we are in cloud
202245
.memberCount(orgIdToMemberCount[org.organizationId])
203246
orgSummaries.add(summary)

0 commit comments

Comments
 (0)