@@ -2726,54 +2726,40 @@ func handleCallTool(params CallToolParams) CallToolResult {
27262726 resourcesList = []interface {}{}
27272727 }
27282728
2729- // Extract sourceWorkspaceIds from resourceLineage (which is an ARRAY inside metadata)
2730- sourceWorkspaceIds := make (map [string ]bool )
2731- for _ , r := range resourcesList {
2732- resource , ok := r .(map [string ]interface {})
2733- if ! ok {
2734- continue
2735- }
2736- metadata , ok := resource ["metadata" ].(map [string ]interface {})
2737- if ! ok {
2738- continue
2739- }
2740- // resourceLineage is an array inside metadata
2741- if lineageArray , ok := metadata ["resourceLineage" ].([]interface {}); ok && len (lineageArray ) > 0 {
2742- if firstLineage , ok := lineageArray [0 ].(map [string ]interface {}); ok {
2743- if sourceId , ok := firstLineage ["sourceWorkspaceId" ].(string ); ok && sourceId != "" {
2744- sourceWorkspaceIds [sourceId ] = true
2745- }
2746- }
2747- }
2729+ // Build a UUID → display name map with a single batch API call.
2730+ // This avoids the N+1 sequential lookups (one per collection) that caused timeouts.
2731+ collectionNames := make (map [string ]string ) // uuid → display name
2732+ batchBody := map [string ]interface {}{
2733+ "limit" : 1000 ,
2734+ "offset" : 0 ,
2735+ "properties" : []map [string ]string {
2736+ {"key" : "terra-type" , "value" : "data-collection" },
2737+ },
27482738 }
2749-
2750- // Look up each source workspace to get the data collection name
2751- dataCollectionNames := make ( map [ string ] string ) // sourceWorkspaceId -> display name
2752- for sourceId := range sourceWorkspaceIds {
2753- // Use API to get workspace details
2754- wsUrl := fmt . Sprintf ( "%s/api/workspaces/v1/%s" , workspaceBaseURL , sourceId )
2755- wsResp , wsErr := makeAPIRequest ( "GET" , wsUrl , nil )
2756- if wsErr == nil {
2757- var wsInfo map [ string ] interface { }
2758- if json . Unmarshal ( wsResp , & wsInfo ) == nil {
2759- // Try to get display name, fall back to id
2760- if displayName , ok := wsInfo [ "displayName" ].( string ); ok && displayName ! = "" {
2761- dataCollectionNames [ sourceId ] = displayName
2762- } else if userFacingId , ok := wsInfo [ "userFacingId" ].( string ); ok && userFacingId != "" {
2763- dataCollectionNames [ sourceId ] = userFacingId
2764- } else {
2765- dataCollectionNames [ sourceId ] = sourceId
2739+ if batchResp , batchErr := makeAPIRequest ( "POST" , workspaceBaseURL + "/api/workspaces/v2/filtered" , batchBody ); batchErr == nil {
2740+ var batchData map [ string ] interface {}
2741+ if json . Unmarshal ( batchResp , & batchData ) == nil {
2742+ if wsList , ok := batchData [ "workspaces" ].([] interface {}); ok {
2743+ for _ , w := range wsList {
2744+ ws , ok := w .( map [ string ] interface {} )
2745+ if ! ok {
2746+ continue
2747+ }
2748+ uuid , _ := ws [ "id" ].( string )
2749+ displayName , _ := ws [ "displayName" ].( string )
2750+ if displayName = = "" {
2751+ displayName , _ = ws [ "userFacingId" ].( string )
2752+ }
2753+ if uuid != "" && displayName != "" {
2754+ collectionNames [ uuid ] = displayName
2755+ }
27662756 }
2767- } else {
2768- dataCollectionNames [sourceId ] = sourceId
27692757 }
2770- } else {
2771- // If we can't access the source workspace, use the ID
2772- dataCollectionNames [sourceId ] = sourceId + " (inaccessible)"
27732758 }
27742759 }
2760+ // Fall back gracefully: if the batch call fails, groups will be keyed by UUID
27752761
2776- // Group resources by data collection ( using resourceLineage array inside metadata)
2762+ // Group resources by data collection, using display name where available
27772763 dataCollections := make (map [string ]map [string ]interface {})
27782764 localResources := []map [string ]interface {}{}
27792765
@@ -2819,17 +2805,20 @@ func handleCallTool(params CallToolParams) CallToolResult {
28192805 }
28202806 }
28212807
2822- // Group by data collection or mark as local
2808+ // Group by display name (falling back to UUID if name not resolved)
28232809 if sourceId != "" {
2824- collectionName := dataCollectionNames [sourceId ]
2825- if dataCollections [collectionName ] == nil {
2826- dataCollections [collectionName ] = map [string ]interface {}{
2810+ groupKey := collectionNames [sourceId ]
2811+ if groupKey == "" {
2812+ groupKey = sourceId
2813+ }
2814+ if dataCollections [groupKey ] == nil {
2815+ dataCollections [groupKey ] = map [string ]interface {}{
28272816 "sourceWorkspaceId" : sourceId ,
28282817 "resources" : []map [string ]interface {}{},
28292818 }
28302819 }
2831- resList := dataCollections [collectionName ]["resources" ].([]map [string ]interface {})
2832- dataCollections [collectionName ]["resources" ] = append (resList , resourceInfo )
2820+ resList := dataCollections [groupKey ]["resources" ].([]map [string ]interface {})
2821+ dataCollections [groupKey ]["resources" ] = append (resList , resourceInfo )
28332822 } else {
28342823 localResources = append (localResources , resourceInfo )
28352824 }
0 commit comments