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