Use singleflight in localCache.load (#21606)

Signed-off-by: Congqi Xia <congqi.xia@zilliz.com>
This commit is contained in:
congqixia 2023-01-10 16:21:39 +08:00 committed by GitHub
parent 3b41a6931d
commit c550427e81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 24 additions and 12 deletions

View File

@ -19,7 +19,7 @@ linters:
- gosimple - gosimple
- gosec - gosec
- revive - revive
- gocritic # - gocritic
linters-settings: linters-settings:
misspell: misspell:

View File

@ -18,11 +18,13 @@ package cache
import ( import (
"errors" "errors"
"fmt"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
"go.uber.org/zap" "go.uber.org/zap"
"golang.org/x/sync/singleflight"
"github.com/milvus-io/milvus/internal/log" "github.com/milvus-io/milvus/internal/log"
) )
@ -55,6 +57,7 @@ type localCache[K comparable, V any] struct {
onInsertion Func[K, V] onInsertion Func[K, V]
onRemoval Func[K, V] onRemoval Func[K, V]
singleflight singleflight.Group
loader LoaderFunc[K, V] loader LoaderFunc[K, V]
getPreLoadData GetPreLoadDataFunc[K, V] getPreLoadData GetPreLoadDataFunc[K, V]
@ -345,20 +348,29 @@ func (c *localCache[K, V]) load(k K) (v V, err error) {
var ret V var ret V
return ret, errors.New("cache loader function must be set") return ret, errors.New("cache loader function must be set")
} }
// TODO: Poll the value instead when the entry is loading.
start := currentTime() // use singleflight here
v, err = c.loader(k) val, err, _ := c.singleflight.Do(fmt.Sprintf("%v", k), func() (any, error) {
now := currentTime() start := currentTime()
loadTime := now.Sub(start) v, err := c.loader(k)
now := currentTime()
loadTime := now.Sub(start)
if err != nil {
c.stats.RecordLoadError(loadTime)
return v, err
}
c.stats.RecordLoadSuccess(loadTime)
en := newEntry(k, v, sum(k))
c.setEntryWriteTime(en, now)
c.setEntryAccessTime(en, now)
c.sendEvent(eventWrite, en)
return v, err
})
if err != nil { if err != nil {
c.stats.RecordLoadError(loadTime)
return v, err return v, err
} }
c.stats.RecordLoadSuccess(loadTime) v = val.(V)
en := newEntry(k, v, sum(k))
c.setEntryWriteTime(en, now)
c.setEntryAccessTime(en, now)
c.sendEvent(eventWrite, en)
return v, nil return v, nil
} }