From 3094531b632d5bb4d89d422f6cabe7082847a50e Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Thu, 25 Jan 2024 15:02:32 +0300 Subject: [PATCH] Folders: Optimize shared folders listing (#81245) * Folders: Expose function for getting all org folders with specific UIDs * lint * Fix test * fixup * Apply suggestion from code review * Remove changes in alerting scheduler * fixup * fixup after merge with main * Add batching * Use strings.Builder * Return all org folders if UIDs is empty * Filter out not accessible folders by the user * Remove comment * Fix batching when count is zero * Do not include dashboard permissions * Add some tests * fix test * Use batch request for folders * Use batch request to deduplicate folders * Refactor * Fix after merging main * Refactor --------- Co-authored-by: Sofia Papagiannaki <1632407+papagian@users.noreply.github.com> --- pkg/services/folder/folderimpl/folder.go | 28 ++++++++++++++++-------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/pkg/services/folder/folderimpl/folder.go b/pkg/services/folder/folderimpl/folder.go index c48287a446a..8db17f447ca 100644 --- a/pkg/services/folder/folderimpl/folder.go +++ b/pkg/services/folder/folderimpl/folder.go @@ -370,7 +370,8 @@ func (s *Service) GetSharedWithMe(ctx context.Context, q *folder.GetChildrenQuer s.metrics.sharedWithMeFetchFoldersRequestsDuration.WithLabelValues("failure").Observe(time.Since(start).Seconds()) return nil, folder.ErrInternal.Errorf("failed to fetch root folders to which the user has access: %w", err) } - availableNonRootFolders = s.deduplicateAvailableFolders(ctx, availableNonRootFolders, rootFolders) + + availableNonRootFolders = s.deduplicateAvailableFolders(ctx, availableNonRootFolders, rootFolders, q.OrgID) s.metrics.sharedWithMeFetchFoldersRequestsDuration.WithLabelValues("success").Observe(time.Since(start).Seconds()) return availableNonRootFolders, nil } @@ -393,7 +394,12 @@ func (s *Service) getAvailableNonRootFolders(ctx context.Context, orgID int64, u return nonRootFolders, nil } - dashFolders, err := s.store.GetFolders(ctx, NewGetFoldersQuery(folder.GetFoldersQuery{OrgID: orgID, UIDs: folderUids})) + dashFolders, err := s.GetFolders(ctx, folder.GetFoldersQuery{ + UIDs: folderUids, + OrgID: orgID, + SignedInUser: user, + WithFullpathUIDs: true, + }) if err != nil { return nil, folder.ErrInternal.Errorf("failed to fetch subfolders: %w", err) } @@ -407,24 +413,28 @@ func (s *Service) getAvailableNonRootFolders(ctx context.Context, orgID int64, u return nonRootFolders, nil } -func (s *Service) deduplicateAvailableFolders(ctx context.Context, folders []*folder.Folder, rootFolders []*folder.Folder) []*folder.Folder { +func (s *Service) deduplicateAvailableFolders(ctx context.Context, folders []*folder.Folder, rootFolders []*folder.Folder, orgID int64) []*folder.Folder { allFolders := append(folders, rootFolders...) foldersDedup := make([]*folder.Folder, 0) + for _, f := range folders { isSubfolder := slices.ContainsFunc(allFolders, func(folder *folder.Folder) bool { return f.ParentUID == folder.UID }) if !isSubfolder { - parents, err := s.GetParents(ctx, folder.GetParentsQuery{UID: f.UID, OrgID: f.OrgID}) - if err != nil { - s.log.Error("failed to fetch folder parents", "uid", f.UID, "error", err) - continue + // Get parents UIDs + parentUIDs := make([]string, 0) + pathUIDs := strings.Split(f.FullpathUIDs, "/") + for _, p := range pathUIDs { + if p != "" && p != f.UID { + parentUIDs = append(parentUIDs, p) + } } - for _, parent := range parents { + for _, parentUID := range parentUIDs { contains := slices.ContainsFunc(allFolders, func(f *folder.Folder) bool { - return f.UID == parent.UID + return f.UID == parentUID }) if contains { isSubfolder = true