Compare commits
2 Commits
936d033547
...
86d1616732
Author | SHA1 | Date | |
---|---|---|---|
86d1616732 | |||
2eb58f732b |
6
cache/cache.go
vendored
6
cache/cache.go
vendored
@ -15,3 +15,9 @@ type Cache[K comparable, V any] interface {
|
||||
Del(ctx context.Context, key ...K)
|
||||
ClearExpired(ctx context.Context)
|
||||
}
|
||||
|
||||
type Expend[K comparable, V any] interface {
|
||||
Gets(ctx context.Context, k []K) (map[K]V, error)
|
||||
Vers(ctx context.Context, k []K) map[K]int
|
||||
Sets(ctx context.Context, m map[K]V)
|
||||
}
|
||||
|
100
cache/map.go
vendored
100
cache/map.go
vendored
@ -14,6 +14,7 @@ type MapCache[K comparable, V any] struct {
|
||||
mux sync.Mutex
|
||||
cacheFunc MapSingleFn[K, V]
|
||||
batchCacheFn MapBatchFn[K, V]
|
||||
getCacheBatch func(c context.Context, key []K, timeout time.Duration, params ...any) ([]V, error)
|
||||
}
|
||||
|
||||
type MapSingleFn[K, V any] func(context.Context, K, ...any) (V, error)
|
||||
@ -31,6 +32,12 @@ func NewMapCache[K comparable, V any](data Cache[K, V], cacheFunc MapSingleFn[K,
|
||||
} else if batchCacheFn == nil && cacheFunc != nil {
|
||||
r.SetDefaultBatchFunc(cacheFunc)
|
||||
}
|
||||
ex, ok := any(data).(Expend[K, V])
|
||||
if !ok {
|
||||
r.getCacheBatch = r.getCacheBatchs
|
||||
} else {
|
||||
r.getCacheBatch = r.getBatches(ex)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
@ -129,6 +136,10 @@ func (m *MapCache[K, V]) GetCache(c context.Context, key K, timeout time.Duratio
|
||||
}
|
||||
|
||||
func (m *MapCache[K, V]) GetCacheBatch(c context.Context, key []K, timeout time.Duration, params ...any) ([]V, error) {
|
||||
return m.getCacheBatch(c, key, timeout, params...)
|
||||
}
|
||||
|
||||
func (m *MapCache[K, V]) getCacheBatchs(c context.Context, key []K, timeout time.Duration, params ...any) ([]V, error) {
|
||||
var res = make([]V, 0, len(key))
|
||||
var needIndex = make(map[K]int)
|
||||
var ver = make(map[K]int)
|
||||
@ -196,3 +207,92 @@ func (m *MapCache[K, V]) GetCacheBatch(c context.Context, key []K, timeout time.
|
||||
|
||||
return res, err
|
||||
}
|
||||
|
||||
func (m *MapCache[K, V]) getBatches(e Expend[K, V]) func(ctx context.Context, key []K, timeout time.Duration, params ...any) ([]V, error) {
|
||||
cc := e
|
||||
return func(ctx context.Context, key []K, timeout time.Duration, params ...any) ([]V, error) {
|
||||
var res = make([]V, 0, len(key))
|
||||
var needIndex = make(map[K]int)
|
||||
var err error
|
||||
mm, err := cc.Gets(ctx, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var flushKeys []K
|
||||
for i, k := range key {
|
||||
v, ok := mm[k]
|
||||
if !ok {
|
||||
flushKeys = append(flushKeys, k)
|
||||
needIndex[k] = i
|
||||
var vv V
|
||||
v = vv
|
||||
}
|
||||
res = append(res, v)
|
||||
}
|
||||
if len(needIndex) < 1 {
|
||||
return res, nil
|
||||
}
|
||||
vers := cc.Vers(ctx, flushKeys)
|
||||
|
||||
call := func() {
|
||||
m.mux.Lock()
|
||||
defer m.mux.Unlock()
|
||||
verss := cc.Vers(ctx, flushKeys)
|
||||
needFlushs := maps.FilterToSlice(needIndex, func(k K, v int) (K, bool) {
|
||||
vv, ok := vers[k]
|
||||
vvv, ook := verss[k]
|
||||
if !ok || !ook || vv >= vvv {
|
||||
return k, true
|
||||
}
|
||||
return k, false
|
||||
})
|
||||
|
||||
if len(needFlushs) < 1 {
|
||||
vv, er := cc.Gets(ctx, needFlushs)
|
||||
if er != nil {
|
||||
err = er
|
||||
return
|
||||
}
|
||||
for k, i := range needIndex {
|
||||
v, ok := vv[k]
|
||||
if ok {
|
||||
res[i] = v
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
r, er := m.batchCacheFn(ctx, needFlushs, params...)
|
||||
if err != nil {
|
||||
err = er
|
||||
return
|
||||
}
|
||||
cc.Sets(ctx, r)
|
||||
|
||||
for k, i := range needIndex {
|
||||
v, ok := r[k]
|
||||
if ok {
|
||||
res[i] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
if timeout > 0 {
|
||||
ctx, cancel := context.WithTimeout(ctx, timeout)
|
||||
defer cancel()
|
||||
done := make(chan struct{}, 1)
|
||||
go func() {
|
||||
call()
|
||||
done <- struct{}{}
|
||||
}()
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
err = errors.New(fmt.Sprintf("get cache %v %s", key, ctx.Err().Error()))
|
||||
case <-done:
|
||||
}
|
||||
} else {
|
||||
call()
|
||||
}
|
||||
|
||||
return res, err
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user