Skip to content

Commit

Permalink
Merge pull request #12 from mgtv-tech/perf_mget
Browse files Browse the repository at this point in the history
perf: mget with singleflight
  • Loading branch information
daoshenzzg authored Jun 18, 2024
2 parents 4ecb73f + 5dcd3c2 commit 55bcf9c
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 50 deletions.
109 changes: 62 additions & 47 deletions cachegeneric.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,22 @@ package cache
import (
"bytes"
"context"
"fmt"
"sort"

"golang.org/x/exp/constraints"

"github.com/mgtv-tech/jetcache-go/logger"
"github.com/mgtv-tech/jetcache-go/util"
)

// T wrap Cache to support golang's generics
type T[K comparable, V any] struct {
type T[K constraints.Ordered, V any] struct {
Cache
}

// NewT new a T
func NewT[K comparable, V any](cache Cache) *T[K, V] {
func NewT[K constraints.Ordered, V any](cache Cache) *T[K, V] {
return &T[K, V]{cache}
}

Expand All @@ -26,64 +30,75 @@ func (w *T[K, V]) MGet(ctx context.Context, key string, ids []K, fn func(context
values, missIds := w.mGetCache(ctx, key, ids)

if len(missIds) > 0 && fn != nil {
c.statsHandler.IncrQuery()
sort.Slice(missIds, func(i, j int) bool {
return missIds[i] < missIds[j]
})
v, err, _ := c.group.Do(fmt.Sprintf("%v", missIds), func() (interface{}, error) {
c.statsHandler.IncrQuery()
v, err := fn(ctx, missIds)
if err != nil {
c.statsHandler.IncrQueryFail(err)
}
return v, err
})

fnValues, err := fn(ctx, missIds)
if err != nil {
c.statsHandler.IncrQueryFail(err)
} else {
placeholderValues := make(map[string]any, len(ids))
cacheValues := make(map[string]any, len(ids))
for rk, rv := range fnValues {
values[rk] = rv
cacheKey := util.JoinAny(":", key, rk)
if b, err := c.Marshal(rv); err != nil {
placeholderValues[cacheKey] = notFoundPlaceholder
logger.Warn("MGet#w.Marshal(%v) error(%v)", rv, err)
} else {
cacheValues[cacheKey] = b
}
return values
}

fnValues := v.(map[K]V)

placeholderValues := make(map[string]any, len(ids))
cacheValues := make(map[string]any, len(ids))
for rk, rv := range fnValues {
values[rk] = rv
cacheKey := util.JoinAny(":", key, rk)
if b, err := c.Marshal(rv); err != nil {
placeholderValues[cacheKey] = notFoundPlaceholder
logger.Warn("MGet#w.Marshal(%v) error(%v)", rv, err)
} else {
cacheValues[cacheKey] = b
}
}

for _, missId := range missIds {
if _, ok := values[missId]; !ok {
cacheKey := util.JoinAny(":", key, missId)
placeholderValues[cacheKey] = notFoundPlaceholder
}
for _, missId := range missIds {
if _, ok := values[missId]; !ok {
cacheKey := util.JoinAny(":", key, missId)
placeholderValues[cacheKey] = notFoundPlaceholder
}
}

if c.local != nil {
if len(placeholderValues) > 0 {
for key, value := range placeholderValues {
c.local.Set(key, value.([]byte))
}
if c.local != nil {
if len(placeholderValues) > 0 {
for key, value := range placeholderValues {
c.local.Set(key, value.([]byte))
}
if len(cacheValues) > 0 {
for key, value := range cacheValues {
c.local.Set(key, value.([]byte))
}
}
if len(cacheValues) > 0 {
for key, value := range cacheValues {
c.local.Set(key, value.([]byte))
}
}
}

if c.remote != nil {
if len(placeholderValues) > 0 {
if err = c.remote.MSet(ctx, placeholderValues, c.notFoundExpiry); err != nil {
logger.Warn("MGet#remote.MSet error(%v)", err)
}
if c.remote != nil {
if len(placeholderValues) > 0 {
if err = c.remote.MSet(ctx, placeholderValues, c.notFoundExpiry); err != nil {
logger.Warn("MGet#remote.MSet error(%v)", err)
}
if len(cacheValues) > 0 {
if err = c.remote.MSet(ctx, cacheValues, c.remoteExpiry); err != nil {
logger.Warn("MGet#remote.MSet error(%v)", err)
}
}
if len(cacheValues) > 0 {
if err = c.remote.MSet(ctx, cacheValues, c.remoteExpiry); err != nil {
logger.Warn("MGet#remote.MSet error(%v)", err)
}
if c.isSyncLocal() {
cacheKeys := make([]string, 0, len(missIds))
for _, missId := range missIds {
cacheKey := util.JoinAny(":", key, missId)
cacheKeys = append(cacheKeys, cacheKey)
}
c.send(EventTypeSetByMGet, cacheKeys...)
}
if c.isSyncLocal() {
cacheKeys := make([]string, 0, len(missIds))
for _, missId := range missIds {
cacheKey := util.JoinAny(":", key, missId)
cacheKeys = append(cacheKeys, cacheKey)
}
c.send(EventTypeSetByMGet, cacheKeys...)
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ require (
github.com/stretchr/testify v1.8.2
github.com/vmihailenco/go-tinylfu v0.2.2
github.com/vmihailenco/msgpack/v5 v5.3.5
golang.org/x/sync v0.3.0
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8
golang.org/x/sync v0.7.0
)

require (
Expand Down
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUu
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY=
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
Expand All @@ -109,8 +111,8 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand Down

0 comments on commit 55bcf9c

Please sign in to comment.