Use singleflight in localCache.load (#21606)

Signed-off-by: Congqi Xia <congqi.xia@zilliz.com>
pull/21620/head
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
- gosec
- revive
- gocritic
# - gocritic
linters-settings:
misspell:

View File

@ -18,11 +18,13 @@ package cache
import (
"errors"
"fmt"
"sync"
"sync/atomic"
"time"
"go.uber.org/zap"
"golang.org/x/sync/singleflight"
"github.com/milvus-io/milvus/internal/log"
)
@ -55,6 +57,7 @@ type localCache[K comparable, V any] struct {
onInsertion Func[K, V]
onRemoval Func[K, V]
singleflight singleflight.Group
loader LoaderFunc[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
return ret, errors.New("cache loader function must be set")
}
// TODO: Poll the value instead when the entry is loading.
start := currentTime()
v, err = c.loader(k)
now := currentTime()
loadTime := now.Sub(start)
// use singleflight here
val, err, _ := c.singleflight.Do(fmt.Sprintf("%v", k), func() (any, error) {
start := currentTime()
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 {
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)
v = val.(V)
return v, nil
}