mirror of https://github.com/minio/minio.git
use singleflight when bucket metadata is reloaded() (#20216)
this allows for de-duplicating the callers when called concurrently, allowing for bucketmetadata reads to be single call. All concurrent callers will get the same data as the first one.
This commit is contained in:
parent
e3eb5c1328
commit
dea9abed29
|
@ -39,6 +39,7 @@ import (
|
||||||
"github.com/minio/minio/internal/logger"
|
"github.com/minio/minio/internal/logger"
|
||||||
"github.com/minio/pkg/v3/policy"
|
"github.com/minio/pkg/v3/policy"
|
||||||
"github.com/minio/pkg/v3/sync/errgroup"
|
"github.com/minio/pkg/v3/sync/errgroup"
|
||||||
|
"golang.org/x/sync/singleflight"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BucketMetadataSys captures all bucket metadata for a given cluster.
|
// BucketMetadataSys captures all bucket metadata for a given cluster.
|
||||||
|
@ -47,6 +48,7 @@ type BucketMetadataSys struct {
|
||||||
|
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
initialized bool
|
initialized bool
|
||||||
|
group *singleflight.Group
|
||||||
metadataMap map[string]BucketMetadata
|
metadataMap map[string]BucketMetadata
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +64,7 @@ func (sys *BucketMetadataSys) Count() int {
|
||||||
func (sys *BucketMetadataSys) Remove(buckets ...string) {
|
func (sys *BucketMetadataSys) Remove(buckets ...string) {
|
||||||
sys.Lock()
|
sys.Lock()
|
||||||
for _, bucket := range buckets {
|
for _, bucket := range buckets {
|
||||||
|
sys.group.Forget(bucket)
|
||||||
delete(sys.metadataMap, bucket)
|
delete(sys.metadataMap, bucket)
|
||||||
globalBucketMonitor.DeleteBucket(bucket)
|
globalBucketMonitor.DeleteBucket(bucket)
|
||||||
}
|
}
|
||||||
|
@ -154,8 +157,7 @@ func (sys *BucketMetadataSys) updateAndParse(ctx context.Context, bucket string,
|
||||||
return updatedAt, fmt.Errorf("Unknown bucket %s metadata update requested %s", bucket, configFile)
|
return updatedAt, fmt.Errorf("Unknown bucket %s metadata update requested %s", bucket, configFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = sys.save(ctx, meta)
|
return updatedAt, sys.save(ctx, meta)
|
||||||
return updatedAt, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sys *BucketMetadataSys) save(ctx context.Context, meta BucketMetadata) error {
|
func (sys *BucketMetadataSys) save(ctx context.Context, meta BucketMetadata) error {
|
||||||
|
@ -451,13 +453,20 @@ func (sys *BucketMetadataSys) GetConfig(ctx context.Context, bucket string) (met
|
||||||
if ok {
|
if ok {
|
||||||
return meta, reloaded, nil
|
return meta, reloaded, nil
|
||||||
}
|
}
|
||||||
meta, err = loadBucketMetadata(ctx, objAPI, bucket)
|
|
||||||
if err != nil {
|
val, err, _ := sys.group.Do(bucket, func() (val interface{}, err error) {
|
||||||
if !sys.Initialized() {
|
meta, err = loadBucketMetadata(ctx, objAPI, bucket)
|
||||||
// bucket metadata not yet initialized
|
if err != nil {
|
||||||
return newBucketMetadata(bucket), reloaded, errBucketMetadataNotInitialized
|
if !sys.Initialized() {
|
||||||
|
// bucket metadata not yet initialized
|
||||||
|
return newBucketMetadata(bucket), errBucketMetadataNotInitialized
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return meta, reloaded, err
|
return meta, err
|
||||||
|
})
|
||||||
|
meta, _ = val.(BucketMetadata)
|
||||||
|
if err != nil {
|
||||||
|
return meta, false, err
|
||||||
}
|
}
|
||||||
sys.Lock()
|
sys.Lock()
|
||||||
sys.metadataMap[bucket] = meta
|
sys.metadataMap[bucket] = meta
|
||||||
|
@ -630,5 +639,6 @@ func (sys *BucketMetadataSys) Reset() {
|
||||||
func NewBucketMetadataSys() *BucketMetadataSys {
|
func NewBucketMetadataSys() *BucketMetadataSys {
|
||||||
return &BucketMetadataSys{
|
return &BucketMetadataSys{
|
||||||
metadataMap: make(map[string]BucketMetadata),
|
metadataMap: make(map[string]BucketMetadata),
|
||||||
|
group: &singleflight.Group{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue