@@ -9,13 +9,15 @@ import io.airbyte.api.model.generated.ListOrganizationSummariesRequestBody
9
9
import io.airbyte.api.model.generated.ListOrganizationSummariesResponse
10
10
import io.airbyte.api.model.generated.ListOrganizationsByUserRequestBody
11
11
import io.airbyte.api.model.generated.ListWorkspacesByUserRequestBody
12
+ import io.airbyte.api.model.generated.ListWorkspacesInOrganizationRequestBody
12
13
import io.airbyte.api.model.generated.OrganizationCreateRequestBody
13
14
import io.airbyte.api.model.generated.OrganizationIdRequestBody
14
15
import io.airbyte.api.model.generated.OrganizationInfoRead
15
16
import io.airbyte.api.model.generated.OrganizationRead
16
17
import io.airbyte.api.model.generated.OrganizationReadList
17
18
import io.airbyte.api.model.generated.OrganizationSummary
18
19
import io.airbyte.api.model.generated.OrganizationUpdateRequestBody
20
+ import io.airbyte.api.model.generated.Pagination
19
21
import io.airbyte.api.model.generated.WorkspaceRead
20
22
import io.airbyte.api.model.generated.WorkspaceReadList
21
23
import io.airbyte.config.ConfigNotFoundType
@@ -148,6 +150,25 @@ open class OrganizationsHandler(
148
150
return OrganizationReadList ().organizations(organizationReadList)
149
151
}
150
152
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
+ */
151
172
@Trace
152
173
fun getOrganizationSummaries (request : ListOrganizationSummariesRequestBody ): ListOrganizationSummariesResponse {
153
174
val orgListReq =
@@ -187,17 +208,39 @@ open class OrganizationsHandler(
187
208
)
188
209
val orgIdToMemberCount = memberCounts.associate { it.organizationId to it.count }
189
210
190
- val orgIdToWorkspace = mutableMapOf<UUID , MutableList <WorkspaceRead >>()
211
+ val orgIdToWorkspaceMap = mutableMapOf<UUID , MutableList <WorkspaceRead >>()
191
212
for (workspace in workspaceListResp.workspaces) {
192
- orgIdToWorkspace .getOrPut(workspace.organizationId) { mutableListOf () }.add(workspace)
213
+ orgIdToWorkspaceMap .getOrPut(workspace.organizationId) { mutableListOf () }.add(workspace)
193
214
}
194
215
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
+
195
238
val orgSummaries = mutableListOf<OrganizationSummary >()
196
239
for (org in orgListResp.organizations) {
197
240
val summary =
198
241
OrganizationSummary ()
199
242
.organization(org)
200
- .workspaces(orgIdToWorkspace [org.organizationId])
243
+ .workspaces(fullyPopulatedOrgMap [org.organizationId])
201
244
.subscription(null ) // will be filled in by the caller when we are in cloud
202
245
.memberCount(orgIdToMemberCount[org.organizationId])
203
246
orgSummaries.add(summary)
0 commit comments