mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
AuthZ Service: Use singleflight group to fetch and build the folder tree (#98299)
* AuthZ Service: Use singleflight group to fetch and build the folder tree * Change the sfgroup key * Future proof
This commit is contained in:
parent
24bf337c56
commit
55f8be62a1
@ -8,6 +8,7 @@ import (
|
||||
|
||||
authzv1 "github.com/grafana/authlib/authz/proto/v1"
|
||||
"github.com/grafana/authlib/claims"
|
||||
"golang.org/x/sync/singleflight"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
@ -49,6 +50,9 @@ type Service struct {
|
||||
teamCache *localcache.CacheService
|
||||
basicRoleCache *localcache.CacheService
|
||||
folderCache *localcache.CacheService
|
||||
|
||||
// Deduplication of concurrent requests
|
||||
sf *singleflight.Group
|
||||
}
|
||||
|
||||
func NewService(sql legacysql.LegacyDatabaseProvider, identityStore legacy.LegacyIdentityStore, logger log.Logger, tracer tracing.Tracer) *Service {
|
||||
@ -63,6 +67,7 @@ func NewService(sql legacysql.LegacyDatabaseProvider, identityStore legacy.Legac
|
||||
teamCache: localcache.New(shortCacheTTL, shortCleanupInterval),
|
||||
basicRoleCache: localcache.New(longCacheTTL, longCleanupInterval),
|
||||
folderCache: localcache.New(shortCacheTTL, shortCleanupInterval),
|
||||
sf: new(singleflight.Group),
|
||||
}
|
||||
}
|
||||
|
||||
@ -339,38 +344,45 @@ func (s *Service) buildFolderTree(ctx context.Context, ns claims.NamespaceInfo)
|
||||
return cached.(map[string]FolderNode), nil
|
||||
}
|
||||
|
||||
folders, err := s.store.GetFolders(ctx, ns)
|
||||
res, err, _ := s.sf.Do(ns.Value+"_buildFolderTree", func() (interface{}, error) {
|
||||
folders, err := s.store.GetFolders(ctx, ns)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get folders: %w", err)
|
||||
}
|
||||
|
||||
folderMap := make(map[string]FolderNode, len(folders))
|
||||
for _, folder := range folders {
|
||||
if node, has := folderMap[folder.UID]; !has {
|
||||
folderMap[folder.UID] = FolderNode{
|
||||
uid: folder.UID,
|
||||
parentUID: folder.ParentUID,
|
||||
}
|
||||
} else {
|
||||
node.parentUID = folder.ParentUID
|
||||
folderMap[folder.UID] = node
|
||||
}
|
||||
// Register that the parent has this child node
|
||||
if folder.ParentUID == nil {
|
||||
continue
|
||||
}
|
||||
if parent, has := folderMap[*folder.ParentUID]; has {
|
||||
parent.childrenUIDs = append(parent.childrenUIDs, folder.UID)
|
||||
folderMap[*folder.ParentUID] = parent
|
||||
} else {
|
||||
folderMap[*folder.ParentUID] = FolderNode{
|
||||
uid: *folder.ParentUID,
|
||||
childrenUIDs: []string{folder.UID},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s.folderCache.Set(key, folderMap, 0)
|
||||
return folderMap, nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get folders: %w", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
folderMap := make(map[string]FolderNode, len(folders))
|
||||
for _, folder := range folders {
|
||||
if node, has := folderMap[folder.UID]; !has {
|
||||
folderMap[folder.UID] = FolderNode{
|
||||
uid: folder.UID,
|
||||
parentUID: folder.ParentUID,
|
||||
}
|
||||
} else {
|
||||
node.parentUID = folder.ParentUID
|
||||
folderMap[folder.UID] = node
|
||||
}
|
||||
// Register that the parent has this child node
|
||||
if folder.ParentUID == nil {
|
||||
continue
|
||||
}
|
||||
if parent, has := folderMap[*folder.ParentUID]; has {
|
||||
parent.childrenUIDs = append(parent.childrenUIDs, folder.UID)
|
||||
folderMap[*folder.ParentUID] = parent
|
||||
} else {
|
||||
folderMap[*folder.ParentUID] = FolderNode{
|
||||
uid: *folder.ParentUID,
|
||||
childrenUIDs: []string{folder.UID},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s.folderCache.Set(key, folderMap, 0)
|
||||
|
||||
return folderMap, nil
|
||||
return res.(map[string]FolderNode), nil
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"github.com/grafana/authlib/claims"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/sync/singleflight"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/localcache"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
@ -438,6 +439,7 @@ func TestService_buildFolderTree(t *testing.T) {
|
||||
store: store,
|
||||
folderCache: cacheService,
|
||||
logger: log.New("test"),
|
||||
sf: new(singleflight.Group),
|
||||
}
|
||||
|
||||
tree, err := s.buildFolderTree(ctx, ns)
|
||||
|
Loading…
Reference in New Issue
Block a user