parent
1d54c61b8c
commit
326dc3836c
@ -0,0 +1,87 @@
|
||||
package redis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/dtm-labs/rockscache"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"golang.org/x/sync/singleflight"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func getRocksCacheRedisClient(cli *rockscache.Client) redis.UniversalClient {
|
||||
type Client struct {
|
||||
rdb redis.UniversalClient
|
||||
_ rockscache.Options
|
||||
_ singleflight.Group
|
||||
}
|
||||
return (*Client)(unsafe.Pointer(cli)).rdb
|
||||
}
|
||||
|
||||
func batchGetCache2[K comparable, V any](ctx context.Context, rcClient *rockscache.Client, expire time.Duration, ids []K, idKey func(id K) string, vId func(v V) K, fn func(ctx context.Context, ids []K) ([]V, error)) ([]V, error) {
|
||||
if len(ids) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
findKeys := make([]string, 0, len(ids))
|
||||
keyId := make(map[string]K)
|
||||
for _, id := range ids {
|
||||
key := idKey(id)
|
||||
if _, ok := keyId[key]; ok {
|
||||
continue
|
||||
}
|
||||
keyId[key] = id
|
||||
findKeys = append(findKeys, key)
|
||||
}
|
||||
slotKeys, err := groupKeysBySlot(ctx, getRocksCacheRedisClient(rcClient), findKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := make([]V, 0, len(findKeys))
|
||||
for _, keys := range slotKeys {
|
||||
indexCache, err := rcClient.FetchBatch2(ctx, keys, expire, func(idx []int) (map[int]string, error) {
|
||||
queryIds := make([]K, 0, len(idx))
|
||||
idIndex := make(map[K]int)
|
||||
for _, index := range idx {
|
||||
id := keyId[keys[index]]
|
||||
idIndex[id] = index
|
||||
queryIds = append(queryIds, id)
|
||||
}
|
||||
values, err := fn(ctx, queryIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(values) == 0 {
|
||||
return map[int]string{}, nil
|
||||
}
|
||||
cacheIndex := make(map[int]string)
|
||||
for _, value := range values {
|
||||
id := vId(value)
|
||||
index, ok := idIndex[id]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
bs, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cacheIndex[index] = string(bs)
|
||||
}
|
||||
return cacheIndex, nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, data := range indexCache {
|
||||
if data == "" {
|
||||
continue
|
||||
}
|
||||
var value V
|
||||
if err := json.Unmarshal([]byte(data), &value); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result = append(result, value)
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package redis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/dtm-labs/rockscache"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database/mgo"
|
||||
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
|
||||
"github.com/openimsdk/tools/db/mongoutil"
|
||||
"github.com/openimsdk/tools/db/redisutil"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestName(t *testing.T) {
|
||||
//var rocks rockscache.Client
|
||||
//rdb := getRocksCacheRedisClient(&rocks)
|
||||
//t.Log(rdb == nil)
|
||||
|
||||
ctx := context.Background()
|
||||
rdb, err := redisutil.NewRedisClient(ctx, (&config.Redis{
|
||||
Address: []string{"172.16.8.48:16379"},
|
||||
Password: "openIM123",
|
||||
DB: 3,
|
||||
}).Build())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
mgocli, err := mongoutil.NewMongoDB(ctx, (&config.Mongo{
|
||||
Address: []string{"172.16.8.48:37017"},
|
||||
Database: "openim_v3",
|
||||
Username: "openIM",
|
||||
Password: "openIM123",
|
||||
MaxPoolSize: 100,
|
||||
MaxRetry: 1,
|
||||
}).Build())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
userMgo, err := mgo.NewUserMongo(mgocli.GetDB())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
rock := rockscache.NewClient(rdb, rockscache.NewDefaultOptions())
|
||||
//var keys []string
|
||||
//for i := 1; i <= 10; i++ {
|
||||
// keys = append(keys, fmt.Sprintf("test%d", i))
|
||||
//}
|
||||
//res, err := cli.FetchBatch2(ctx, keys, time.Hour, func(idx []int) (map[int]string, error) {
|
||||
// t.Log("FetchBatch2=>", idx)
|
||||
// time.Sleep(time.Second * 1)
|
||||
// res := make(map[int]string)
|
||||
// for _, i := range idx {
|
||||
// res[i] = fmt.Sprintf("hello_%d", i)
|
||||
// }
|
||||
// t.Log("FetchBatch2=>", res)
|
||||
// return res, nil
|
||||
//})
|
||||
//if err != nil {
|
||||
// t.Log(err)
|
||||
// return
|
||||
//}
|
||||
//t.Log(res)
|
||||
|
||||
userIDs := []string{"1814217053", "2110910952", "1234567890"}
|
||||
|
||||
res, err := batchGetCache2(ctx, rock, time.Hour, userIDs, func(id string) string {
|
||||
return "TEST_USER:" + id
|
||||
}, func(v *model.User) string {
|
||||
return v.UserID
|
||||
}, func(ctx context.Context, ids []string) ([]*model.User, error) {
|
||||
t.Log("find mongo", ids)
|
||||
return userMgo.Find(ctx, ids)
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
t.Log("==>", res)
|
||||
}
|
Loading…
Reference in new issue