diff --git a/packages/server/dataloader/azureDevOpsLoaders.ts b/packages/server/dataloader/azureDevOpsLoaders.ts index e9fb91d6df6..3bf4e889b3f 100644 --- a/packages/server/dataloader/azureDevOpsLoaders.ts +++ b/packages/server/dataloader/azureDevOpsLoaders.ts @@ -226,11 +226,11 @@ export const azureDevOpsAllWorkItems = ( workItems.map(async (returnedWorkItem): Promise => { const instanceId = getInstanceId(new URL(returnedWorkItem.url)) const mappedWorkItem = await getMappedAzureDevOpsWorkItem( - manager, userId, teamId, instanceId, - returnedWorkItem + returnedWorkItem, + parent ) return mappedWorkItem }) @@ -483,11 +483,11 @@ export const azureDevOpsUserStory = ( } else { const returnedWorkItem: WorkItem = workItems[0] const azureDevOpsWorkItem = await getMappedAzureDevOpsWorkItem( - manager, userId, teamId, instanceId, - returnedWorkItem + returnedWorkItem, + parent ) return azureDevOpsWorkItem } @@ -530,11 +530,11 @@ export const azureDevOpsWorkItem = ( if (returnedWorkItems.length !== 1 || !returnedWorkItems[0]) return null const returnedWorkItem = returnedWorkItems[0] const azureDevOpsWorkItem = await getMappedAzureDevOpsWorkItem( - manager, userId, teamId, instanceId, - returnedWorkItem + returnedWorkItem, + parent ) // update our records @@ -580,12 +580,57 @@ export const azureDevOpsWorkItem = ( ) } -export const getMappedAzureDevOpsWorkItem = async ( - manager: AzureDevOpsServerManager, +export type AzureDevOpsProjectProcessTemplateKey = { + userId: string + teamId: string + instanceId: string + projectId: string +} +export type AzureDevOpsProjectProcessTemplate = { + error?: Error + projectTemplate?: string +} + +export const azureDevOpsProjectProcessTemplate = (parent: RootDataLoader) => { + return new DataLoader< + AzureDevOpsProjectProcessTemplateKey, + AzureDevOpsProjectProcessTemplate, + string + >( + async (keys) => { + const results = await Promise.allSettled( + keys.map(async ({userId, teamId, instanceId, projectId}) => { + const auth = await parent.get('freshAzureDevOpsAuth').load({teamId, userId}) + if (!auth) return null + const provider = await parent.get('integrationProviders').loadNonNull(auth.providerId) + const manager = new AzureDevOpsServerManager( + auth, + provider as IntegrationProviderAzureDevOps + ) + + return manager.getProjectProcessTemplate(instanceId, projectId) + }) + ) + return results.map((result) => + result.status === 'fulfilled' && result.value + ? result.value + : {error: new Error('Failed to get project process template')} + ) + }, + { + ...parent.dataLoaderOptions, + cacheKeyFn: ({userId, teamId, instanceId, projectId}) => + `${userId}:${teamId}:${instanceId}:${projectId}` + } + ) +} + +const getMappedAzureDevOpsWorkItem = async ( userId: string, teamId: string, instanceId: string, - returnedWorkItem: WorkItem + returnedWorkItem: WorkItem, + dataLoader: RootDataLoader ) => { const mappedUrl = returnedWorkItem._links['html']?.href ?? returnedWorkItem.url const azureDevOpsWorkItem = { @@ -603,10 +648,12 @@ export const getMappedAzureDevOpsWorkItem = async ( userId } as AzureDevOpsWorkItem - const projectResult = await manager.getProjectProcessTemplate( + const projectResult = await dataLoader.get('azureDevOpsProjectProcessTemplate').load({ + userId, + teamId, instanceId, - azureDevOpsWorkItem.teamProject - ) + projectId: azureDevOpsWorkItem.teamProject + }) const {error: projectResultError, projectTemplate} = projectResult if (!!projectResultError) { const workItemId = returnedWorkItem.id.toString() @@ -647,11 +694,11 @@ export const azureDevOpsWorkItems = ( const mappedWorkItems: AzureDevOpsWorkItem[] = await Promise.all( returnedWorkItems.map(async (returnedWorkItem): Promise => { const mappedWorkItem = await getMappedAzureDevOpsWorkItem( - manager, userId, teamId, instanceId, - returnedWorkItem + returnedWorkItem, + parent ) return mappedWorkItem }) diff --git a/packages/server/utils/AzureDevOpsServerManager.ts b/packages/server/utils/AzureDevOpsServerManager.ts index 16950351455..ff4df7c0c67 100644 --- a/packages/server/utils/AzureDevOpsServerManager.ts +++ b/packages/server/utils/AzureDevOpsServerManager.ts @@ -591,7 +591,7 @@ class AzureDevOpsServerManager implements TaskIntegrationManager { return {error: undefined, projects: teamProjectReferences} } - async getProjectProperties(instanceId: string, projectId: string) { + private async getProjectProperties(instanceId: string, projectId: string) { let firstError: Error | undefined const uri = `https://${instanceId}/_apis/projects/${projectId}/properties?keys=System.CurrentProcessTemplateId` const result = await this.get(uri)