mirror of
				https://github.com/openimsdk/open-im-server.git
				synced 2025-11-04 19:32:17 +08:00 
			
		
		
		
	refactor: db refactor and cache key add.
This commit is contained in:
		
							parent
							
								
									285523751d
								
							
						
					
					
						commit
						25908e5157
					
				@ -12,7 +12,7 @@ services:
 | 
				
			|||||||
    container_name: mongo
 | 
					    container_name: mongo
 | 
				
			||||||
    command: ["/bin/bash", "-c", "/docker-entrypoint-initdb.d/mongo-init.sh; docker-entrypoint.sh mongod --wiredTigerCacheSizeGB 1 --auth"]
 | 
					    command: ["/bin/bash", "-c", "/docker-entrypoint-initdb.d/mongo-init.sh; docker-entrypoint.sh mongod --wiredTigerCacheSizeGB 1 --auth"]
 | 
				
			||||||
    volumes:
 | 
					    volumes:
 | 
				
			||||||
      - "${DATA_DIR}/components/mongodb/data/db:/data/db"
 | 
					      - "${DATA_DIR}/components/mongodb/data/storage:/data/storage"
 | 
				
			||||||
      - "${DATA_DIR}/components/mongodb/data/logs:/data/logs"
 | 
					      - "${DATA_DIR}/components/mongodb/data/logs:/data/logs"
 | 
				
			||||||
      - "${DATA_DIR}/components/mongodb/data/conf:/etc/mongo"
 | 
					      - "${DATA_DIR}/components/mongodb/data/conf:/etc/mongo"
 | 
				
			||||||
      - "./scripts/mongo-init.sh:/docker-entrypoint-initdb.d/mongo-init.sh:ro"
 | 
					      - "./scripts/mongo-init.sh:/docker-entrypoint-initdb.d/mongo-init.sh:ro"
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.mod
									
									
									
									
									
								
							@ -1,6 +1,6 @@
 | 
				
			|||||||
module github.com/openimsdk/open-im-server/v3
 | 
					module github.com/openimsdk/open-im-server/v3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
go 1.21.2
 | 
					go 1.20
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
	firebase.google.com/go v3.13.0+incompatible
 | 
						firebase.google.com/go v3.13.0+incompatible
 | 
				
			||||||
 | 
				
			|||||||
@ -17,6 +17,8 @@ package msgtransfer
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database/mgo"
 | 
				
			||||||
	"github.com/openimsdk/tools/db/mongoutil"
 | 
						"github.com/openimsdk/tools/db/mongoutil"
 | 
				
			||||||
	"github.com/openimsdk/tools/db/redisutil"
 | 
						"github.com/openimsdk/tools/db/redisutil"
 | 
				
			||||||
	"github.com/openimsdk/tools/utils/datautil"
 | 
						"github.com/openimsdk/tools/utils/datautil"
 | 
				
			||||||
@ -26,11 +28,9 @@ import (
 | 
				
			|||||||
	"syscall"
 | 
						"syscall"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
 | 
					 | 
				
			||||||
	kdisc "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister"
 | 
						kdisc "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
 | 
				
			||||||
	"github.com/openimsdk/tools/errs"
 | 
						"github.com/openimsdk/tools/errs"
 | 
				
			||||||
	"github.com/openimsdk/tools/log"
 | 
						"github.com/openimsdk/tools/log"
 | 
				
			||||||
@ -83,8 +83,8 @@ func Start(ctx context.Context, index int, config *Config) error {
 | 
				
			|||||||
	client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()),
 | 
						client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()),
 | 
				
			||||||
		grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, "round_robin")))
 | 
							grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, "round_robin")))
 | 
				
			||||||
	//todo MsgCacheTimeout
 | 
						//todo MsgCacheTimeout
 | 
				
			||||||
	msgModel := cache.NewMsgCache(rdb, config.RedisConfig.EnablePipeline)
 | 
						msgModel := redis.NewMsgCache(rdb, config.RedisConfig.EnablePipeline)
 | 
				
			||||||
	seqModel := cache.NewSeqCache(rdb)
 | 
						seqModel := redis.NewSeqCache(rdb)
 | 
				
			||||||
	msgDocModel, err := mgo.NewMsgMongo(mgocli.GetDB())
 | 
						msgDocModel, err := mgo.NewMsgMongo(mgocli.GetDB())
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
 | 
				
			|||||||
@ -25,7 +25,7 @@ import (
 | 
				
			|||||||
	"github.com/IBM/sarama"
 | 
						"github.com/IBM/sarama"
 | 
				
			||||||
	"github.com/go-redis/redis"
 | 
						"github.com/go-redis/redis"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
 | 
				
			||||||
	"github.com/openimsdk/protocol/constant"
 | 
						"github.com/openimsdk/protocol/constant"
 | 
				
			||||||
 | 
				
			|||||||
@ -19,8 +19,8 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"github.com/IBM/sarama"
 | 
						"github.com/IBM/sarama"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
 | 
				
			||||||
	pbmsg "github.com/openimsdk/protocol/msg"
 | 
						pbmsg "github.com/openimsdk/protocol/msg"
 | 
				
			||||||
	"github.com/openimsdk/tools/log"
 | 
						"github.com/openimsdk/tools/log"
 | 
				
			||||||
	"github.com/openimsdk/tools/mq/kafka"
 | 
						"github.com/openimsdk/tools/mq/kafka"
 | 
				
			||||||
 | 
				
			|||||||
@ -22,7 +22,7 @@ import (
 | 
				
			|||||||
	firebase "firebase.google.com/go"
 | 
						firebase "firebase.google.com/go"
 | 
				
			||||||
	"firebase.google.com/go/messaging"
 | 
						"firebase.google.com/go/messaging"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
 | 
				
			||||||
	"github.com/openimsdk/protocol/constant"
 | 
						"github.com/openimsdk/protocol/constant"
 | 
				
			||||||
	"github.com/openimsdk/tools/errs"
 | 
						"github.com/openimsdk/tools/errs"
 | 
				
			||||||
	"github.com/redis/go-redis/v9"
 | 
						"github.com/redis/go-redis/v9"
 | 
				
			||||||
 | 
				
			|||||||
@ -24,7 +24,7 @@ import (
 | 
				
			|||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
 | 
				
			||||||
	"github.com/openimsdk/tools/errs"
 | 
						"github.com/openimsdk/tools/errs"
 | 
				
			||||||
	"github.com/openimsdk/tools/log"
 | 
						"github.com/openimsdk/tools/log"
 | 
				
			||||||
	"github.com/openimsdk/tools/mcontext"
 | 
						"github.com/openimsdk/tools/mcontext"
 | 
				
			||||||
 | 
				
			|||||||
@ -22,7 +22,7 @@ import (
 | 
				
			|||||||
	"github.com/openimsdk/open-im-server/v3/internal/push/offlinepush/jpush"
 | 
						"github.com/openimsdk/open-im-server/v3/internal/push/offlinepush/jpush"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/internal/push/offlinepush/options"
 | 
						"github.com/openimsdk/open-im-server/v3/internal/push/offlinepush/options"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
 | 
				
			|||||||
@ -4,8 +4,8 @@ import (
 | 
				
			|||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/internal/push/offlinepush"
 | 
						"github.com/openimsdk/open-im-server/v3/internal/push/offlinepush"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
 | 
				
			||||||
	pbpush "github.com/openimsdk/protocol/push"
 | 
						pbpush "github.com/openimsdk/protocol/push"
 | 
				
			||||||
	"github.com/openimsdk/tools/db/redisutil"
 | 
						"github.com/openimsdk/tools/db/redisutil"
 | 
				
			||||||
	"github.com/openimsdk/tools/discovery"
 | 
						"github.com/openimsdk/tools/discovery"
 | 
				
			||||||
@ -49,7 +49,7 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	cacheModel := cache.NewThirdCache(rdb)
 | 
						cacheModel := redis.NewThirdCache(rdb)
 | 
				
			||||||
	offlinePusher, err := offlinepush.NewOfflinePusher(&config.RpcConfig, cacheModel)
 | 
						offlinePusher, err := offlinepush.NewOfflinePusher(&config.RpcConfig, cacheModel)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
 | 
				
			|||||||
@ -17,14 +17,14 @@ package auth
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
				
			||||||
 | 
						redis2 "github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis"
 | 
				
			||||||
	"github.com/openimsdk/tools/db/redisutil"
 | 
						"github.com/openimsdk/tools/db/redisutil"
 | 
				
			||||||
	"github.com/redis/go-redis/v9"
 | 
						"github.com/redis/go-redis/v9"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/authverify"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/authverify"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
 | 
				
			||||||
	pbauth "github.com/openimsdk/protocol/auth"
 | 
						pbauth "github.com/openimsdk/protocol/auth"
 | 
				
			||||||
	"github.com/openimsdk/protocol/constant"
 | 
						"github.com/openimsdk/protocol/constant"
 | 
				
			||||||
@ -61,7 +61,7 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
 | 
				
			|||||||
		userRpcClient:  &userRpcClient,
 | 
							userRpcClient:  &userRpcClient,
 | 
				
			||||||
		RegisterCenter: client,
 | 
							RegisterCenter: client,
 | 
				
			||||||
		authDatabase: controller.NewAuthDatabase(
 | 
							authDatabase: controller.NewAuthDatabase(
 | 
				
			||||||
			cache.NewTokenCacheModel(rdb),
 | 
								redis2.NewTokenCacheModel(rdb),
 | 
				
			||||||
			config.Share.Secret,
 | 
								config.Share.Secret,
 | 
				
			||||||
			config.RpcConfig.TokenPolicy.Expire,
 | 
								config.RpcConfig.TokenPolicy.Expire,
 | 
				
			||||||
		),
 | 
							),
 | 
				
			||||||
 | 
				
			|||||||
@ -17,15 +17,16 @@ package conversation
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database/mgo"
 | 
				
			||||||
 | 
						tablerelation "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/localcache"
 | 
				
			||||||
	"github.com/openimsdk/tools/db/redisutil"
 | 
						"github.com/openimsdk/tools/db/redisutil"
 | 
				
			||||||
	"sort"
 | 
						"sort"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
 | 
					 | 
				
			||||||
	tablerelation "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
 | 
				
			||||||
	"github.com/openimsdk/protocol/constant"
 | 
						"github.com/openimsdk/protocol/constant"
 | 
				
			||||||
	pbconversation "github.com/openimsdk/protocol/conversation"
 | 
						pbconversation "github.com/openimsdk/protocol/conversation"
 | 
				
			||||||
@ -73,13 +74,14 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
 | 
				
			|||||||
	groupRpcClient := rpcclient.NewGroupRpcClient(client, config.Share.RpcRegisterName.Group)
 | 
						groupRpcClient := rpcclient.NewGroupRpcClient(client, config.Share.RpcRegisterName.Group)
 | 
				
			||||||
	msgRpcClient := rpcclient.NewMessageRpcClient(client, config.Share.RpcRegisterName.Msg)
 | 
						msgRpcClient := rpcclient.NewMessageRpcClient(client, config.Share.RpcRegisterName.Msg)
 | 
				
			||||||
	userRpcClient := rpcclient.NewUserRpcClient(client, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID)
 | 
						userRpcClient := rpcclient.NewUserRpcClient(client, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID)
 | 
				
			||||||
	cache.InitLocalCache(&config.LocalCacheConfig)
 | 
						localcache.InitLocalCache(&config.LocalCacheConfig)
 | 
				
			||||||
	pbconversation.RegisterConversationServer(server, &conversationServer{
 | 
						pbconversation.RegisterConversationServer(server, &conversationServer{
 | 
				
			||||||
		msgRpcClient:                   &msgRpcClient,
 | 
							msgRpcClient:                   &msgRpcClient,
 | 
				
			||||||
		user:                           &userRpcClient,
 | 
							user:                           &userRpcClient,
 | 
				
			||||||
		conversationNotificationSender: NewConversationNotificationSender(&config.NotificationConfig, &msgRpcClient),
 | 
							conversationNotificationSender: NewConversationNotificationSender(&config.NotificationConfig, &msgRpcClient),
 | 
				
			||||||
		groupRpcClient:                 &groupRpcClient,
 | 
							groupRpcClient:                 &groupRpcClient,
 | 
				
			||||||
		conversationDatabase:           controller.NewConversationDatabase(conversationDB, cache.NewConversationRedis(rdb, &config.LocalCacheConfig, cache.GetDefaultOpt(), conversationDB), mgocli.GetTx()),
 | 
							conversationDatabase: controller.NewConversationDatabase(conversationDB,
 | 
				
			||||||
 | 
								redis.NewConversationRedis(rdb, &config.LocalCacheConfig, redis.GetRocksCacheOptions(), conversationDB), mgocli.GetTx()),
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -192,11 +194,11 @@ func (c *conversationServer) GetConversations(ctx context.Context, req *pbconver
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *conversationServer) SetConversation(ctx context.Context, req *pbconversation.SetConversationReq) (*pbconversation.SetConversationResp, error) {
 | 
					func (c *conversationServer) SetConversation(ctx context.Context, req *pbconversation.SetConversationReq) (*pbconversation.SetConversationResp, error) {
 | 
				
			||||||
	var conversation tablerelation.ConversationModel
 | 
						var conversation tablerelation.Conversation
 | 
				
			||||||
	if err := datautil.CopyStructFields(&conversation, req.Conversation); err != nil {
 | 
						if err := datautil.CopyStructFields(&conversation, req.Conversation); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	err := c.conversationDatabase.SetUserConversations(ctx, req.Conversation.OwnerUserID, []*tablerelation.ConversationModel{&conversation})
 | 
						err := c.conversationDatabase.SetUserConversations(ctx, req.Conversation.OwnerUserID, []*tablerelation.Conversation{&conversation})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -220,7 +222,7 @@ func (c *conversationServer) SetConversations(ctx context.Context, req *pbconver
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	var unequal int
 | 
						var unequal int
 | 
				
			||||||
	var conv tablerelation.ConversationModel
 | 
						var conv tablerelation.Conversation
 | 
				
			||||||
	if len(req.UserIDs) == 1 {
 | 
						if len(req.UserIDs) == 1 {
 | 
				
			||||||
		cs, err := c.conversationDatabase.FindConversations(ctx, req.UserIDs[0], []string{req.Conversation.ConversationID})
 | 
							cs, err := c.conversationDatabase.FindConversations(ctx, req.UserIDs[0], []string{req.Conversation.ConversationID})
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
@ -231,7 +233,7 @@ func (c *conversationServer) SetConversations(ctx context.Context, req *pbconver
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		conv = *cs[0]
 | 
							conv = *cs[0]
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	var conversation tablerelation.ConversationModel
 | 
						var conversation tablerelation.Conversation
 | 
				
			||||||
	conversation.ConversationID = req.Conversation.ConversationID
 | 
						conversation.ConversationID = req.Conversation.ConversationID
 | 
				
			||||||
	conversation.ConversationType = req.Conversation.ConversationType
 | 
						conversation.ConversationType = req.Conversation.ConversationType
 | 
				
			||||||
	conversation.UserID = req.Conversation.UserID
 | 
						conversation.UserID = req.Conversation.UserID
 | 
				
			||||||
@ -280,7 +282,7 @@ func (c *conversationServer) SetConversations(ctx context.Context, req *pbconver
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if req.Conversation.IsPrivateChat != nil && req.Conversation.ConversationType != constant.ReadGroupChatType {
 | 
						if req.Conversation.IsPrivateChat != nil && req.Conversation.ConversationType != constant.ReadGroupChatType {
 | 
				
			||||||
		var conversations []*tablerelation.ConversationModel
 | 
							var conversations []*tablerelation.Conversation
 | 
				
			||||||
		for _, ownerUserID := range req.UserIDs {
 | 
							for _, ownerUserID := range req.UserIDs {
 | 
				
			||||||
			conversation2 := conversation
 | 
								conversation2 := conversation
 | 
				
			||||||
			conversation2.OwnerUserID = ownerUserID
 | 
								conversation2.OwnerUserID = ownerUserID
 | 
				
			||||||
@ -328,12 +330,12 @@ func (c *conversationServer) CreateSingleChatConversations(ctx context.Context,
 | 
				
			|||||||
) (*pbconversation.CreateSingleChatConversationsResp, error) {
 | 
					) (*pbconversation.CreateSingleChatConversationsResp, error) {
 | 
				
			||||||
	switch req.ConversationType {
 | 
						switch req.ConversationType {
 | 
				
			||||||
	case constant.SingleChatType:
 | 
						case constant.SingleChatType:
 | 
				
			||||||
		var conversation tablerelation.ConversationModel
 | 
							var conversation tablerelation.Conversation
 | 
				
			||||||
		conversation.ConversationID = req.ConversationID
 | 
							conversation.ConversationID = req.ConversationID
 | 
				
			||||||
		conversation.ConversationType = req.ConversationType
 | 
							conversation.ConversationType = req.ConversationType
 | 
				
			||||||
		conversation.OwnerUserID = req.SendID
 | 
							conversation.OwnerUserID = req.SendID
 | 
				
			||||||
		conversation.UserID = req.RecvID
 | 
							conversation.UserID = req.RecvID
 | 
				
			||||||
		err := c.conversationDatabase.CreateConversation(ctx, []*tablerelation.ConversationModel{&conversation})
 | 
							err := c.conversationDatabase.CreateConversation(ctx, []*tablerelation.Conversation{&conversation})
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			log.ZWarn(ctx, "create conversation failed", err, "conversation", conversation)
 | 
								log.ZWarn(ctx, "create conversation failed", err, "conversation", conversation)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -341,17 +343,17 @@ func (c *conversationServer) CreateSingleChatConversations(ctx context.Context,
 | 
				
			|||||||
		conversation2 := conversation
 | 
							conversation2 := conversation
 | 
				
			||||||
		conversation2.OwnerUserID = req.RecvID
 | 
							conversation2.OwnerUserID = req.RecvID
 | 
				
			||||||
		conversation2.UserID = req.SendID
 | 
							conversation2.UserID = req.SendID
 | 
				
			||||||
		err = c.conversationDatabase.CreateConversation(ctx, []*tablerelation.ConversationModel{&conversation2})
 | 
							err = c.conversationDatabase.CreateConversation(ctx, []*tablerelation.Conversation{&conversation2})
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			log.ZWarn(ctx, "create conversation failed", err, "conversation2", conversation)
 | 
								log.ZWarn(ctx, "create conversation failed", err, "conversation2", conversation)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	case constant.NotificationChatType:
 | 
						case constant.NotificationChatType:
 | 
				
			||||||
		var conversation tablerelation.ConversationModel
 | 
							var conversation tablerelation.Conversation
 | 
				
			||||||
		conversation.ConversationID = req.ConversationID
 | 
							conversation.ConversationID = req.ConversationID
 | 
				
			||||||
		conversation.ConversationType = req.ConversationType
 | 
							conversation.ConversationType = req.ConversationType
 | 
				
			||||||
		conversation.OwnerUserID = req.RecvID
 | 
							conversation.OwnerUserID = req.RecvID
 | 
				
			||||||
		conversation.UserID = req.SendID
 | 
							conversation.UserID = req.SendID
 | 
				
			||||||
		err := c.conversationDatabase.CreateConversation(ctx, []*tablerelation.ConversationModel{&conversation})
 | 
							err := c.conversationDatabase.CreateConversation(ctx, []*tablerelation.Conversation{&conversation})
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			log.ZWarn(ctx, "create conversation failed", err, "conversation2", conversation)
 | 
								log.ZWarn(ctx, "create conversation failed", err, "conversation2", conversation)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
				
			|||||||
@ -16,11 +16,11 @@ package friend
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/authverify"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/authverify"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	pbfriend "github.com/openimsdk/protocol/friend"
 | 
						pbfriend "github.com/openimsdk/protocol/friend"
 | 
				
			||||||
	"github.com/openimsdk/tools/mcontext"
 | 
						"github.com/openimsdk/tools/mcontext"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@ -58,7 +58,7 @@ func (s *friendServer) RemoveBlack(ctx context.Context, req *pbfriend.RemoveBlac
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := s.blackDatabase.Delete(ctx, []*relation.BlackModel{{OwnerUserID: req.OwnerUserID, BlockUserID: req.BlackUserID}}); err != nil {
 | 
						if err := s.blackDatabase.Delete(ctx, []*model.Black{{OwnerUserID: req.OwnerUserID, BlockUserID: req.BlackUserID}}); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -75,7 +75,7 @@ func (s *friendServer) AddBlack(ctx context.Context, req *pbfriend.AddBlackReq)
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	black := relation.BlackModel{
 | 
						black := model.Black{
 | 
				
			||||||
		OwnerUserID:    req.OwnerUserID,
 | 
							OwnerUserID:    req.OwnerUserID,
 | 
				
			||||||
		BlockUserID:    req.BlackUserID,
 | 
							BlockUserID:    req.BlackUserID,
 | 
				
			||||||
		OperatorUserID: mcontext.GetOpUserID(ctx),
 | 
							OperatorUserID: mcontext.GetOpUserID(ctx),
 | 
				
			||||||
@ -83,7 +83,7 @@ func (s *friendServer) AddBlack(ctx context.Context, req *pbfriend.AddBlackReq)
 | 
				
			|||||||
		Ex:             req.Ex,
 | 
							Ex:             req.Ex,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := s.blackDatabase.Create(ctx, []*relation.BlackModel{&black}); err != nil {
 | 
						if err := s.blackDatabase.Create(ctx, []*model.Black{&black}); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	s.notificationSender.BlackAddedNotification(ctx, req)
 | 
						s.notificationSender.BlackAddedNotification(ctx, req)
 | 
				
			||||||
 | 
				
			|||||||
@ -17,16 +17,17 @@ package friend
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis"
 | 
				
			||||||
 | 
						"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/open-im-server/v3/pkg/common/webhook"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/webhook"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/localcache"
 | 
				
			||||||
	"github.com/openimsdk/tools/db/redisutil"
 | 
						"github.com/openimsdk/tools/db/redisutil"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/authverify"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/authverify"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
 | 
					 | 
				
			||||||
	tablerelation "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
 | 
				
			||||||
	"github.com/openimsdk/protocol/constant"
 | 
						"github.com/openimsdk/protocol/constant"
 | 
				
			||||||
	pbfriend "github.com/openimsdk/protocol/friend"
 | 
						pbfriend "github.com/openimsdk/protocol/friend"
 | 
				
			||||||
@ -96,19 +97,19 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
 | 
				
			|||||||
		&msgRpcClient,
 | 
							&msgRpcClient,
 | 
				
			||||||
		WithRpcFunc(userRpcClient.GetUsersInfo),
 | 
							WithRpcFunc(userRpcClient.GetUsersInfo),
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	cache.InitLocalCache(&config.LocalCacheConfig)
 | 
						localcache.InitLocalCache(&config.LocalCacheConfig)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Register Friend server with refactored MongoDB and Redis integrations
 | 
						// Register Friend server with refactored MongoDB and Redis integrations
 | 
				
			||||||
	pbfriend.RegisterFriendServer(server, &friendServer{
 | 
						pbfriend.RegisterFriendServer(server, &friendServer{
 | 
				
			||||||
		friendDatabase: controller.NewFriendDatabase(
 | 
							friendDatabase: controller.NewFriendDatabase(
 | 
				
			||||||
			friendMongoDB,
 | 
								friendMongoDB,
 | 
				
			||||||
			friendRequestMongoDB,
 | 
								friendRequestMongoDB,
 | 
				
			||||||
			cache.NewFriendCacheRedis(rdb, &config.LocalCacheConfig, friendMongoDB, cache.GetDefaultOpt()),
 | 
								redis.NewFriendCacheRedis(rdb, &config.LocalCacheConfig, friendMongoDB, redis.GetRocksCacheOptions()),
 | 
				
			||||||
			mgocli.GetTx(),
 | 
								mgocli.GetTx(),
 | 
				
			||||||
		),
 | 
							),
 | 
				
			||||||
		blackDatabase: controller.NewBlackDatabase(
 | 
							blackDatabase: controller.NewBlackDatabase(
 | 
				
			||||||
			blackMongoDB,
 | 
								blackMongoDB,
 | 
				
			||||||
			cache.NewBlackCacheRedis(rdb, &config.LocalCacheConfig, blackMongoDB, cache.GetDefaultOpt()),
 | 
								redis.NewBlackCacheRedis(rdb, &config.LocalCacheConfig, blackMongoDB, redis.GetRocksCacheOptions()),
 | 
				
			||||||
		),
 | 
							),
 | 
				
			||||||
		userRpcClient:         &userRpcClient,
 | 
							userRpcClient:         &userRpcClient,
 | 
				
			||||||
		notificationSender:    notificationSender,
 | 
							notificationSender:    notificationSender,
 | 
				
			||||||
@ -193,7 +194,7 @@ func (s *friendServer) RespondFriendApply(ctx context.Context, req *pbfriend.Res
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	friendRequest := tablerelation.FriendRequestModel{
 | 
						friendRequest := model.FriendRequest{
 | 
				
			||||||
		FromUserID:   req.FromUserID,
 | 
							FromUserID:   req.FromUserID,
 | 
				
			||||||
		ToUserID:     req.ToUserID,
 | 
							ToUserID:     req.ToUserID,
 | 
				
			||||||
		HandleMsg:    req.HandleMsg,
 | 
							HandleMsg:    req.HandleMsg,
 | 
				
			||||||
@ -384,10 +385,10 @@ func (s *friendServer) GetSpecifiedFriendsInfo(ctx context.Context, req *pbfrien
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	friendMap := datautil.SliceToMap(friends, func(e *tablerelation.FriendModel) string {
 | 
						friendMap := datautil.SliceToMap(friends, func(e *model.Friend) string {
 | 
				
			||||||
		return e.FriendUserID
 | 
							return e.FriendUserID
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	blackMap := datautil.SliceToMap(blacks, func(e *tablerelation.BlackModel) string {
 | 
						blackMap := datautil.SliceToMap(blacks, func(e *model.Black) string {
 | 
				
			||||||
		return e.BlockUserID
 | 
							return e.BlockUserID
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	resp := &pbfriend.GetSpecifiedFriendsInfoResp{
 | 
						resp := &pbfriend.GetSpecifiedFriendsInfoResp{
 | 
				
			||||||
 | 
				
			|||||||
@ -16,11 +16,11 @@ package friend
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
 | 
				
			||||||
	relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
 | 
				
			||||||
	"github.com/openimsdk/protocol/constant"
 | 
						"github.com/openimsdk/protocol/constant"
 | 
				
			||||||
@ -46,7 +46,7 @@ func WithFriendDB(db controller.FriendDatabase) friendNotificationSenderOptions
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func WithDBFunc(
 | 
					func WithDBFunc(
 | 
				
			||||||
	fn func(ctx context.Context, userIDs []string) (users []*relationtb.UserModel, err error),
 | 
						fn func(ctx context.Context, userIDs []string) (users []*relationtb.User, err error),
 | 
				
			||||||
) friendNotificationSenderOptions {
 | 
					) friendNotificationSenderOptions {
 | 
				
			||||||
	return func(s *FriendNotificationSender) {
 | 
						return func(s *FriendNotificationSender) {
 | 
				
			||||||
		f := func(ctx context.Context, userIDs []string) (result []notification.CommonUser, err error) {
 | 
							f := func(ctx context.Context, userIDs []string) (result []notification.CommonUser, err error) {
 | 
				
			||||||
 | 
				
			|||||||
@ -19,7 +19,7 @@ import (
 | 
				
			|||||||
	"github.com/openimsdk/open-im-server/v3/pkg/apistruct"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/apistruct"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/webhook"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/webhook"
 | 
				
			||||||
	"github.com/openimsdk/protocol/constant"
 | 
						"github.com/openimsdk/protocol/constant"
 | 
				
			||||||
	"github.com/openimsdk/protocol/group"
 | 
						"github.com/openimsdk/protocol/group"
 | 
				
			||||||
@ -100,7 +100,7 @@ func (s *groupServer) webhookAfterCreateGroup(ctx context.Context, after *config
 | 
				
			|||||||
	s.webhookClient.AsyncPost(ctx, cbReq.GetCallbackCommand(), cbReq, &callbackstruct.CallbackAfterCreateGroupResp{}, after)
 | 
						s.webhookClient.AsyncPost(ctx, cbReq.GetCallbackCommand(), cbReq, &callbackstruct.CallbackAfterCreateGroupResp{}, after)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *groupServer) webhookBeforeMemberJoinGroup(ctx context.Context, before *config.BeforeConfig, groupMember *relation.GroupMemberModel, groupEx string) error {
 | 
					func (s *groupServer) webhookBeforeMemberJoinGroup(ctx context.Context, before *config.BeforeConfig, groupMember *model.GroupMember, groupEx string) error {
 | 
				
			||||||
	return webhook.WithCondition(ctx, before, func(ctx context.Context) error {
 | 
						return webhook.WithCondition(ctx, before, func(ctx context.Context) error {
 | 
				
			||||||
		cbReq := &callbackstruct.CallbackBeforeMemberJoinGroupReq{
 | 
							cbReq := &callbackstruct.CallbackBeforeMemberJoinGroupReq{
 | 
				
			||||||
			CallbackCommand: callbackstruct.CallbackBeforeMemberJoinGroupCommand,
 | 
								CallbackCommand: callbackstruct.CallbackBeforeMemberJoinGroupCommand,
 | 
				
			||||||
 | 
				
			|||||||
@ -15,11 +15,11 @@
 | 
				
			|||||||
package group
 | 
					package group
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"github.com/openimsdk/protocol/sdkws"
 | 
						"github.com/openimsdk/protocol/sdkws"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *groupServer) groupDB2PB(group *relation.GroupModel, ownerUserID string, memberCount uint32) *sdkws.GroupInfo {
 | 
					func (s *groupServer) groupDB2PB(group *model.Group, ownerUserID string, memberCount uint32) *sdkws.GroupInfo {
 | 
				
			||||||
	return &sdkws.GroupInfo{
 | 
						return &sdkws.GroupInfo{
 | 
				
			||||||
		GroupID:                group.GroupID,
 | 
							GroupID:                group.GroupID,
 | 
				
			||||||
		GroupName:              group.GroupName,
 | 
							GroupName:              group.GroupName,
 | 
				
			||||||
@ -41,7 +41,7 @@ func (s *groupServer) groupDB2PB(group *relation.GroupModel, ownerUserID string,
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *groupServer) groupMemberDB2PB(member *relation.GroupMemberModel, appMangerLevel int32) *sdkws.GroupMemberFullInfo {
 | 
					func (s *groupServer) groupMemberDB2PB(member *model.GroupMember, appMangerLevel int32) *sdkws.GroupMemberFullInfo {
 | 
				
			||||||
	return &sdkws.GroupMemberFullInfo{
 | 
						return &sdkws.GroupMemberFullInfo{
 | 
				
			||||||
		GroupID:        member.GroupID,
 | 
							GroupID:        member.GroupID,
 | 
				
			||||||
		UserID:         member.UserID,
 | 
							UserID:         member.UserID,
 | 
				
			||||||
 | 
				
			|||||||
@ -16,10 +16,9 @@ package group
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *groupServer) PopulateGroupMember(ctx context.Context, members ...*relationtb.GroupMemberModel) error {
 | 
					func (s *groupServer) PopulateGroupMember(ctx context.Context, members ...*relationtb.GroupMember) error {
 | 
				
			||||||
	return s.notification.PopulateGroupMember(ctx, members...)
 | 
						return s.notification.PopulateGroupMember(ctx, members...)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -18,8 +18,11 @@ import (
 | 
				
			|||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/common"
 | 
				
			||||||
 | 
						"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/open-im-server/v3/pkg/common/webhook"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/webhook"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/localcache"
 | 
				
			||||||
	"math/big"
 | 
						"math/big"
 | 
				
			||||||
	"math/rand"
 | 
						"math/rand"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
@ -29,10 +32,8 @@ import (
 | 
				
			|||||||
	"github.com/openimsdk/open-im-server/v3/pkg/authverify"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/authverify"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
 | 
					 | 
				
			||||||
	relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/grouphash"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/grouphash"
 | 
				
			||||||
@ -110,7 +111,7 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		return datautil.Slice(users, func(e *sdkws.UserInfo) notification.CommonUser { return e }), nil
 | 
							return datautil.Slice(users, func(e *sdkws.UserInfo) notification.CommonUser { return e }), nil
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	cache.InitLocalCache(&config.LocalCacheConfig)
 | 
						localcache.InitLocalCache(&config.LocalCacheConfig)
 | 
				
			||||||
	gs.conversationRpcClient = conversationRpcClient
 | 
						gs.conversationRpcClient = conversationRpcClient
 | 
				
			||||||
	gs.msgRpcClient = msgRpcClient
 | 
						gs.msgRpcClient = msgRpcClient
 | 
				
			||||||
	gs.config = config
 | 
						gs.config = config
 | 
				
			||||||
@ -234,14 +235,14 @@ func (s *groupServer) CreateGroup(ctx context.Context, req *pbgroup.CreateGroupR
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var groupMembers []*relationtb.GroupMemberModel
 | 
						var groupMembers []*model.GroupMember
 | 
				
			||||||
	group := convert.Pb2DBGroupInfo(req.GroupInfo)
 | 
						group := convert.Pb2DBGroupInfo(req.GroupInfo)
 | 
				
			||||||
	if err := s.GenGroupID(ctx, &group.GroupID); err != nil {
 | 
						if err := s.GenGroupID(ctx, &group.GroupID); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	joinGroup := func(userID string, roleLevel int32) error {
 | 
						joinGroup := func(userID string, roleLevel int32) error {
 | 
				
			||||||
		groupMember := &relationtb.GroupMemberModel{
 | 
							groupMember := &model.GroupMember{
 | 
				
			||||||
			GroupID:        group.GroupID,
 | 
								GroupID:        group.GroupID,
 | 
				
			||||||
			UserID:         userID,
 | 
								UserID:         userID,
 | 
				
			||||||
			RoleLevel:      roleLevel,
 | 
								RoleLevel:      roleLevel,
 | 
				
			||||||
@ -271,7 +272,7 @@ func (s *groupServer) CreateGroup(ctx context.Context, req *pbgroup.CreateGroupR
 | 
				
			|||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := s.db.CreateGroup(ctx, []*relationtb.GroupModel{group}, groupMembers); err != nil {
 | 
						if err := s.db.CreateGroup(ctx, []*model.Group{group}, groupMembers); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	resp := &pbgroup.CreateGroupResp{GroupInfo: &sdkws.GroupInfo{}}
 | 
						resp := &pbgroup.CreateGroupResp{GroupInfo: &sdkws.GroupInfo{}}
 | 
				
			||||||
@ -339,7 +340,7 @@ func (s *groupServer) GetJoinedGroupList(ctx context.Context, req *pbgroup.GetJo
 | 
				
			|||||||
	if len(members) == 0 {
 | 
						if len(members) == 0 {
 | 
				
			||||||
		return &resp, nil
 | 
							return &resp, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	groupIDs := datautil.Slice(members, func(e *relationtb.GroupMemberModel) string {
 | 
						groupIDs := datautil.Slice(members, func(e *model.GroupMember) string {
 | 
				
			||||||
		return e.GroupID
 | 
							return e.GroupID
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	groups, err := s.db.FindGroup(ctx, groupIDs)
 | 
						groups, err := s.db.FindGroup(ctx, groupIDs)
 | 
				
			||||||
@ -357,12 +358,12 @@ func (s *groupServer) GetJoinedGroupList(ctx context.Context, req *pbgroup.GetJo
 | 
				
			|||||||
	if err := s.PopulateGroupMember(ctx, members...); err != nil {
 | 
						if err := s.PopulateGroupMember(ctx, members...); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ownerMap := datautil.SliceToMap(owners, func(e *relationtb.GroupMemberModel) string {
 | 
						ownerMap := datautil.SliceToMap(owners, func(e *model.GroupMember) string {
 | 
				
			||||||
		return e.GroupID
 | 
							return e.GroupID
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	resp.Groups = datautil.Slice(datautil.Order(groupIDs, groups, func(group *relationtb.GroupModel) string {
 | 
						resp.Groups = datautil.Slice(datautil.Order(groupIDs, groups, func(group *model.Group) string {
 | 
				
			||||||
		return group.GroupID
 | 
							return group.GroupID
 | 
				
			||||||
	}), func(group *relationtb.GroupModel) *sdkws.GroupInfo {
 | 
						}), func(group *model.Group) *sdkws.GroupInfo {
 | 
				
			||||||
		var userID string
 | 
							var userID string
 | 
				
			||||||
		if user := ownerMap[group.GroupID]; user != nil {
 | 
							if user := ownerMap[group.GroupID]; user != nil {
 | 
				
			||||||
			userID = user.UserID
 | 
								userID = user.UserID
 | 
				
			||||||
@ -397,7 +398,7 @@ func (s *groupServer) InviteUserToGroup(ctx context.Context, req *pbgroup.Invite
 | 
				
			|||||||
		return nil, errs.ErrRecordNotFound.WrapMsg("user not found")
 | 
							return nil, errs.ErrRecordNotFound.WrapMsg("user not found")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var groupMember *relationtb.GroupMemberModel
 | 
						var groupMember *model.GroupMember
 | 
				
			||||||
	var opUserID string
 | 
						var opUserID string
 | 
				
			||||||
	if !authverify.IsAppManagerUid(ctx, s.config.Share.IMAdminUserID) {
 | 
						if !authverify.IsAppManagerUid(ctx, s.config.Share.IMAdminUserID) {
 | 
				
			||||||
		opUserID = mcontext.GetOpUserID(ctx)
 | 
							opUserID = mcontext.GetOpUserID(ctx)
 | 
				
			||||||
@ -418,9 +419,9 @@ func (s *groupServer) InviteUserToGroup(ctx context.Context, req *pbgroup.Invite
 | 
				
			|||||||
	if group.NeedVerification == constant.AllNeedVerification {
 | 
						if group.NeedVerification == constant.AllNeedVerification {
 | 
				
			||||||
		if !authverify.IsAppManagerUid(ctx, s.config.Share.IMAdminUserID) {
 | 
							if !authverify.IsAppManagerUid(ctx, s.config.Share.IMAdminUserID) {
 | 
				
			||||||
			if !(groupMember.RoleLevel == constant.GroupOwner || groupMember.RoleLevel == constant.GroupAdmin) {
 | 
								if !(groupMember.RoleLevel == constant.GroupOwner || groupMember.RoleLevel == constant.GroupAdmin) {
 | 
				
			||||||
				var requests []*relationtb.GroupRequestModel
 | 
									var requests []*model.GroupRequest
 | 
				
			||||||
				for _, userID := range req.InvitedUserIDs {
 | 
									for _, userID := range req.InvitedUserIDs {
 | 
				
			||||||
					requests = append(requests, &relationtb.GroupRequestModel{
 | 
										requests = append(requests, &model.GroupRequest{
 | 
				
			||||||
						UserID:        userID,
 | 
											UserID:        userID,
 | 
				
			||||||
						GroupID:       req.GroupID,
 | 
											GroupID:       req.GroupID,
 | 
				
			||||||
						JoinSource:    constant.JoinByInvitation,
 | 
											JoinSource:    constant.JoinByInvitation,
 | 
				
			||||||
@ -444,9 +445,9 @@ func (s *groupServer) InviteUserToGroup(ctx context.Context, req *pbgroup.Invite
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	var groupMembers []*relationtb.GroupMemberModel
 | 
						var groupMembers []*model.GroupMember
 | 
				
			||||||
	for _, userID := range req.InvitedUserIDs {
 | 
						for _, userID := range req.InvitedUserIDs {
 | 
				
			||||||
		member := &relationtb.GroupMemberModel{
 | 
							member := &model.GroupMember{
 | 
				
			||||||
			GroupID:        req.GroupID,
 | 
								GroupID:        req.GroupID,
 | 
				
			||||||
			UserID:         userID,
 | 
								UserID:         userID,
 | 
				
			||||||
			RoleLevel:      constant.GroupOrdinaryUsers,
 | 
								RoleLevel:      constant.GroupOrdinaryUsers,
 | 
				
			||||||
@ -482,7 +483,7 @@ func (s *groupServer) GetGroupAllMember(ctx context.Context, req *pbgroup.GetGro
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	var resp pbgroup.GetGroupAllMemberResp
 | 
						var resp pbgroup.GetGroupAllMemberResp
 | 
				
			||||||
	resp.Members = datautil.Slice(members, func(e *relationtb.GroupMemberModel) *sdkws.GroupMemberFullInfo {
 | 
						resp.Members = datautil.Slice(members, func(e *model.GroupMember) *sdkws.GroupMemberFullInfo {
 | 
				
			||||||
		return convert.Db2PbGroupMember(e)
 | 
							return convert.Db2PbGroupMember(e)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	return &resp, nil
 | 
						return &resp, nil
 | 
				
			||||||
@ -491,7 +492,7 @@ func (s *groupServer) GetGroupAllMember(ctx context.Context, req *pbgroup.GetGro
 | 
				
			|||||||
func (s *groupServer) GetGroupMemberList(ctx context.Context, req *pbgroup.GetGroupMemberListReq) (*pbgroup.GetGroupMemberListResp, error) {
 | 
					func (s *groupServer) GetGroupMemberList(ctx context.Context, req *pbgroup.GetGroupMemberListReq) (*pbgroup.GetGroupMemberListResp, error) {
 | 
				
			||||||
	var (
 | 
						var (
 | 
				
			||||||
		total   int64
 | 
							total   int64
 | 
				
			||||||
		members []*relationtb.GroupMemberModel
 | 
							members []*model.GroupMember
 | 
				
			||||||
		err     error
 | 
							err     error
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	if req.Keyword == "" {
 | 
						if req.Keyword == "" {
 | 
				
			||||||
@ -506,7 +507,7 @@ func (s *groupServer) GetGroupMemberList(ctx context.Context, req *pbgroup.GetGr
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if req.Keyword != "" {
 | 
						if req.Keyword != "" {
 | 
				
			||||||
		groupMembers := make([]*relationtb.GroupMemberModel, 0)
 | 
							groupMembers := make([]*model.GroupMember, 0)
 | 
				
			||||||
		for _, member := range members {
 | 
							for _, member := range members {
 | 
				
			||||||
			if member.UserID == req.Keyword {
 | 
								if member.UserID == req.Keyword {
 | 
				
			||||||
				groupMembers = append(groupMembers, member)
 | 
									groupMembers = append(groupMembers, member)
 | 
				
			||||||
@ -554,7 +555,7 @@ func (s *groupServer) KickGroupMember(ctx context.Context, req *pbgroup.KickGrou
 | 
				
			|||||||
	if err := s.PopulateGroupMember(ctx, members...); err != nil {
 | 
						if err := s.PopulateGroupMember(ctx, members...); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	memberMap := make(map[string]*relationtb.GroupMemberModel)
 | 
						memberMap := make(map[string]*model.GroupMember)
 | 
				
			||||||
	for i, member := range members {
 | 
						for i, member := range members {
 | 
				
			||||||
		memberMap[member.UserID] = members[i]
 | 
							memberMap[member.UserID] = members[i]
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -649,7 +650,7 @@ func (s *groupServer) GetGroupMembersInfo(ctx context.Context, req *pbgroup.GetG
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return &pbgroup.GetGroupMembersInfoResp{
 | 
						return &pbgroup.GetGroupMembersInfoResp{
 | 
				
			||||||
		Members: datautil.Slice(members, func(e *relationtb.GroupMemberModel) *sdkws.GroupMemberFullInfo {
 | 
							Members: datautil.Slice(members, func(e *model.GroupMember) *sdkws.GroupMemberFullInfo {
 | 
				
			||||||
			return convert.Db2PbGroupMember(e)
 | 
								return convert.Db2PbGroupMember(e)
 | 
				
			||||||
		}),
 | 
							}),
 | 
				
			||||||
	}, nil
 | 
						}, nil
 | 
				
			||||||
@ -687,7 +688,7 @@ func (s *groupServer) GetGroupApplicationList(ctx context.Context, req *pbgroup.
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	groupMap := datautil.SliceToMap(groups, func(e *relationtb.GroupModel) string {
 | 
						groupMap := datautil.SliceToMap(groups, func(e *model.Group) string {
 | 
				
			||||||
		return e.GroupID
 | 
							return e.GroupID
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	if ids := datautil.Single(datautil.Keys(groupMap), groupIDs); len(ids) > 0 {
 | 
						if ids := datautil.Single(datautil.Keys(groupMap), groupIDs); len(ids) > 0 {
 | 
				
			||||||
@ -704,10 +705,10 @@ func (s *groupServer) GetGroupApplicationList(ctx context.Context, req *pbgroup.
 | 
				
			|||||||
	if err := s.PopulateGroupMember(ctx, owners...); err != nil {
 | 
						if err := s.PopulateGroupMember(ctx, owners...); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ownerMap := datautil.SliceToMap(owners, func(e *relationtb.GroupMemberModel) string {
 | 
						ownerMap := datautil.SliceToMap(owners, func(e *model.GroupMember) string {
 | 
				
			||||||
		return e.GroupID
 | 
							return e.GroupID
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	resp.GroupRequests = datautil.Slice(groupRequests, func(e *relationtb.GroupRequestModel) *sdkws.GroupRequest {
 | 
						resp.GroupRequests = datautil.Slice(groupRequests, func(e *model.GroupRequest) *sdkws.GroupRequest {
 | 
				
			||||||
		var ownerUserID string
 | 
							var ownerUserID string
 | 
				
			||||||
		if owner, ok := ownerMap[e.GroupID]; ok {
 | 
							if owner, ok := ownerMap[e.GroupID]; ok {
 | 
				
			||||||
			ownerUserID = owner.UserID
 | 
								ownerUserID = owner.UserID
 | 
				
			||||||
@ -736,11 +737,11 @@ func (s *groupServer) GetGroupsInfo(ctx context.Context, req *pbgroup.GetGroupsI
 | 
				
			|||||||
	if err := s.PopulateGroupMember(ctx, owners...); err != nil {
 | 
						if err := s.PopulateGroupMember(ctx, owners...); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ownerMap := datautil.SliceToMap(owners, func(e *relationtb.GroupMemberModel) string {
 | 
						ownerMap := datautil.SliceToMap(owners, func(e *model.GroupMember) string {
 | 
				
			||||||
		return e.GroupID
 | 
							return e.GroupID
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	return &pbgroup.GetGroupsInfoResp{
 | 
						return &pbgroup.GetGroupsInfoResp{
 | 
				
			||||||
		GroupInfos: datautil.Slice(groups, func(e *relationtb.GroupModel) *sdkws.GroupInfo {
 | 
							GroupInfos: datautil.Slice(groups, func(e *model.Group) *sdkws.GroupInfo {
 | 
				
			||||||
			var ownerUserID string
 | 
								var ownerUserID string
 | 
				
			||||||
			if owner, ok := ownerMap[e.GroupID]; ok {
 | 
								if owner, ok := ownerMap[e.GroupID]; ok {
 | 
				
			||||||
				ownerUserID = owner.UserID
 | 
									ownerUserID = owner.UserID
 | 
				
			||||||
@ -783,9 +784,9 @@ func (s *groupServer) GroupApplicationResponse(ctx context.Context, req *pbgroup
 | 
				
			|||||||
	if _, err := s.user.GetPublicUserInfo(ctx, req.FromUserID); err != nil {
 | 
						if _, err := s.user.GetPublicUserInfo(ctx, req.FromUserID); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	var member *relationtb.GroupMemberModel
 | 
						var member *model.GroupMember
 | 
				
			||||||
	if (!inGroup) && req.HandleResult == constant.GroupResponseAgree {
 | 
						if (!inGroup) && req.HandleResult == constant.GroupResponseAgree {
 | 
				
			||||||
		member = &relationtb.GroupMemberModel{
 | 
							member = &model.GroupMember{
 | 
				
			||||||
			GroupID:        req.GroupID,
 | 
								GroupID:        req.GroupID,
 | 
				
			||||||
			UserID:         req.FromUserID,
 | 
								UserID:         req.FromUserID,
 | 
				
			||||||
			Nickname:       "",
 | 
								Nickname:       "",
 | 
				
			||||||
@ -857,7 +858,7 @@ func (s *groupServer) JoinGroup(ctx context.Context, req *pbgroup.JoinGroupReq)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	log.ZDebug(ctx, "JoinGroup.groupInfo", "group", group, "eq", group.NeedVerification == constant.Directly)
 | 
						log.ZDebug(ctx, "JoinGroup.groupInfo", "group", group, "eq", group.NeedVerification == constant.Directly)
 | 
				
			||||||
	if group.NeedVerification == constant.Directly {
 | 
						if group.NeedVerification == constant.Directly {
 | 
				
			||||||
		groupMember := &relationtb.GroupMemberModel{
 | 
							groupMember := &model.GroupMember{
 | 
				
			||||||
			GroupID:        group.GroupID,
 | 
								GroupID:        group.GroupID,
 | 
				
			||||||
			UserID:         user.UserID,
 | 
								UserID:         user.UserID,
 | 
				
			||||||
			RoleLevel:      constant.GroupOrdinaryUsers,
 | 
								RoleLevel:      constant.GroupOrdinaryUsers,
 | 
				
			||||||
@ -871,7 +872,7 @@ func (s *groupServer) JoinGroup(ctx context.Context, req *pbgroup.JoinGroupReq)
 | 
				
			|||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := s.db.CreateGroup(ctx, nil, []*relationtb.GroupMemberModel{groupMember}); err != nil {
 | 
							if err := s.db.CreateGroup(ctx, nil, []*model.GroupMember{groupMember}); err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -883,7 +884,7 @@ func (s *groupServer) JoinGroup(ctx context.Context, req *pbgroup.JoinGroupReq)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		return &pbgroup.JoinGroupResp{}, nil
 | 
							return &pbgroup.JoinGroupResp{}, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	groupRequest := relationtb.GroupRequestModel{
 | 
						groupRequest := model.GroupRequest{
 | 
				
			||||||
		UserID:      req.InviterUserID,
 | 
							UserID:      req.InviterUserID,
 | 
				
			||||||
		ReqMsg:      req.ReqMessage,
 | 
							ReqMsg:      req.ReqMessage,
 | 
				
			||||||
		GroupID:     req.GroupID,
 | 
							GroupID:     req.GroupID,
 | 
				
			||||||
@ -892,7 +893,7 @@ func (s *groupServer) JoinGroup(ctx context.Context, req *pbgroup.JoinGroupReq)
 | 
				
			|||||||
		HandledTime: time.Unix(0, 0),
 | 
							HandledTime: time.Unix(0, 0),
 | 
				
			||||||
		Ex:          req.Ex,
 | 
							Ex:          req.Ex,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err = s.db.CreateGroupRequest(ctx, []*relationtb.GroupRequestModel{&groupRequest}); err != nil {
 | 
						if err = s.db.CreateGroupRequest(ctx, []*model.GroupRequest{&groupRequest}); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	s.notification.JoinGroupApplicationNotification(ctx, req)
 | 
						s.notification.JoinGroupApplicationNotification(ctx, req)
 | 
				
			||||||
@ -940,7 +941,7 @@ func (s *groupServer) deleteMemberAndSetConversationSeq(ctx context.Context, gro
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *groupServer) SetGroupInfo(ctx context.Context, req *pbgroup.SetGroupInfoReq) (*pbgroup.SetGroupInfoResp, error) {
 | 
					func (s *groupServer) SetGroupInfo(ctx context.Context, req *pbgroup.SetGroupInfoReq) (*pbgroup.SetGroupInfoResp, error) {
 | 
				
			||||||
	var opMember *relationtb.GroupMemberModel
 | 
						var opMember *model.GroupMember
 | 
				
			||||||
	if !authverify.IsAppManagerUid(ctx, s.config.Share.IMAdminUserID) {
 | 
						if !authverify.IsAppManagerUid(ctx, s.config.Share.IMAdminUserID) {
 | 
				
			||||||
		var err error
 | 
							var err error
 | 
				
			||||||
		opMember, err = s.db.TakeGroupMember(ctx, req.GroupInfoForSet.GroupID, mcontext.GetOpUserID(ctx))
 | 
							opMember, err = s.db.TakeGroupMember(ctx, req.GroupInfoForSet.GroupID, mcontext.GetOpUserID(ctx))
 | 
				
			||||||
@ -1049,7 +1050,7 @@ func (s *groupServer) TransferGroupOwner(ctx context.Context, req *pbgroup.Trans
 | 
				
			|||||||
	if err := s.PopulateGroupMember(ctx, members...); err != nil {
 | 
						if err := s.PopulateGroupMember(ctx, members...); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	memberMap := datautil.SliceToMap(members, func(e *relationtb.GroupMemberModel) string { return e.UserID })
 | 
						memberMap := datautil.SliceToMap(members, func(e *model.GroupMember) string { return e.UserID })
 | 
				
			||||||
	if ids := datautil.Single([]string{req.OldOwnerUserID, req.NewOwnerUserID}, datautil.Keys(memberMap)); len(ids) > 0 {
 | 
						if ids := datautil.Single([]string{req.OldOwnerUserID, req.NewOwnerUserID}, datautil.Keys(memberMap)); len(ids) > 0 {
 | 
				
			||||||
		return nil, errs.ErrArgs.WrapMsg("user not in group " + strings.Join(ids, ","))
 | 
							return nil, errs.ErrArgs.WrapMsg("user not in group " + strings.Join(ids, ","))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -1078,7 +1079,7 @@ func (s *groupServer) TransferGroupOwner(ctx context.Context, req *pbgroup.Trans
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (s *groupServer) GetGroups(ctx context.Context, req *pbgroup.GetGroupsReq) (*pbgroup.GetGroupsResp, error) {
 | 
					func (s *groupServer) GetGroups(ctx context.Context, req *pbgroup.GetGroupsReq) (*pbgroup.GetGroupsResp, error) {
 | 
				
			||||||
	var (
 | 
						var (
 | 
				
			||||||
		group []*relationtb.GroupModel
 | 
							group []*model.Group
 | 
				
			||||||
		err   error
 | 
							err   error
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	var resp pbgroup.GetGroupsResp
 | 
						var resp pbgroup.GetGroupsResp
 | 
				
			||||||
@ -1095,7 +1096,7 @@ func (s *groupServer) GetGroups(ctx context.Context, req *pbgroup.GetGroupsReq)
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	groupIDs := datautil.Slice(group, func(e *relationtb.GroupModel) string {
 | 
						groupIDs := datautil.Slice(group, func(e *model.Group) string {
 | 
				
			||||||
		return e.GroupID
 | 
							return e.GroupID
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1104,14 +1105,14 @@ func (s *groupServer) GetGroups(ctx context.Context, req *pbgroup.GetGroupsReq)
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ownerMemberMap := datautil.SliceToMap(ownerMembers, func(e *relationtb.GroupMemberModel) string {
 | 
						ownerMemberMap := datautil.SliceToMap(ownerMembers, func(e *model.GroupMember) string {
 | 
				
			||||||
		return e.GroupID
 | 
							return e.GroupID
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	groupMemberNumMap, err := s.db.MapGroupMemberNum(ctx, groupIDs)
 | 
						groupMemberNumMap, err := s.db.MapGroupMemberNum(ctx, groupIDs)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	resp.Groups = datautil.Slice(group, func(group *relationtb.GroupModel) *pbgroup.CMSGroup {
 | 
						resp.Groups = datautil.Slice(group, func(group *model.Group) *pbgroup.CMSGroup {
 | 
				
			||||||
		var (
 | 
							var (
 | 
				
			||||||
			userID   string
 | 
								userID   string
 | 
				
			||||||
			username string
 | 
								username string
 | 
				
			||||||
@ -1135,7 +1136,7 @@ func (s *groupServer) GetGroupMembersCMS(ctx context.Context, req *pbgroup.GetGr
 | 
				
			|||||||
	if err := s.PopulateGroupMember(ctx, members...); err != nil {
 | 
						if err := s.PopulateGroupMember(ctx, members...); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	resp.Members = datautil.Slice(members, func(e *relationtb.GroupMemberModel) *sdkws.GroupMemberFullInfo {
 | 
						resp.Members = datautil.Slice(members, func(e *model.GroupMember) *sdkws.GroupMemberFullInfo {
 | 
				
			||||||
		return convert.Db2PbGroupMember(e)
 | 
							return convert.Db2PbGroupMember(e)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	return &resp, nil
 | 
						return &resp, nil
 | 
				
			||||||
@ -1153,14 +1154,14 @@ func (s *groupServer) GetUserReqApplicationList(ctx context.Context, req *pbgrou
 | 
				
			|||||||
	if len(requests) == 0 {
 | 
						if len(requests) == 0 {
 | 
				
			||||||
		return &pbgroup.GetUserReqApplicationListResp{Total: uint32(total)}, nil
 | 
							return &pbgroup.GetUserReqApplicationListResp{Total: uint32(total)}, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	groupIDs := datautil.Distinct(datautil.Slice(requests, func(e *relationtb.GroupRequestModel) string {
 | 
						groupIDs := datautil.Distinct(datautil.Slice(requests, func(e *model.GroupRequest) string {
 | 
				
			||||||
		return e.GroupID
 | 
							return e.GroupID
 | 
				
			||||||
	}))
 | 
						}))
 | 
				
			||||||
	groups, err := s.db.FindGroup(ctx, groupIDs)
 | 
						groups, err := s.db.FindGroup(ctx, groupIDs)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	groupMap := datautil.SliceToMap(groups, func(e *relationtb.GroupModel) string {
 | 
						groupMap := datautil.SliceToMap(groups, func(e *model.Group) string {
 | 
				
			||||||
		return e.GroupID
 | 
							return e.GroupID
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	owners, err := s.db.FindGroupsOwner(ctx, groupIDs)
 | 
						owners, err := s.db.FindGroupsOwner(ctx, groupIDs)
 | 
				
			||||||
@ -1170,7 +1171,7 @@ func (s *groupServer) GetUserReqApplicationList(ctx context.Context, req *pbgrou
 | 
				
			|||||||
	if err := s.PopulateGroupMember(ctx, owners...); err != nil {
 | 
						if err := s.PopulateGroupMember(ctx, owners...); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ownerMap := datautil.SliceToMap(owners, func(e *relationtb.GroupMemberModel) string {
 | 
						ownerMap := datautil.SliceToMap(owners, func(e *model.GroupMember) string {
 | 
				
			||||||
		return e.GroupID
 | 
							return e.GroupID
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	groupMemberNum, err := s.db.MapGroupMemberNum(ctx, groupIDs)
 | 
						groupMemberNum, err := s.db.MapGroupMemberNum(ctx, groupIDs)
 | 
				
			||||||
@ -1179,7 +1180,7 @@ func (s *groupServer) GetUserReqApplicationList(ctx context.Context, req *pbgrou
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return &pbgroup.GetUserReqApplicationListResp{
 | 
						return &pbgroup.GetUserReqApplicationListResp{
 | 
				
			||||||
		Total: uint32(total),
 | 
							Total: uint32(total),
 | 
				
			||||||
		GroupRequests: datautil.Slice(requests, func(e *relationtb.GroupRequestModel) *sdkws.GroupRequest {
 | 
							GroupRequests: datautil.Slice(requests, func(e *model.GroupRequest) *sdkws.GroupRequest {
 | 
				
			||||||
			var ownerUserID string
 | 
								var ownerUserID string
 | 
				
			||||||
			if owner, ok := ownerMap[e.GroupID]; ok {
 | 
								if owner, ok := ownerMap[e.GroupID]; ok {
 | 
				
			||||||
				ownerUserID = owner.UserID
 | 
									ownerUserID = owner.UserID
 | 
				
			||||||
@ -1430,8 +1431,8 @@ func (s *groupServer) SetGroupMemberInfo(ctx context.Context, req *pbgroup.SetGr
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := s.db.UpdateGroupMembers(ctx, datautil.Slice(req.Members, func(e *pbgroup.SetGroupMemberInfo) *relationtb.BatchUpdateGroupMember {
 | 
						if err := s.db.UpdateGroupMembers(ctx, datautil.Slice(req.Members, func(e *pbgroup.SetGroupMemberInfo) *common.BatchUpdateGroupMember {
 | 
				
			||||||
		return &relationtb.BatchUpdateGroupMember{
 | 
							return &common.BatchUpdateGroupMember{
 | 
				
			||||||
			GroupID: e.GroupID,
 | 
								GroupID: e.GroupID,
 | 
				
			||||||
			UserID:  e.UserID,
 | 
								UserID:  e.UserID,
 | 
				
			||||||
			Map:     UpdateGroupMemberMap(e),
 | 
								Map:     UpdateGroupMemberMap(e),
 | 
				
			||||||
@ -1470,7 +1471,7 @@ func (s *groupServer) GetGroupAbstractInfo(ctx context.Context, req *pbgroup.Get
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if ids := datautil.Single(req.GroupIDs, datautil.Slice(groups, func(group *relationtb.GroupModel) string {
 | 
						if ids := datautil.Single(req.GroupIDs, datautil.Slice(groups, func(group *model.Group) string {
 | 
				
			||||||
		return group.GroupID
 | 
							return group.GroupID
 | 
				
			||||||
	})); len(ids) > 0 {
 | 
						})); len(ids) > 0 {
 | 
				
			||||||
		return nil, servererrs.ErrGroupIDNotFound.WrapMsg("not found group " + strings.Join(ids, ","))
 | 
							return nil, servererrs.ErrGroupIDNotFound.WrapMsg("not found group " + strings.Join(ids, ","))
 | 
				
			||||||
@ -1483,7 +1484,7 @@ func (s *groupServer) GetGroupAbstractInfo(ctx context.Context, req *pbgroup.Get
 | 
				
			|||||||
		return nil, servererrs.ErrGroupIDNotFound.WrapMsg(fmt.Sprintf("group %s not found member", strings.Join(ids, ",")))
 | 
							return nil, servererrs.ErrGroupIDNotFound.WrapMsg(fmt.Sprintf("group %s not found member", strings.Join(ids, ",")))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return &pbgroup.GetGroupAbstractInfoResp{
 | 
						return &pbgroup.GetGroupAbstractInfoResp{
 | 
				
			||||||
		GroupAbstractInfos: datautil.Slice(groups, func(group *relationtb.GroupModel) *pbgroup.GroupAbstractInfo {
 | 
							GroupAbstractInfos: datautil.Slice(groups, func(group *model.Group) *pbgroup.GroupAbstractInfo {
 | 
				
			||||||
			users := groupUserMap[group.GroupID]
 | 
								users := groupUserMap[group.GroupID]
 | 
				
			||||||
			return convert.Db2PbGroupAbstractInfo(group.GroupID, users.MemberNum, users.Hash)
 | 
								return convert.Db2PbGroupAbstractInfo(group.GroupID, users.MemberNum, users.Hash)
 | 
				
			||||||
		}),
 | 
							}),
 | 
				
			||||||
@ -1502,7 +1503,7 @@ func (s *groupServer) GetUserInGroupMembers(ctx context.Context, req *pbgroup.Ge
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return &pbgroup.GetUserInGroupMembersResp{
 | 
						return &pbgroup.GetUserInGroupMembersResp{
 | 
				
			||||||
		Members: datautil.Slice(members, func(e *relationtb.GroupMemberModel) *sdkws.GroupMemberFullInfo {
 | 
							Members: datautil.Slice(members, func(e *model.GroupMember) *sdkws.GroupMemberFullInfo {
 | 
				
			||||||
			return convert.Db2PbGroupMember(e)
 | 
								return convert.Db2PbGroupMember(e)
 | 
				
			||||||
		}),
 | 
							}),
 | 
				
			||||||
	}, nil
 | 
						}, nil
 | 
				
			||||||
@ -1530,7 +1531,7 @@ func (s *groupServer) GetGroupMemberRoleLevel(ctx context.Context, req *pbgroup.
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return &pbgroup.GetGroupMemberRoleLevelResp{
 | 
						return &pbgroup.GetGroupMemberRoleLevelResp{
 | 
				
			||||||
		Members: datautil.Slice(members, func(e *relationtb.GroupMemberModel) *sdkws.GroupMemberFullInfo {
 | 
							Members: datautil.Slice(members, func(e *model.GroupMember) *sdkws.GroupMemberFullInfo {
 | 
				
			||||||
			return convert.Db2PbGroupMember(e)
 | 
								return convert.Db2PbGroupMember(e)
 | 
				
			||||||
		}),
 | 
							}),
 | 
				
			||||||
	}, nil
 | 
						}, nil
 | 
				
			||||||
@ -1544,14 +1545,14 @@ func (s *groupServer) GetGroupUsersReqApplicationList(ctx context.Context, req *
 | 
				
			|||||||
	if len(requests) == 0 {
 | 
						if len(requests) == 0 {
 | 
				
			||||||
		return &pbgroup.GetGroupUsersReqApplicationListResp{}, nil
 | 
							return &pbgroup.GetGroupUsersReqApplicationListResp{}, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	groupIDs := datautil.Distinct(datautil.Slice(requests, func(e *relationtb.GroupRequestModel) string {
 | 
						groupIDs := datautil.Distinct(datautil.Slice(requests, func(e *model.GroupRequest) string {
 | 
				
			||||||
		return e.GroupID
 | 
							return e.GroupID
 | 
				
			||||||
	}))
 | 
						}))
 | 
				
			||||||
	groups, err := s.db.FindGroup(ctx, groupIDs)
 | 
						groups, err := s.db.FindGroup(ctx, groupIDs)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	groupMap := datautil.SliceToMap(groups, func(e *relationtb.GroupModel) string {
 | 
						groupMap := datautil.SliceToMap(groups, func(e *model.Group) string {
 | 
				
			||||||
		return e.GroupID
 | 
							return e.GroupID
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	if ids := datautil.Single(groupIDs, datautil.Keys(groupMap)); len(ids) > 0 {
 | 
						if ids := datautil.Single(groupIDs, datautil.Keys(groupMap)); len(ids) > 0 {
 | 
				
			||||||
@ -1564,7 +1565,7 @@ func (s *groupServer) GetGroupUsersReqApplicationList(ctx context.Context, req *
 | 
				
			|||||||
	if err := s.PopulateGroupMember(ctx, owners...); err != nil {
 | 
						if err := s.PopulateGroupMember(ctx, owners...); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ownerMap := datautil.SliceToMap(owners, func(e *relationtb.GroupMemberModel) string {
 | 
						ownerMap := datautil.SliceToMap(owners, func(e *model.GroupMember) string {
 | 
				
			||||||
		return e.GroupID
 | 
							return e.GroupID
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	groupMemberNum, err := s.db.MapGroupMemberNum(ctx, groupIDs)
 | 
						groupMemberNum, err := s.db.MapGroupMemberNum(ctx, groupIDs)
 | 
				
			||||||
@ -1573,7 +1574,7 @@ func (s *groupServer) GetGroupUsersReqApplicationList(ctx context.Context, req *
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return &pbgroup.GetGroupUsersReqApplicationListResp{
 | 
						return &pbgroup.GetGroupUsersReqApplicationListResp{
 | 
				
			||||||
		Total: int64(len(requests)),
 | 
							Total: int64(len(requests)),
 | 
				
			||||||
		GroupRequests: datautil.Slice(requests, func(e *relationtb.GroupRequestModel) *sdkws.GroupRequest {
 | 
							GroupRequests: datautil.Slice(requests, func(e *model.GroupRequest) *sdkws.GroupRequest {
 | 
				
			||||||
			var ownerUserID string
 | 
								var ownerUserID string
 | 
				
			||||||
			if owner, ok := ownerMap[e.GroupID]; ok {
 | 
								if owner, ok := ownerMap[e.GroupID]; ok {
 | 
				
			||||||
				ownerUserID = owner.UserID
 | 
									ownerUserID = owner.UserID
 | 
				
			||||||
 | 
				
			|||||||
@ -17,12 +17,12 @@ package group
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/authverify"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/authverify"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
 | 
				
			||||||
	"github.com/openimsdk/protocol/constant"
 | 
						"github.com/openimsdk/protocol/constant"
 | 
				
			||||||
	pbgroup "github.com/openimsdk/protocol/group"
 | 
						pbgroup "github.com/openimsdk/protocol/group"
 | 
				
			||||||
@ -50,7 +50,7 @@ type GroupNotificationSender struct {
 | 
				
			|||||||
	config       *Config
 | 
						config       *Config
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupNotificationSender) PopulateGroupMember(ctx context.Context, members ...*relation.GroupMemberModel) error {
 | 
					func (g *GroupNotificationSender) PopulateGroupMember(ctx context.Context, members ...*model.GroupMember) error {
 | 
				
			||||||
	if len(members) == 0 {
 | 
						if len(members) == 0 {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -186,12 +186,12 @@ func (g *GroupNotificationSender) getGroupOwnerAndAdminUserID(ctx context.Contex
 | 
				
			|||||||
	if err := g.PopulateGroupMember(ctx, members...); err != nil {
 | 
						if err := g.PopulateGroupMember(ctx, members...); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	fn := func(e *relation.GroupMemberModel) string { return e.UserID }
 | 
						fn := func(e *model.GroupMember) string { return e.UserID }
 | 
				
			||||||
	return datautil.Slice(members, fn), nil
 | 
						return datautil.Slice(members, fn), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//nolint:unused
 | 
					//nolint:unused
 | 
				
			||||||
func (g *GroupNotificationSender) groupDB2PB(group *relation.GroupModel, ownerUserID string, memberCount uint32) *sdkws.GroupInfo {
 | 
					func (g *GroupNotificationSender) groupDB2PB(group *model.Group, ownerUserID string, memberCount uint32) *sdkws.GroupInfo {
 | 
				
			||||||
	return &sdkws.GroupInfo{
 | 
						return &sdkws.GroupInfo{
 | 
				
			||||||
		GroupID:                group.GroupID,
 | 
							GroupID:                group.GroupID,
 | 
				
			||||||
		GroupName:              group.GroupName,
 | 
							GroupName:              group.GroupName,
 | 
				
			||||||
@ -213,7 +213,7 @@ func (g *GroupNotificationSender) groupDB2PB(group *relation.GroupModel, ownerUs
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupNotificationSender) groupMemberDB2PB(member *relation.GroupMemberModel, appMangerLevel int32) *sdkws.GroupMemberFullInfo {
 | 
					func (g *GroupNotificationSender) groupMemberDB2PB(member *model.GroupMember, appMangerLevel int32) *sdkws.GroupMemberFullInfo {
 | 
				
			||||||
	return &sdkws.GroupMemberFullInfo{
 | 
						return &sdkws.GroupMemberFullInfo{
 | 
				
			||||||
		GroupID:        member.GroupID,
 | 
							GroupID:        member.GroupID,
 | 
				
			||||||
		UserID:         member.UserID,
 | 
							UserID:         member.UserID,
 | 
				
			||||||
 | 
				
			|||||||
@ -17,10 +17,10 @@ package msg
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/authverify"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/authverify"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
 | 
				
			||||||
	"github.com/openimsdk/protocol/constant"
 | 
						"github.com/openimsdk/protocol/constant"
 | 
				
			||||||
	"github.com/openimsdk/protocol/msg"
 | 
						"github.com/openimsdk/protocol/msg"
 | 
				
			||||||
@ -93,7 +93,7 @@ func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq) (*msg.
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	now := time.Now().UnixMilli()
 | 
						now := time.Now().UnixMilli()
 | 
				
			||||||
	err = m.MsgDatabase.RevokeMsg(ctx, req.ConversationID, req.Seq, &relation.RevokeModel{
 | 
						err = m.MsgDatabase.RevokeMsg(ctx, req.ConversationID, req.Seq, &model.RevokeModel{
 | 
				
			||||||
		Role:     role,
 | 
							Role:     role,
 | 
				
			||||||
		UserID:   req.UserID,
 | 
							UserID:   req.UserID,
 | 
				
			||||||
		Nickname: user.Nickname,
 | 
							Nickname: user.Nickname,
 | 
				
			||||||
 | 
				
			|||||||
@ -17,14 +17,14 @@ package msg
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database/mgo"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/webhook"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/webhook"
 | 
				
			||||||
	"github.com/openimsdk/protocol/sdkws"
 | 
						"github.com/openimsdk/protocol/sdkws"
 | 
				
			||||||
	"github.com/openimsdk/tools/db/mongoutil"
 | 
						"github.com/openimsdk/tools/db/mongoutil"
 | 
				
			||||||
	"github.com/openimsdk/tools/db/redisutil"
 | 
						"github.com/openimsdk/tools/db/redisutil"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/rpccache"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/rpccache"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
 | 
				
			||||||
	"github.com/openimsdk/protocol/constant"
 | 
						"github.com/openimsdk/protocol/constant"
 | 
				
			||||||
@ -86,8 +86,8 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	//todo MsgCacheTimeout
 | 
						//todo MsgCacheTimeout
 | 
				
			||||||
	msgModel := cache.NewMsgCache(rdb, config.RedisConfig.EnablePipeline)
 | 
						msgModel := redis.NewMsgCache(rdb, config.RedisConfig.EnablePipeline)
 | 
				
			||||||
	seqModel := cache.NewSeqCache(rdb)
 | 
						seqModel := redis.NewSeqCache(rdb)
 | 
				
			||||||
	conversationClient := rpcclient.NewConversationRpcClient(client, config.Share.RpcRegisterName.Conversation)
 | 
						conversationClient := rpcclient.NewConversationRpcClient(client, config.Share.RpcRegisterName.Conversation)
 | 
				
			||||||
	userRpcClient := rpcclient.NewUserRpcClient(client, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID)
 | 
						userRpcClient := rpcclient.NewUserRpcClient(client, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID)
 | 
				
			||||||
	groupRpcClient := rpcclient.NewGroupRpcClient(client, config.Share.RpcRegisterName.Group)
 | 
						groupRpcClient := rpcclient.NewGroupRpcClient(client, config.Share.RpcRegisterName.Group)
 | 
				
			||||||
 | 
				
			|||||||
@ -16,9 +16,9 @@ package msg
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/protocol/msg"
 | 
						"github.com/openimsdk/protocol/msg"
 | 
				
			||||||
	"github.com/openimsdk/protocol/sdkws"
 | 
						"github.com/openimsdk/protocol/sdkws"
 | 
				
			||||||
	"github.com/openimsdk/tools/utils/datautil"
 | 
						"github.com/openimsdk/tools/utils/datautil"
 | 
				
			||||||
@ -31,7 +31,7 @@ func (m *msgServer) GetActiveUser(ctx context.Context, req *msg.GetActiveUserReq
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	var pbUsers []*msg.ActiveUser
 | 
						var pbUsers []*msg.ActiveUser
 | 
				
			||||||
	if len(users) > 0 {
 | 
						if len(users) > 0 {
 | 
				
			||||||
		userIDs := datautil.Slice(users, func(e *relation.UserCount) string { return e.UserID })
 | 
							userIDs := datautil.Slice(users, func(e *model.UserCount) string { return e.UserID })
 | 
				
			||||||
		userMap, err := m.UserLocalCache.GetUsersInfoMap(ctx, userIDs)
 | 
							userMap, err := m.UserLocalCache.GetUsersInfoMap(ctx, userIDs)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
@ -66,7 +66,7 @@ func (m *msgServer) GetActiveGroup(ctx context.Context, req *msg.GetActiveGroupR
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	var pbgroups []*msg.ActiveGroup
 | 
						var pbgroups []*msg.ActiveGroup
 | 
				
			||||||
	if len(groups) > 0 {
 | 
						if len(groups) > 0 {
 | 
				
			||||||
		groupIDs := datautil.Slice(groups, func(e *relation.GroupCount) string { return e.GroupID })
 | 
							groupIDs := datautil.Slice(groups, func(e *model.GroupCount) string { return e.GroupID })
 | 
				
			||||||
		resp, err := m.GroupLocalCache.GetGroupInfos(ctx, groupIDs)
 | 
							resp, err := m.GroupLocalCache.GetGroupInfos(ctx, groupIDs)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
 | 
				
			|||||||
@ -17,10 +17,10 @@ package third
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"crypto/rand"
 | 
						"crypto/rand"
 | 
				
			||||||
 | 
						relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/authverify"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/authverify"
 | 
				
			||||||
	relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
 | 
				
			||||||
	"github.com/openimsdk/protocol/constant"
 | 
						"github.com/openimsdk/protocol/constant"
 | 
				
			||||||
	"github.com/openimsdk/protocol/third"
 | 
						"github.com/openimsdk/protocol/third"
 | 
				
			||||||
@ -45,11 +45,11 @@ func genLogID() string {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (t *thirdServer) UploadLogs(ctx context.Context, req *third.UploadLogsReq) (*third.UploadLogsResp, error) {
 | 
					func (t *thirdServer) UploadLogs(ctx context.Context, req *third.UploadLogsReq) (*third.UploadLogsResp, error) {
 | 
				
			||||||
	var dbLogs []*relationtb.LogModel
 | 
						var dbLogs []*relationtb.Log
 | 
				
			||||||
	userID := ctx.Value(constant.OpUserID).(string)
 | 
						userID := ctx.Value(constant.OpUserID).(string)
 | 
				
			||||||
	platform := constant.PlatformID2Name[int(req.Platform)]
 | 
						platform := constant.PlatformID2Name[int(req.Platform)]
 | 
				
			||||||
	for _, fileURL := range req.FileURLs {
 | 
						for _, fileURL := range req.FileURLs {
 | 
				
			||||||
		log := relationtb.LogModel{
 | 
							log := relationtb.Log{
 | 
				
			||||||
			Version:    req.Version,
 | 
								Version:    req.Version,
 | 
				
			||||||
			SystemType: req.SystemType,
 | 
								SystemType: req.SystemType,
 | 
				
			||||||
			Platform:   platform,
 | 
								Platform:   platform,
 | 
				
			||||||
@ -70,7 +70,7 @@ func (t *thirdServer) UploadLogs(ctx context.Context, req *third.UploadLogsReq)
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if log.LogID == "" {
 | 
							if log.LogID == "" {
 | 
				
			||||||
			return nil, servererrs.ErrData.WrapMsg("LogModel id gen error")
 | 
								return nil, servererrs.ErrData.WrapMsg("Log id gen error")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		dbLogs = append(dbLogs, &log)
 | 
							dbLogs = append(dbLogs, &log)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -105,8 +105,8 @@ func (t *thirdServer) DeleteLogs(ctx context.Context, req *third.DeleteLogsReq)
 | 
				
			|||||||
	return &third.DeleteLogsResp{}, nil
 | 
						return &third.DeleteLogsResp{}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func dbToPbLogInfos(logs []*relationtb.LogModel) []*third.LogInfo {
 | 
					func dbToPbLogInfos(logs []*relationtb.Log) []*third.LogInfo {
 | 
				
			||||||
	db2pbForLogInfo := func(log *relationtb.LogModel) *third.LogInfo {
 | 
						db2pbForLogInfo := func(log *relationtb.Log) *third.LogInfo {
 | 
				
			||||||
		return &third.LogInfo{
 | 
							return &third.LogInfo{
 | 
				
			||||||
			Filename:   log.FileName,
 | 
								Filename:   log.FileName,
 | 
				
			||||||
			UserID:     log.UserID,
 | 
								UserID:     log.UserID,
 | 
				
			||||||
 | 
				
			|||||||
@ -19,12 +19,12 @@ import (
 | 
				
			|||||||
	"encoding/base64"
 | 
						"encoding/base64"
 | 
				
			||||||
	"encoding/hex"
 | 
						"encoding/hex"
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"path"
 | 
						"path"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/google/uuid"
 | 
						"github.com/google/uuid"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
 | 
				
			||||||
	"github.com/openimsdk/protocol/third"
 | 
						"github.com/openimsdk/protocol/third"
 | 
				
			||||||
	"github.com/openimsdk/tools/errs"
 | 
						"github.com/openimsdk/tools/errs"
 | 
				
			||||||
@ -60,7 +60,7 @@ func (t *thirdServer) InitiateMultipartUpload(ctx context.Context, req *third.In
 | 
				
			|||||||
	result, err := t.s3dataBase.InitiateMultipartUpload(ctx, req.Hash, req.Size, t.defaultExpire, int(req.MaxParts))
 | 
						result, err := t.s3dataBase.InitiateMultipartUpload(ctx, req.Hash, req.Size, t.defaultExpire, int(req.MaxParts))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		if haErr, ok := errs.Unwrap(err).(*cont.HashAlreadyExistsError); ok {
 | 
							if haErr, ok := errs.Unwrap(err).(*cont.HashAlreadyExistsError); ok {
 | 
				
			||||||
			obj := &relation.ObjectModel{
 | 
								obj := &model.Object{
 | 
				
			||||||
				Name:        req.Name,
 | 
									Name:        req.Name,
 | 
				
			||||||
				UserID:      mcontext.GetOpUserID(ctx),
 | 
									UserID:      mcontext.GetOpUserID(ctx),
 | 
				
			||||||
				Hash:        req.Hash,
 | 
									Hash:        req.Hash,
 | 
				
			||||||
@ -137,7 +137,7 @@ func (t *thirdServer) CompleteMultipartUpload(ctx context.Context, req *third.Co
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	obj := &relation.ObjectModel{
 | 
						obj := &model.Object{
 | 
				
			||||||
		Name:        req.Name,
 | 
							Name:        req.Name,
 | 
				
			||||||
		UserID:      mcontext.GetOpUserID(ctx),
 | 
							UserID:      mcontext.GetOpUserID(ctx),
 | 
				
			||||||
		Hash:        result.Hash,
 | 
							Hash:        result.Hash,
 | 
				
			||||||
@ -263,7 +263,7 @@ func (t *thirdServer) CompleteFormData(ctx context.Context, req *third.CompleteF
 | 
				
			|||||||
	if info.Size > 0 && info.Size != mate.Size {
 | 
						if info.Size > 0 && info.Size != mate.Size {
 | 
				
			||||||
		return nil, servererrs.ErrData.WrapMsg("file size mismatch")
 | 
							return nil, servererrs.ErrData.WrapMsg("file size mismatch")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	obj := &relation.ObjectModel{
 | 
						obj := &model.Object{
 | 
				
			||||||
		Name:        mate.Name,
 | 
							Name:        mate.Name,
 | 
				
			||||||
		UserID:      mcontext.GetOpUserID(ctx),
 | 
							UserID:      mcontext.GetOpUserID(ctx),
 | 
				
			||||||
		Hash:        "etag_" + info.ETag,
 | 
							Hash:        "etag_" + info.ETag,
 | 
				
			||||||
 | 
				
			|||||||
@ -18,11 +18,12 @@ import (
 | 
				
			|||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database/mgo"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/localcache"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
 | 
				
			||||||
	"github.com/openimsdk/protocol/third"
 | 
						"github.com/openimsdk/protocol/third"
 | 
				
			||||||
	"github.com/openimsdk/tools/db/mongoutil"
 | 
						"github.com/openimsdk/tools/db/mongoutil"
 | 
				
			||||||
@ -75,7 +76,7 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
 | 
				
			|||||||
	var o s3.Interface
 | 
						var o s3.Interface
 | 
				
			||||||
	switch enable {
 | 
						switch enable {
 | 
				
			||||||
	case "minio":
 | 
						case "minio":
 | 
				
			||||||
		o, err = minio.NewMinio(ctx, cache.NewMinioCache(rdb), *config.MinioConfig.Build())
 | 
							o, err = minio.NewMinio(ctx, redis.NewMinioCache(rdb), *config.MinioConfig.Build())
 | 
				
			||||||
	case "cos":
 | 
						case "cos":
 | 
				
			||||||
		o, err = cos.NewCos(*config.RpcConfig.Object.Cos.Build())
 | 
							o, err = cos.NewCos(*config.RpcConfig.Object.Cos.Build())
 | 
				
			||||||
	case "oss":
 | 
						case "oss":
 | 
				
			||||||
@ -86,9 +87,9 @@ func Start(ctx context.Context, config *Config, client discovery.SvcDiscoveryReg
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	cache.InitLocalCache(&config.LocalCacheConfig)
 | 
						localcache.InitLocalCache(&config.LocalCacheConfig)
 | 
				
			||||||
	third.RegisterThirdServer(server, &thirdServer{
 | 
						third.RegisterThirdServer(server, &thirdServer{
 | 
				
			||||||
		thirdDatabase: controller.NewThirdDatabase(cache.NewThirdCache(rdb), logdb),
 | 
							thirdDatabase: controller.NewThirdDatabase(redis.NewThirdCache(rdb), logdb),
 | 
				
			||||||
		userRpcClient: rpcclient.NewUserRpcClient(client, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID),
 | 
							userRpcClient: rpcclient.NewUserRpcClient(client, config.Share.RpcRegisterName.User, config.Share.IMAdminUserID),
 | 
				
			||||||
		s3dataBase:    controller.NewS3Database(rdb, o, s3db),
 | 
							s3dataBase:    controller.NewS3Database(rdb, o, s3db),
 | 
				
			||||||
		defaultExpire: time.Hour * 24 * 7,
 | 
							defaultExpire: time.Hour * 24 * 7,
 | 
				
			||||||
 | 
				
			|||||||
@ -16,10 +16,10 @@ package user
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
 | 
				
			||||||
	relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
 | 
				
			||||||
	"github.com/openimsdk/protocol/constant"
 | 
						"github.com/openimsdk/protocol/constant"
 | 
				
			||||||
	"github.com/openimsdk/protocol/sdkws"
 | 
						"github.com/openimsdk/protocol/sdkws"
 | 
				
			||||||
@ -41,7 +41,7 @@ func WithUserDB(db controller.UserDatabase) userNotificationSenderOptions {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func WithUserFunc(
 | 
					func WithUserFunc(
 | 
				
			||||||
	fn func(ctx context.Context, userIDs []string) (users []*relationtb.UserModel, err error),
 | 
						fn func(ctx context.Context, userIDs []string) (users []*relationtb.User, err error),
 | 
				
			||||||
) userNotificationSenderOptions {
 | 
					) userNotificationSenderOptions {
 | 
				
			||||||
	return func(u *UserNotificationSender) {
 | 
						return func(u *UserNotificationSender) {
 | 
				
			||||||
		f := func(ctx context.Context, userIDs []string) (result []notification.CommonUser, err error) {
 | 
							f := func(ctx context.Context, userIDs []string) (result []notification.CommonUser, err error) {
 | 
				
			||||||
 | 
				
			|||||||
@ -18,7 +18,11 @@ import (
 | 
				
			|||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/internal/rpc/friend"
 | 
						"github.com/openimsdk/open-im-server/v3/internal/rpc/friend"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database/mgo"
 | 
				
			||||||
 | 
						tablerelation "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/webhook"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/webhook"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/localcache"
 | 
				
			||||||
	"github.com/openimsdk/tools/db/redisutil"
 | 
						"github.com/openimsdk/tools/db/redisutil"
 | 
				
			||||||
	"math/rand"
 | 
						"math/rand"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
@ -26,12 +30,8 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/authverify"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/authverify"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	tablerelation "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
 | 
				
			||||||
	"github.com/openimsdk/protocol/constant"
 | 
						"github.com/openimsdk/protocol/constant"
 | 
				
			||||||
	"github.com/openimsdk/protocol/sdkws"
 | 
						"github.com/openimsdk/protocol/sdkws"
 | 
				
			||||||
@ -77,22 +77,22 @@ func Start(ctx context.Context, config *Config, client registry.SvcDiscoveryRegi
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	users := make([]*tablerelation.UserModel, 0)
 | 
						users := make([]*tablerelation.User, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, v := range config.Share.IMAdminUserID {
 | 
						for _, v := range config.Share.IMAdminUserID {
 | 
				
			||||||
		users = append(users, &tablerelation.UserModel{UserID: v, Nickname: v, AppMangerLevel: constant.AppNotificationAdmin})
 | 
							users = append(users, &tablerelation.User{UserID: v, Nickname: v, AppMangerLevel: constant.AppNotificationAdmin})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	userDB, err := mgo.NewUserMongo(mgocli.GetDB())
 | 
						userDB, err := mgo.NewUserMongo(mgocli.GetDB())
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	userCache := cache.NewUserCacheRedis(rdb, &config.LocalCacheConfig, userDB, cache.GetDefaultOpt())
 | 
						userCache := redis.NewUserCacheRedis(rdb, &config.LocalCacheConfig, userDB, redis.GetRocksCacheOptions())
 | 
				
			||||||
	userMongoDB := mgo.NewUserMongoDriver(mgocli.GetDB())
 | 
						userMongoDB := mgo.NewUserMongoDriver(mgocli.GetDB())
 | 
				
			||||||
	database := controller.NewUserDatabase(userDB, userCache, mgocli.GetTx(), userMongoDB)
 | 
						database := controller.NewUserDatabase(userDB, userCache, mgocli.GetTx(), userMongoDB)
 | 
				
			||||||
	friendRpcClient := rpcclient.NewFriendRpcClient(client, config.Share.RpcRegisterName.Friend)
 | 
						friendRpcClient := rpcclient.NewFriendRpcClient(client, config.Share.RpcRegisterName.Friend)
 | 
				
			||||||
	groupRpcClient := rpcclient.NewGroupRpcClient(client, config.Share.RpcRegisterName.Group)
 | 
						groupRpcClient := rpcclient.NewGroupRpcClient(client, config.Share.RpcRegisterName.Group)
 | 
				
			||||||
	msgRpcClient := rpcclient.NewMessageRpcClient(client, config.Share.RpcRegisterName.Msg)
 | 
						msgRpcClient := rpcclient.NewMessageRpcClient(client, config.Share.RpcRegisterName.Msg)
 | 
				
			||||||
	cache.InitLocalCache(&config.LocalCacheConfig)
 | 
						localcache.InitLocalCache(&config.LocalCacheConfig)
 | 
				
			||||||
	u := &userServer{
 | 
						u := &userServer{
 | 
				
			||||||
		db:                       database,
 | 
							db:                       database,
 | 
				
			||||||
		RegisterCenter:           client,
 | 
							RegisterCenter:           client,
 | 
				
			||||||
@ -281,9 +281,9 @@ func (s *userServer) UserRegister(ctx context.Context, req *pbuser.UserRegisterR
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	now := time.Now()
 | 
						now := time.Now()
 | 
				
			||||||
	users := make([]*tablerelation.UserModel, 0, len(req.Users))
 | 
						users := make([]*tablerelation.User, 0, len(req.Users))
 | 
				
			||||||
	for _, user := range req.Users {
 | 
						for _, user := range req.Users {
 | 
				
			||||||
		users = append(users, &tablerelation.UserModel{
 | 
							users = append(users, &tablerelation.User{
 | 
				
			||||||
			UserID:           user.UserID,
 | 
								UserID:           user.UserID,
 | 
				
			||||||
			Nickname:         user.Nickname,
 | 
								Nickname:         user.Nickname,
 | 
				
			||||||
			FaceURL:          user.FaceURL,
 | 
								FaceURL:          user.FaceURL,
 | 
				
			||||||
@ -403,7 +403,7 @@ func (s *userServer) ProcessUserCommandAdd(ctx context.Context, req *pbuser.Proc
 | 
				
			|||||||
	if req.Ex != nil {
 | 
						if req.Ex != nil {
 | 
				
			||||||
		value = req.Ex.Value
 | 
							value = req.Ex.Value
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Assuming you have a method in s.db to add a user command
 | 
						// Assuming you have a method in s.storage to add a user command
 | 
				
			||||||
	err = s.db.AddUserCommand(ctx, req.UserID, req.Type, req.Uuid, value, ex)
 | 
						err = s.db.AddUserCommand(ctx, req.UserID, req.Type, req.Uuid, value, ex)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
@ -451,7 +451,7 @@ func (s *userServer) ProcessUserCommandUpdate(ctx context.Context, req *pbuser.P
 | 
				
			|||||||
		val["ex"] = req.Ex.Value
 | 
							val["ex"] = req.Ex.Value
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Assuming you have a method in s.db to update a user command
 | 
						// Assuming you have a method in s.storage to update a user command
 | 
				
			||||||
	err = s.db.UpdateUserCommand(ctx, req.UserID, req.Type, req.Uuid, val)
 | 
						err = s.db.UpdateUserCommand(ctx, req.UserID, req.Type, req.Uuid, val)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
@ -548,14 +548,14 @@ func (s *userServer) AddNotificationAccount(ctx context.Context, req *pbuser.Add
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	user := &tablerelation.UserModel{
 | 
						user := &tablerelation.User{
 | 
				
			||||||
		UserID:         req.UserID,
 | 
							UserID:         req.UserID,
 | 
				
			||||||
		Nickname:       req.NickName,
 | 
							Nickname:       req.NickName,
 | 
				
			||||||
		FaceURL:        req.FaceURL,
 | 
							FaceURL:        req.FaceURL,
 | 
				
			||||||
		CreateTime:     time.Now(),
 | 
							CreateTime:     time.Now(),
 | 
				
			||||||
		AppMangerLevel: constant.AppNotificationAdmin,
 | 
							AppMangerLevel: constant.AppNotificationAdmin,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := s.db.Create(ctx, []*tablerelation.UserModel{user}); err != nil {
 | 
						if err := s.db.Create(ctx, []*tablerelation.User{user}); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -598,7 +598,7 @@ func (s *userServer) SearchNotificationAccount(ctx context.Context, req *pbuser.
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var users []*relation.UserModel
 | 
						var users []*tablerelation.User
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// If a keyword is provided in the request
 | 
						// If a keyword is provided in the request
 | 
				
			||||||
@ -664,7 +664,7 @@ func (s *userServer) genUserID() string {
 | 
				
			|||||||
	return string(data)
 | 
						return string(data)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *userServer) userModelToResp(users []*relation.UserModel, pagination pagination.Pagination) *pbuser.SearchNotificationAccountResp {
 | 
					func (s *userServer) userModelToResp(users []*tablerelation.User, pagination pagination.Pagination) *pbuser.SearchNotificationAccountResp {
 | 
				
			||||||
	accounts := make([]*pbuser.NotificationAccountInfo, 0)
 | 
						accounts := make([]*pbuser.NotificationAccountInfo, 0)
 | 
				
			||||||
	var total int64
 | 
						var total int64
 | 
				
			||||||
	for _, v := range users {
 | 
						for _, v := range users {
 | 
				
			||||||
 | 
				
			|||||||
@ -328,7 +328,7 @@ type Redis struct {
 | 
				
			|||||||
	Password       string   `mapstructure:"password"`
 | 
						Password       string   `mapstructure:"password"`
 | 
				
			||||||
	EnablePipeline bool     `mapstructure:"enablePipeline"`
 | 
						EnablePipeline bool     `mapstructure:"enablePipeline"`
 | 
				
			||||||
	ClusterMode    bool     `mapstructure:"clusterMode"`
 | 
						ClusterMode    bool     `mapstructure:"clusterMode"`
 | 
				
			||||||
	DB             int      `mapstructure:"db"`
 | 
						DB             int      `mapstructure:"storage"`
 | 
				
			||||||
	MaxRetry       int      `mapstructure:"MaxRetry"`
 | 
						MaxRetry       int      `mapstructure:"MaxRetry"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -16,13 +16,13 @@ package convert
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/protocol/sdkws"
 | 
						"github.com/openimsdk/protocol/sdkws"
 | 
				
			||||||
	sdk "github.com/openimsdk/protocol/sdkws"
 | 
						sdk "github.com/openimsdk/protocol/sdkws"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func BlackDB2Pb(ctx context.Context, blackDBs []*relation.BlackModel, f func(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error)) (blackPbs []*sdk.BlackInfo, err error) {
 | 
					func BlackDB2Pb(ctx context.Context, blackDBs []*model.Black, f func(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error)) (blackPbs []*sdk.BlackInfo, err error) {
 | 
				
			||||||
	if len(blackDBs) == 0 {
 | 
						if len(blackDBs) == 0 {
 | 
				
			||||||
		return nil, nil
 | 
							return nil, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -15,12 +15,12 @@
 | 
				
			|||||||
package convert
 | 
					package convert
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"github.com/openimsdk/protocol/conversation"
 | 
						"github.com/openimsdk/protocol/conversation"
 | 
				
			||||||
	"github.com/openimsdk/tools/utils/datautil"
 | 
						"github.com/openimsdk/tools/utils/datautil"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ConversationDB2Pb(conversationDB *relation.ConversationModel) *conversation.Conversation {
 | 
					func ConversationDB2Pb(conversationDB *model.Conversation) *conversation.Conversation {
 | 
				
			||||||
	conversationPB := &conversation.Conversation{}
 | 
						conversationPB := &conversation.Conversation{}
 | 
				
			||||||
	conversationPB.LatestMsgDestructTime = conversationDB.LatestMsgDestructTime.Unix()
 | 
						conversationPB.LatestMsgDestructTime = conversationDB.LatestMsgDestructTime.Unix()
 | 
				
			||||||
	if err := datautil.CopyStructFields(conversationPB, conversationDB); err != nil {
 | 
						if err := datautil.CopyStructFields(conversationPB, conversationDB); err != nil {
 | 
				
			||||||
@ -29,7 +29,7 @@ func ConversationDB2Pb(conversationDB *relation.ConversationModel) *conversation
 | 
				
			|||||||
	return conversationPB
 | 
						return conversationPB
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ConversationsDB2Pb(conversationsDB []*relation.ConversationModel) (conversationsPB []*conversation.Conversation) {
 | 
					func ConversationsDB2Pb(conversationsDB []*model.Conversation) (conversationsPB []*conversation.Conversation) {
 | 
				
			||||||
	for _, conversationDB := range conversationsDB {
 | 
						for _, conversationDB := range conversationsDB {
 | 
				
			||||||
		conversationPB := &conversation.Conversation{}
 | 
							conversationPB := &conversation.Conversation{}
 | 
				
			||||||
		if err := datautil.CopyStructFields(conversationPB, conversationDB); err != nil {
 | 
							if err := datautil.CopyStructFields(conversationPB, conversationDB); err != nil {
 | 
				
			||||||
@ -41,17 +41,17 @@ func ConversationsDB2Pb(conversationsDB []*relation.ConversationModel) (conversa
 | 
				
			|||||||
	return conversationsPB
 | 
						return conversationsPB
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ConversationPb2DB(conversationPB *conversation.Conversation) *relation.ConversationModel {
 | 
					func ConversationPb2DB(conversationPB *conversation.Conversation) *model.Conversation {
 | 
				
			||||||
	conversationDB := &relation.ConversationModel{}
 | 
						conversationDB := &model.Conversation{}
 | 
				
			||||||
	if err := datautil.CopyStructFields(conversationDB, conversationPB); err != nil {
 | 
						if err := datautil.CopyStructFields(conversationDB, conversationPB); err != nil {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return conversationDB
 | 
						return conversationDB
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ConversationsPb2DB(conversationsPB []*conversation.Conversation) (conversationsDB []*relation.ConversationModel) {
 | 
					func ConversationsPb2DB(conversationsPB []*conversation.Conversation) (conversationsDB []*model.Conversation) {
 | 
				
			||||||
	for _, conversationPB := range conversationsPB {
 | 
						for _, conversationPB := range conversationsPB {
 | 
				
			||||||
		conversationDB := &relation.ConversationModel{}
 | 
							conversationDB := &model.Conversation{}
 | 
				
			||||||
		if err := datautil.CopyStructFields(conversationDB, conversationPB); err != nil {
 | 
							if err := datautil.CopyStructFields(conversationDB, conversationPB); err != nil {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
				
			|||||||
@ -17,15 +17,15 @@ package convert
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/protocol/sdkws"
 | 
						"github.com/openimsdk/protocol/sdkws"
 | 
				
			||||||
	"github.com/openimsdk/tools/utils/datautil"
 | 
						"github.com/openimsdk/tools/utils/datautil"
 | 
				
			||||||
	"github.com/openimsdk/tools/utils/timeutil"
 | 
						"github.com/openimsdk/tools/utils/timeutil"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func FriendPb2DB(friend *sdkws.FriendInfo) *relation.FriendModel {
 | 
					func FriendPb2DB(friend *sdkws.FriendInfo) *model.Friend {
 | 
				
			||||||
	dbFriend := &relation.FriendModel{}
 | 
						dbFriend := &model.Friend{}
 | 
				
			||||||
	err := datautil.CopyStructFields(dbFriend, friend)
 | 
						err := datautil.CopyStructFields(dbFriend, friend)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
@ -35,7 +35,7 @@ func FriendPb2DB(friend *sdkws.FriendInfo) *relation.FriendModel {
 | 
				
			|||||||
	return dbFriend
 | 
						return dbFriend
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func FriendDB2Pb(ctx context.Context, friendDB *relation.FriendModel,
 | 
					func FriendDB2Pb(ctx context.Context, friendDB *model.Friend,
 | 
				
			||||||
	getUsers func(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error),
 | 
						getUsers func(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error),
 | 
				
			||||||
) (*sdkws.FriendInfo, error) {
 | 
					) (*sdkws.FriendInfo, error) {
 | 
				
			||||||
	users, err := getUsers(ctx, []string{friendDB.FriendUserID})
 | 
						users, err := getUsers(ctx, []string{friendDB.FriendUserID})
 | 
				
			||||||
@ -55,7 +55,7 @@ func FriendDB2Pb(ctx context.Context, friendDB *relation.FriendModel,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func FriendsDB2Pb(
 | 
					func FriendsDB2Pb(
 | 
				
			||||||
	ctx context.Context,
 | 
						ctx context.Context,
 | 
				
			||||||
	friendsDB []*relation.FriendModel,
 | 
						friendsDB []*model.Friend,
 | 
				
			||||||
	getUsers func(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error),
 | 
						getUsers func(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error),
 | 
				
			||||||
) (friendsPb []*sdkws.FriendInfo, err error) {
 | 
					) (friendsPb []*sdkws.FriendInfo, err error) {
 | 
				
			||||||
	if len(friendsDB) == 0 {
 | 
						if len(friendsDB) == 0 {
 | 
				
			||||||
@ -89,7 +89,7 @@ func FriendsDB2Pb(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func FriendRequestDB2Pb(ctx context.Context, friendRequests []*relation.FriendRequestModel, getUsers func(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error)) ([]*sdkws.FriendRequest, error) {
 | 
					func FriendRequestDB2Pb(ctx context.Context, friendRequests []*model.FriendRequest, getUsers func(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error)) ([]*sdkws.FriendRequest, error) {
 | 
				
			||||||
	if len(friendRequests) == 0 {
 | 
						if len(friendRequests) == 0 {
 | 
				
			||||||
		return nil, nil
 | 
							return nil, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -134,8 +134,8 @@ func FriendPb2DBMap(friend *sdkws.FriendInfo) map[string]any {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	val := make(map[string]any)
 | 
						val := make(map[string]any)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Assuming FriendInfo has similar fields to those in FriendModel.
 | 
						// Assuming FriendInfo has similar fields to those in Friend.
 | 
				
			||||||
	// Add or remove fields based on your actual FriendInfo and FriendModel structures.
 | 
						// Add or remove fields based on your actual FriendInfo and Friend structures.
 | 
				
			||||||
	if friend.FriendUser != nil {
 | 
						if friend.FriendUser != nil {
 | 
				
			||||||
		if friend.FriendUser.UserID != "" {
 | 
							if friend.FriendUser.UserID != "" {
 | 
				
			||||||
			val["friend_user_id"] = friend.FriendUser.UserID
 | 
								val["friend_user_id"] = friend.FriendUser.UserID
 | 
				
			||||||
 | 
				
			|||||||
@ -15,14 +15,14 @@
 | 
				
			|||||||
package convert
 | 
					package convert
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	pbgroup "github.com/openimsdk/protocol/group"
 | 
						pbgroup "github.com/openimsdk/protocol/group"
 | 
				
			||||||
	sdkws "github.com/openimsdk/protocol/sdkws"
 | 
						sdkws "github.com/openimsdk/protocol/sdkws"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Db2PbGroupInfo(m *relation.GroupModel, ownerUserID string, memberCount uint32) *sdkws.GroupInfo {
 | 
					func Db2PbGroupInfo(m *model.Group, ownerUserID string, memberCount uint32) *sdkws.GroupInfo {
 | 
				
			||||||
	return &sdkws.GroupInfo{
 | 
						return &sdkws.GroupInfo{
 | 
				
			||||||
		GroupID:                m.GroupID,
 | 
							GroupID:                m.GroupID,
 | 
				
			||||||
		GroupName:              m.GroupName,
 | 
							GroupName:              m.GroupName,
 | 
				
			||||||
@ -44,8 +44,8 @@ func Db2PbGroupInfo(m *relation.GroupModel, ownerUserID string, memberCount uint
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Pb2DbGroupRequest(req *pbgroup.GroupApplicationResponseReq, handleUserID string) *relation.GroupRequestModel {
 | 
					func Pb2DbGroupRequest(req *pbgroup.GroupApplicationResponseReq, handleUserID string) *model.GroupRequest {
 | 
				
			||||||
	return &relation.GroupRequestModel{
 | 
						return &model.GroupRequest{
 | 
				
			||||||
		UserID:       req.FromUserID,
 | 
							UserID:       req.FromUserID,
 | 
				
			||||||
		GroupID:      req.GroupID,
 | 
							GroupID:      req.GroupID,
 | 
				
			||||||
		HandleResult: req.HandleResult,
 | 
							HandleResult: req.HandleResult,
 | 
				
			||||||
@ -55,7 +55,7 @@ func Pb2DbGroupRequest(req *pbgroup.GroupApplicationResponseReq, handleUserID st
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Db2PbCMSGroup(m *relation.GroupModel, ownerUserID string, ownerUserName string, memberCount uint32) *pbgroup.CMSGroup {
 | 
					func Db2PbCMSGroup(m *model.Group, ownerUserID string, ownerUserName string, memberCount uint32) *pbgroup.CMSGroup {
 | 
				
			||||||
	return &pbgroup.CMSGroup{
 | 
						return &pbgroup.CMSGroup{
 | 
				
			||||||
		GroupInfo:          Db2PbGroupInfo(m, ownerUserID, memberCount),
 | 
							GroupInfo:          Db2PbGroupInfo(m, ownerUserID, memberCount),
 | 
				
			||||||
		GroupOwnerUserID:   ownerUserID,
 | 
							GroupOwnerUserID:   ownerUserID,
 | 
				
			||||||
@ -63,7 +63,7 @@ func Db2PbCMSGroup(m *relation.GroupModel, ownerUserID string, ownerUserName str
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Db2PbGroupMember(m *relation.GroupMemberModel) *sdkws.GroupMemberFullInfo {
 | 
					func Db2PbGroupMember(m *model.GroupMember) *sdkws.GroupMemberFullInfo {
 | 
				
			||||||
	return &sdkws.GroupMemberFullInfo{
 | 
						return &sdkws.GroupMemberFullInfo{
 | 
				
			||||||
		GroupID:   m.GroupID,
 | 
							GroupID:   m.GroupID,
 | 
				
			||||||
		UserID:    m.UserID,
 | 
							UserID:    m.UserID,
 | 
				
			||||||
@ -80,7 +80,7 @@ func Db2PbGroupMember(m *relation.GroupMemberModel) *sdkws.GroupMemberFullInfo {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Db2PbGroupRequest(m *relation.GroupRequestModel, user *sdkws.PublicUserInfo, group *sdkws.GroupInfo) *sdkws.GroupRequest {
 | 
					func Db2PbGroupRequest(m *model.GroupRequest, user *sdkws.PublicUserInfo, group *sdkws.GroupInfo) *sdkws.GroupRequest {
 | 
				
			||||||
	return &sdkws.GroupRequest{
 | 
						return &sdkws.GroupRequest{
 | 
				
			||||||
		UserInfo:      user,
 | 
							UserInfo:      user,
 | 
				
			||||||
		GroupInfo:     group,
 | 
							GroupInfo:     group,
 | 
				
			||||||
@ -108,8 +108,8 @@ func Db2PbGroupAbstractInfo(
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Pb2DBGroupInfo(m *sdkws.GroupInfo) *relation.GroupModel {
 | 
					func Pb2DBGroupInfo(m *sdkws.GroupInfo) *model.Group {
 | 
				
			||||||
	return &relation.GroupModel{
 | 
						return &model.Group{
 | 
				
			||||||
		GroupID:                m.GroupID,
 | 
							GroupID:                m.GroupID,
 | 
				
			||||||
		GroupName:              m.GroupName,
 | 
							GroupName:              m.GroupName,
 | 
				
			||||||
		Notification:           m.Notification,
 | 
							Notification:           m.Notification,
 | 
				
			||||||
@ -128,8 +128,8 @@ func Pb2DBGroupInfo(m *sdkws.GroupInfo) *relation.GroupModel {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// func Pb2DbGroupMember(m *sdkws.UserInfo) *relation.GroupMemberModel {
 | 
					// func Pb2DbGroupMember(m *sdkws.UserInfo) *relation.GroupMember {
 | 
				
			||||||
//	return &relation.GroupMemberModel{
 | 
					//	return &relation.GroupMember{
 | 
				
			||||||
//		UserID:   m.UserID,
 | 
					//		UserID:   m.UserID,
 | 
				
			||||||
//		Nickname: m.Nickname,
 | 
					//		Nickname: m.Nickname,
 | 
				
			||||||
//		FaceURL:  m.FaceURL,
 | 
					//		FaceURL:  m.FaceURL,
 | 
				
			||||||
 | 
				
			|||||||
@ -15,16 +15,16 @@
 | 
				
			|||||||
package convert
 | 
					package convert
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"github.com/openimsdk/protocol/constant"
 | 
						"github.com/openimsdk/protocol/constant"
 | 
				
			||||||
	"github.com/openimsdk/protocol/sdkws"
 | 
						"github.com/openimsdk/protocol/sdkws"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func MsgPb2DB(msg *sdkws.MsgData) *relation.MsgDataModel {
 | 
					func MsgPb2DB(msg *sdkws.MsgData) *model.MsgDataModel {
 | 
				
			||||||
	if msg == nil {
 | 
						if msg == nil {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	var msgDataModel relation.MsgDataModel
 | 
						var msgDataModel model.MsgDataModel
 | 
				
			||||||
	msgDataModel.SendID = msg.SendID
 | 
						msgDataModel.SendID = msg.SendID
 | 
				
			||||||
	msgDataModel.RecvID = msg.RecvID
 | 
						msgDataModel.RecvID = msg.RecvID
 | 
				
			||||||
	msgDataModel.GroupID = msg.GroupID
 | 
						msgDataModel.GroupID = msg.GroupID
 | 
				
			||||||
@ -43,7 +43,7 @@ func MsgPb2DB(msg *sdkws.MsgData) *relation.MsgDataModel {
 | 
				
			|||||||
	msgDataModel.Status = msg.Status
 | 
						msgDataModel.Status = msg.Status
 | 
				
			||||||
	msgDataModel.Options = msg.Options
 | 
						msgDataModel.Options = msg.Options
 | 
				
			||||||
	if msg.OfflinePushInfo != nil {
 | 
						if msg.OfflinePushInfo != nil {
 | 
				
			||||||
		msgDataModel.OfflinePush = &relation.OfflinePushModel{
 | 
							msgDataModel.OfflinePush = &model.OfflinePushModel{
 | 
				
			||||||
			Title:         msg.OfflinePushInfo.Title,
 | 
								Title:         msg.OfflinePushInfo.Title,
 | 
				
			||||||
			Desc:          msg.OfflinePushInfo.Desc,
 | 
								Desc:          msg.OfflinePushInfo.Desc,
 | 
				
			||||||
			Ex:            msg.OfflinePushInfo.Ex,
 | 
								Ex:            msg.OfflinePushInfo.Ex,
 | 
				
			||||||
@ -57,7 +57,7 @@ func MsgPb2DB(msg *sdkws.MsgData) *relation.MsgDataModel {
 | 
				
			|||||||
	return &msgDataModel
 | 
						return &msgDataModel
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func MsgDB2Pb(msgModel *relation.MsgDataModel) *sdkws.MsgData {
 | 
					func MsgDB2Pb(msgModel *model.MsgDataModel) *sdkws.MsgData {
 | 
				
			||||||
	if msgModel == nil {
 | 
						if msgModel == nil {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -15,13 +15,13 @@
 | 
				
			|||||||
package convert
 | 
					package convert
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/protocol/sdkws"
 | 
						"github.com/openimsdk/protocol/sdkws"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func UsersDB2Pb(users []*relationtb.UserModel) []*sdkws.UserInfo {
 | 
					func UsersDB2Pb(users []*relationtb.User) []*sdkws.UserInfo {
 | 
				
			||||||
	result := make([]*sdkws.UserInfo, 0, len(users))
 | 
						result := make([]*sdkws.UserInfo, 0, len(users))
 | 
				
			||||||
	for _, user := range users {
 | 
						for _, user := range users {
 | 
				
			||||||
		userPb := &sdkws.UserInfo{
 | 
							userPb := &sdkws.UserInfo{
 | 
				
			||||||
@ -38,8 +38,8 @@ func UsersDB2Pb(users []*relationtb.UserModel) []*sdkws.UserInfo {
 | 
				
			|||||||
	return result
 | 
						return result
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func UserPb2DB(user *sdkws.UserInfo) *relationtb.UserModel {
 | 
					func UserPb2DB(user *sdkws.UserInfo) *relationtb.User {
 | 
				
			||||||
	return &relationtb.UserModel{
 | 
						return &relationtb.User{
 | 
				
			||||||
		UserID:           user.UserID,
 | 
							UserID:           user.UserID,
 | 
				
			||||||
		Nickname:         user.Nickname,
 | 
							Nickname:         user.Nickname,
 | 
				
			||||||
		FaceURL:          user.FaceURL,
 | 
							FaceURL:          user.FaceURL,
 | 
				
			||||||
 | 
				
			|||||||
@ -15,17 +15,16 @@
 | 
				
			|||||||
package convert
 | 
					package convert
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"reflect"
 | 
						"reflect"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/protocol/sdkws"
 | 
						"github.com/openimsdk/protocol/sdkws"
 | 
				
			||||||
 | 
					 | 
				
			||||||
	relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestUsersDB2Pb(t *testing.T) {
 | 
					func TestUsersDB2Pb(t *testing.T) {
 | 
				
			||||||
	type args struct {
 | 
						type args struct {
 | 
				
			||||||
		users []*relationtb.UserModel
 | 
							users []*relationtb.User
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	tests := []struct {
 | 
						tests := []struct {
 | 
				
			||||||
		name       string
 | 
							name       string
 | 
				
			||||||
@ -50,7 +49,7 @@ func TestUserPb2DB(t *testing.T) {
 | 
				
			|||||||
	tests := []struct {
 | 
						tests := []struct {
 | 
				
			||||||
		name string
 | 
							name string
 | 
				
			||||||
		args args
 | 
							args args
 | 
				
			||||||
		want *relationtb.UserModel
 | 
							want *relationtb.User
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		// TODO: Add test cases.
 | 
							// TODO: Add test cases.
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										371
									
								
								pkg/common/db/cache/conversation.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										371
									
								
								pkg/common/db/cache/conversation.go
									
									
									
									
										vendored
									
									
								
							@ -1,371 +0,0 @@
 | 
				
			|||||||
// Copyright © 2023 OpenIM. All rights reserved.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
					 | 
				
			||||||
// you may not use this file except in compliance with the License.
 | 
					 | 
				
			||||||
// You may obtain a copy of the License at
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//     http://www.apache.org/licenses/LICENSE-2.0
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Unless required by applicable law or agreed to in writing, software
 | 
					 | 
				
			||||||
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
					 | 
				
			||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
					 | 
				
			||||||
// See the License for the specific language governing permissions and
 | 
					 | 
				
			||||||
// limitations under the License.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package cache
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"context"
 | 
					 | 
				
			||||||
	"math/big"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/dtm-labs/rockscache"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/cachekey"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
					 | 
				
			||||||
	relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/tools/log"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/tools/utils/datautil"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/tools/utils/encrypt"
 | 
					 | 
				
			||||||
	"github.com/redis/go-redis/v9"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	// ConversationKey                          = "CONVERSATION:"
 | 
					 | 
				
			||||||
	// conversationIDsKey                       = "CONVERSATION_IDS:"
 | 
					 | 
				
			||||||
	// conversationIDsHashKey                   = "CONVERSATION_IDS_HASH:"
 | 
					 | 
				
			||||||
	// conversationHasReadSeqKey                = "CONVERSATION_HAS_READ_SEQ:"
 | 
					 | 
				
			||||||
	// recvMsgOptKey                            = "RECV_MSG_OPT:"
 | 
					 | 
				
			||||||
	// superGroupRecvMsgNotNotifyUserIDsKey     = "SUPER_GROUP_RECV_MSG_NOT_NOTIFY_USER_IDS:"
 | 
					 | 
				
			||||||
	// superGroupRecvMsgNotNotifyUserIDsHashKey = "SUPER_GROUP_RECV_MSG_NOT_NOTIFY_USER_IDS_HASH:"
 | 
					 | 
				
			||||||
	// conversationNotReceiveMessageUserIDsKey  = "CONVERSATION_NOT_RECEIVE_MESSAGE_USER_IDS:".
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	conversationExpireTime = time.Second * 60 * 60 * 12
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// arg fn will exec when no data in msgCache.
 | 
					 | 
				
			||||||
type ConversationCache interface {
 | 
					 | 
				
			||||||
	metaCache
 | 
					 | 
				
			||||||
	NewCache() ConversationCache
 | 
					 | 
				
			||||||
	// get user's conversationIDs from msgCache
 | 
					 | 
				
			||||||
	GetUserConversationIDs(ctx context.Context, ownerUserID string) ([]string, error)
 | 
					 | 
				
			||||||
	DelConversationIDs(userIDs ...string) ConversationCache
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	GetUserConversationIDsHash(ctx context.Context, ownerUserID string) (hash uint64, err error)
 | 
					 | 
				
			||||||
	DelUserConversationIDsHash(ownerUserIDs ...string) ConversationCache
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// get one conversation from msgCache
 | 
					 | 
				
			||||||
	GetConversation(ctx context.Context, ownerUserID, conversationID string) (*relationtb.ConversationModel, error)
 | 
					 | 
				
			||||||
	DelConversations(ownerUserID string, conversationIDs ...string) ConversationCache
 | 
					 | 
				
			||||||
	DelUsersConversation(conversationID string, ownerUserIDs ...string) ConversationCache
 | 
					 | 
				
			||||||
	// get one conversation from msgCache
 | 
					 | 
				
			||||||
	GetConversations(ctx context.Context, ownerUserID string,
 | 
					 | 
				
			||||||
		conversationIDs []string) ([]*relationtb.ConversationModel, error)
 | 
					 | 
				
			||||||
	// get one user's all conversations from msgCache
 | 
					 | 
				
			||||||
	GetUserAllConversations(ctx context.Context, ownerUserID string) ([]*relationtb.ConversationModel, error)
 | 
					 | 
				
			||||||
	// get user conversation recv msg from msgCache
 | 
					 | 
				
			||||||
	GetUserRecvMsgOpt(ctx context.Context, ownerUserID, conversationID string) (opt int, err error)
 | 
					 | 
				
			||||||
	DelUserRecvMsgOpt(ownerUserID, conversationID string) ConversationCache
 | 
					 | 
				
			||||||
	// get one super group recv msg but do not notification userID list
 | 
					 | 
				
			||||||
	// GetSuperGroupRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) (userIDs []string, err error)
 | 
					 | 
				
			||||||
	DelSuperGroupRecvMsgNotNotifyUserIDs(groupID string) ConversationCache
 | 
					 | 
				
			||||||
	// get one super group recv msg but do not notification userID list hash
 | 
					 | 
				
			||||||
	// GetSuperGroupRecvMsgNotNotifyUserIDsHash(ctx context.Context, groupID string) (hash uint64, err error)
 | 
					 | 
				
			||||||
	DelSuperGroupRecvMsgNotNotifyUserIDsHash(groupID string) ConversationCache
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (map[string]int64, error)
 | 
					 | 
				
			||||||
	DelUserAllHasReadSeqs(ownerUserID string, conversationIDs ...string) ConversationCache
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	GetConversationsByConversationID(ctx context.Context,
 | 
					 | 
				
			||||||
		conversationIDs []string) ([]*relationtb.ConversationModel, error)
 | 
					 | 
				
			||||||
	DelConversationByConversationID(conversationIDs ...string) ConversationCache
 | 
					 | 
				
			||||||
	GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error)
 | 
					 | 
				
			||||||
	DelConversationNotReceiveMessageUserIDs(conversationIDs ...string) ConversationCache
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewConversationRedis(rdb redis.UniversalClient, localCache *config.LocalCache, opts rockscache.Options, db relationtb.ConversationModelInterface) ConversationCache {
 | 
					 | 
				
			||||||
	rcClient := rockscache.NewClient(rdb, opts)
 | 
					 | 
				
			||||||
	mc := NewMetaCacheRedis(rcClient)
 | 
					 | 
				
			||||||
	c := localCache.Conversation
 | 
					 | 
				
			||||||
	log.ZDebug(context.Background(), "black local cache init", "Topic", c.Topic, "SlotNum", c.SlotNum, "SlotSize", c.SlotSize, "enable", c.Enable())
 | 
					 | 
				
			||||||
	mc.SetTopic(c.Topic)
 | 
					 | 
				
			||||||
	mc.SetRawRedisClient(rdb)
 | 
					 | 
				
			||||||
	return &ConversationRedisCache{
 | 
					 | 
				
			||||||
		rcClient:       rcClient,
 | 
					 | 
				
			||||||
		metaCache:      mc,
 | 
					 | 
				
			||||||
		conversationDB: db,
 | 
					 | 
				
			||||||
		expireTime:     conversationExpireTime,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type ConversationRedisCache struct {
 | 
					 | 
				
			||||||
	metaCache
 | 
					 | 
				
			||||||
	rcClient       *rockscache.Client
 | 
					 | 
				
			||||||
	conversationDB relationtb.ConversationModelInterface
 | 
					 | 
				
			||||||
	expireTime     time.Duration
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// func NewNewConversationRedis(
 | 
					 | 
				
			||||||
//	rdb redis.UniversalClient,
 | 
					 | 
				
			||||||
//	conversationDB *relation.ConversationGorm,
 | 
					 | 
				
			||||||
//	options rockscache.Options,
 | 
					 | 
				
			||||||
// ) ConversationCache {
 | 
					 | 
				
			||||||
//	rcClient := rockscache.NewClient(rdb, options)
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//	return &ConversationRedisCache{
 | 
					 | 
				
			||||||
//		rcClient:       rcClient,
 | 
					 | 
				
			||||||
//		metaCache:      NewMetaCacheRedis(rcClient),
 | 
					 | 
				
			||||||
//		conversationDB: conversationDB,
 | 
					 | 
				
			||||||
//		expireTime:     conversationExpireTime,
 | 
					 | 
				
			||||||
//	}
 | 
					 | 
				
			||||||
//}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) NewCache() ConversationCache {
 | 
					 | 
				
			||||||
	return &ConversationRedisCache{
 | 
					 | 
				
			||||||
		rcClient:       c.rcClient,
 | 
					 | 
				
			||||||
		metaCache:      c.Copy(),
 | 
					 | 
				
			||||||
		conversationDB: c.conversationDB,
 | 
					 | 
				
			||||||
		expireTime:     c.expireTime,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) getConversationKey(ownerUserID, conversationID string) string {
 | 
					 | 
				
			||||||
	return cachekey.GetConversationKey(ownerUserID, conversationID)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) getConversationIDsKey(ownerUserID string) string {
 | 
					 | 
				
			||||||
	return cachekey.GetConversationIDsKey(ownerUserID)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) getSuperGroupRecvNotNotifyUserIDsKey(groupID string) string {
 | 
					 | 
				
			||||||
	return cachekey.GetSuperGroupRecvNotNotifyUserIDsKey(groupID)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) getRecvMsgOptKey(ownerUserID, conversationID string) string {
 | 
					 | 
				
			||||||
	return cachekey.GetRecvMsgOptKey(ownerUserID, conversationID)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) getSuperGroupRecvNotNotifyUserIDsHashKey(groupID string) string {
 | 
					 | 
				
			||||||
	return cachekey.GetSuperGroupRecvNotNotifyUserIDsHashKey(groupID)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) getConversationHasReadSeqKey(ownerUserID, conversationID string) string {
 | 
					 | 
				
			||||||
	return cachekey.GetConversationHasReadSeqKey(ownerUserID, conversationID)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) getConversationNotReceiveMessageUserIDsKey(conversationID string) string {
 | 
					 | 
				
			||||||
	return cachekey.GetConversationNotReceiveMessageUserIDsKey(conversationID)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) getUserConversationIDsHashKey(ownerUserID string) string {
 | 
					 | 
				
			||||||
	return cachekey.GetUserConversationIDsHashKey(ownerUserID)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) GetUserConversationIDs(ctx context.Context, ownerUserID string) ([]string, error) {
 | 
					 | 
				
			||||||
	return getCache(ctx, c.rcClient, c.getConversationIDsKey(ownerUserID), c.expireTime, func(ctx context.Context) ([]string, error) {
 | 
					 | 
				
			||||||
		return c.conversationDB.FindUserIDAllConversationID(ctx, ownerUserID)
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) DelConversationIDs(userIDs ...string) ConversationCache {
 | 
					 | 
				
			||||||
	keys := make([]string, 0, len(userIDs))
 | 
					 | 
				
			||||||
	for _, userID := range userIDs {
 | 
					 | 
				
			||||||
		keys = append(keys, c.getConversationIDsKey(userID))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	cache := c.NewCache()
 | 
					 | 
				
			||||||
	cache.AddKeys(keys...)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return cache
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) GetUserConversationIDsHash(ctx context.Context, ownerUserID string) (hash uint64, err error) {
 | 
					 | 
				
			||||||
	return getCache(
 | 
					 | 
				
			||||||
		ctx,
 | 
					 | 
				
			||||||
		c.rcClient,
 | 
					 | 
				
			||||||
		c.getUserConversationIDsHashKey(ownerUserID),
 | 
					 | 
				
			||||||
		c.expireTime,
 | 
					 | 
				
			||||||
		func(ctx context.Context) (uint64, error) {
 | 
					 | 
				
			||||||
			conversationIDs, err := c.GetUserConversationIDs(ctx, ownerUserID)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				return 0, err
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			datautil.Sort(conversationIDs, true)
 | 
					 | 
				
			||||||
			bi := big.NewInt(0)
 | 
					 | 
				
			||||||
			bi.SetString(encrypt.Md5(strings.Join(conversationIDs, ";"))[0:8], 16)
 | 
					 | 
				
			||||||
			return bi.Uint64(), nil
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) DelUserConversationIDsHash(ownerUserIDs ...string) ConversationCache {
 | 
					 | 
				
			||||||
	keys := make([]string, 0, len(ownerUserIDs))
 | 
					 | 
				
			||||||
	for _, ownerUserID := range ownerUserIDs {
 | 
					 | 
				
			||||||
		keys = append(keys, c.getUserConversationIDsHashKey(ownerUserID))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	cache := c.NewCache()
 | 
					 | 
				
			||||||
	cache.AddKeys(keys...)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return cache
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) GetConversation(ctx context.Context, ownerUserID, conversationID string) (*relationtb.ConversationModel, error) {
 | 
					 | 
				
			||||||
	return getCache(ctx, c.rcClient, c.getConversationKey(ownerUserID, conversationID), c.expireTime, func(ctx context.Context) (*relationtb.ConversationModel, error) {
 | 
					 | 
				
			||||||
		return c.conversationDB.Take(ctx, ownerUserID, conversationID)
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) DelConversations(ownerUserID string, conversationIDs ...string) ConversationCache {
 | 
					 | 
				
			||||||
	keys := make([]string, 0, len(conversationIDs))
 | 
					 | 
				
			||||||
	for _, conversationID := range conversationIDs {
 | 
					 | 
				
			||||||
		keys = append(keys, c.getConversationKey(ownerUserID, conversationID))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	cache := c.NewCache()
 | 
					 | 
				
			||||||
	cache.AddKeys(keys...)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return cache
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// func (c *ConversationRedisCache) getConversationIndex(convsation *relationtb.ConversationModel, keys []string) (int, error) {
 | 
					 | 
				
			||||||
// 	key := c.getConversationKey(convsation.OwnerUserID, convsation.ConversationID)
 | 
					 | 
				
			||||||
// 	for _i, _key := range keys {
 | 
					 | 
				
			||||||
// 		if _key == key {
 | 
					 | 
				
			||||||
// 			return _i, nil
 | 
					 | 
				
			||||||
// 		}
 | 
					 | 
				
			||||||
// 	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 	return 0, errs.New("not found key:" + key + " in keys")
 | 
					 | 
				
			||||||
// }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) GetConversations(ctx context.Context, ownerUserID string, conversationIDs []string) ([]*relationtb.ConversationModel, error) {
 | 
					 | 
				
			||||||
	// var keys []string
 | 
					 | 
				
			||||||
	// for _, conversarionID := range conversationIDs {
 | 
					 | 
				
			||||||
	//	keys = append(keys, c.getConversationKey(ownerUserID, conversarionID))
 | 
					 | 
				
			||||||
	//}
 | 
					 | 
				
			||||||
	// return batchGetCache(
 | 
					 | 
				
			||||||
	//	ctx,
 | 
					 | 
				
			||||||
	//	c.rcClient,
 | 
					 | 
				
			||||||
	//	keys,
 | 
					 | 
				
			||||||
	//	c.expireTime,
 | 
					 | 
				
			||||||
	//	c.getConversationIndex,
 | 
					 | 
				
			||||||
	//	func(ctx context.Context) ([]*relationtb.ConversationModel, error) {
 | 
					 | 
				
			||||||
	//		return c.conversationDB.Find(ctx, ownerUserID, conversationIDs)
 | 
					 | 
				
			||||||
	//	},
 | 
					 | 
				
			||||||
	//)
 | 
					 | 
				
			||||||
	return batchGetCache2(ctx, c.rcClient, c.expireTime, conversationIDs, func(conversationID string) string {
 | 
					 | 
				
			||||||
		return c.getConversationKey(ownerUserID, conversationID)
 | 
					 | 
				
			||||||
	}, func(ctx context.Context, conversationID string) (*relationtb.ConversationModel, error) {
 | 
					 | 
				
			||||||
		return c.conversationDB.Take(ctx, ownerUserID, conversationID)
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) GetUserAllConversations(ctx context.Context, ownerUserID string) ([]*relationtb.ConversationModel, error) {
 | 
					 | 
				
			||||||
	conversationIDs, err := c.GetUserConversationIDs(ctx, ownerUserID)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// var keys []string
 | 
					 | 
				
			||||||
	// for _, conversarionID := range conversationIDs {
 | 
					 | 
				
			||||||
	//	keys = append(keys, c.getConversationKey(ownerUserID, conversarionID))
 | 
					 | 
				
			||||||
	//}
 | 
					 | 
				
			||||||
	// return batchGetCache(
 | 
					 | 
				
			||||||
	//	ctx,
 | 
					 | 
				
			||||||
	//	c.rcClient,
 | 
					 | 
				
			||||||
	//	keys,
 | 
					 | 
				
			||||||
	//	c.expireTime,
 | 
					 | 
				
			||||||
	//	c.getConversationIndex,
 | 
					 | 
				
			||||||
	//	func(ctx context.Context) ([]*relationtb.ConversationModel, error) {
 | 
					 | 
				
			||||||
	//		return c.conversationDB.FindUserIDAllConversations(ctx, ownerUserID)
 | 
					 | 
				
			||||||
	//	},
 | 
					 | 
				
			||||||
	//)
 | 
					 | 
				
			||||||
	return c.GetConversations(ctx, ownerUserID, conversationIDs)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) GetUserRecvMsgOpt(ctx context.Context, ownerUserID, conversationID string) (opt int, err error) {
 | 
					 | 
				
			||||||
	return getCache(ctx, c.rcClient, c.getRecvMsgOptKey(ownerUserID, conversationID), c.expireTime, func(ctx context.Context) (opt int, err error) {
 | 
					 | 
				
			||||||
		return c.conversationDB.GetUserRecvMsgOpt(ctx, ownerUserID, conversationID)
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// func (c *ConversationRedisCache) GetSuperGroupRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) (userIDs []string, err error) {
 | 
					 | 
				
			||||||
//	return getCache(ctx, c.rcClient, c.getSuperGroupRecvNotNotifyUserIDsKey(groupID), c.expireTime, func(ctx context.Context) (userIDs []string, err error) {
 | 
					 | 
				
			||||||
//		return c.conversationDB.FindSuperGroupRecvMsgNotNotifyUserIDs(ctx, groupID)
 | 
					 | 
				
			||||||
//	})
 | 
					 | 
				
			||||||
//}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) DelUsersConversation(conversationID string, ownerUserIDs ...string) ConversationCache {
 | 
					 | 
				
			||||||
	keys := make([]string, 0, len(ownerUserIDs))
 | 
					 | 
				
			||||||
	for _, ownerUserID := range ownerUserIDs {
 | 
					 | 
				
			||||||
		keys = append(keys, c.getConversationKey(ownerUserID, conversationID))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	cache := c.NewCache()
 | 
					 | 
				
			||||||
	cache.AddKeys(keys...)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return cache
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) DelUserRecvMsgOpt(ownerUserID, conversationID string) ConversationCache {
 | 
					 | 
				
			||||||
	cache := c.NewCache()
 | 
					 | 
				
			||||||
	cache.AddKeys(c.getRecvMsgOptKey(ownerUserID, conversationID))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return cache
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) DelSuperGroupRecvMsgNotNotifyUserIDs(groupID string) ConversationCache {
 | 
					 | 
				
			||||||
	cache := c.NewCache()
 | 
					 | 
				
			||||||
	cache.AddKeys(c.getSuperGroupRecvNotNotifyUserIDsKey(groupID))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return cache
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// func (c *ConversationRedisCache) GetSuperGroupRecvMsgNotNotifyUserIDsHash(ctx context.Context, groupID string) (hash uint64, err error) {
 | 
					 | 
				
			||||||
//	return getCache(ctx, c.rcClient, c.getSuperGroupRecvNotNotifyUserIDsHashKey(groupID), c.expireTime, func(ctx context.Context) (hash uint64, err error) {
 | 
					 | 
				
			||||||
//		userIDs, err := c.GetSuperGroupRecvMsgNotNotifyUserIDs(ctx, groupID)
 | 
					 | 
				
			||||||
//		if err != nil {
 | 
					 | 
				
			||||||
//			return 0, err
 | 
					 | 
				
			||||||
//		}
 | 
					 | 
				
			||||||
//		utils.Sort(userIDs, true)
 | 
					 | 
				
			||||||
//		bi := big.NewInt(0)
 | 
					 | 
				
			||||||
//		bi.SetString(utils.Md5(strings.Join(userIDs, ";"))[0:8], 16)
 | 
					 | 
				
			||||||
//		return bi.Uint64(), nil
 | 
					 | 
				
			||||||
//	},
 | 
					 | 
				
			||||||
//	)
 | 
					 | 
				
			||||||
//}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) DelSuperGroupRecvMsgNotNotifyUserIDsHash(groupID string) ConversationCache {
 | 
					 | 
				
			||||||
	cache := c.NewCache()
 | 
					 | 
				
			||||||
	cache.AddKeys(c.getSuperGroupRecvNotNotifyUserIDsHashKey(groupID))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return cache
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) DelUserAllHasReadSeqs(ownerUserID string, conversationIDs ...string) ConversationCache {
 | 
					 | 
				
			||||||
	cache := c.NewCache()
 | 
					 | 
				
			||||||
	for _, conversationID := range conversationIDs {
 | 
					 | 
				
			||||||
		cache.AddKeys(c.getConversationHasReadSeqKey(ownerUserID, conversationID))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return cache
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*relationtb.ConversationModel, error) {
 | 
					 | 
				
			||||||
	panic("implement me")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) DelConversationByConversationID(conversationIDs ...string) ConversationCache {
 | 
					 | 
				
			||||||
	panic("implement me")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error) {
 | 
					 | 
				
			||||||
	return getCache(ctx, c.rcClient, c.getConversationNotReceiveMessageUserIDsKey(conversationID), c.expireTime, func(ctx context.Context) ([]string, error) {
 | 
					 | 
				
			||||||
		return c.conversationDB.GetConversationNotReceiveMessageUserIDs(ctx, conversationID)
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *ConversationRedisCache) DelConversationNotReceiveMessageUserIDs(conversationIDs ...string) ConversationCache {
 | 
					 | 
				
			||||||
	cache := c.NewCache()
 | 
					 | 
				
			||||||
	for _, conversationID := range conversationIDs {
 | 
					 | 
				
			||||||
		cache.AddKeys(c.getConversationNotReceiveMessageUserIDsKey(conversationID))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return cache
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										284
									
								
								pkg/common/db/cache/meta_cache.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										284
									
								
								pkg/common/db/cache/meta_cache.go
									
									
									
									
										vendored
									
									
								
							@ -1,284 +0,0 @@
 | 
				
			|||||||
// Copyright © 2023 OpenIM. All rights reserved.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
					 | 
				
			||||||
// you may not use this file except in compliance with the License.
 | 
					 | 
				
			||||||
// You may obtain a copy of the License at
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//     http://www.apache.org/licenses/LICENSE-2.0
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Unless required by applicable law or agreed to in writing, software
 | 
					 | 
				
			||||||
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
					 | 
				
			||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
					 | 
				
			||||||
// See the License for the specific language governing permissions and
 | 
					 | 
				
			||||||
// limitations under the License.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package cache
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"context"
 | 
					 | 
				
			||||||
	"encoding/json"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/dtm-labs/rockscache"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/tools/errs"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/tools/log"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/tools/mw/specialerror"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/tools/utils/datautil"
 | 
					 | 
				
			||||||
	"github.com/redis/go-redis/v9"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	scanCount     = 3000
 | 
					 | 
				
			||||||
	maxRetryTimes = 5
 | 
					 | 
				
			||||||
	retryInterval = time.Millisecond * 100
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var errIndex = errs.New("err index")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type metaCache interface {
 | 
					 | 
				
			||||||
	ExecDel(ctx context.Context, distinct ...bool) error
 | 
					 | 
				
			||||||
	// delete key rapid
 | 
					 | 
				
			||||||
	DelKey(ctx context.Context, key string) error
 | 
					 | 
				
			||||||
	AddKeys(keys ...string)
 | 
					 | 
				
			||||||
	ClearKeys()
 | 
					 | 
				
			||||||
	GetPreDelKeys() []string
 | 
					 | 
				
			||||||
	SetTopic(topic string)
 | 
					 | 
				
			||||||
	SetRawRedisClient(cli redis.UniversalClient)
 | 
					 | 
				
			||||||
	Copy() metaCache
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewMetaCacheRedis(rcClient *rockscache.Client, keys ...string) metaCache {
 | 
					 | 
				
			||||||
	return &metaCacheRedis{rcClient: rcClient, keys: keys, maxRetryTimes: maxRetryTimes, retryInterval: retryInterval}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type metaCacheRedis struct {
 | 
					 | 
				
			||||||
	topic         string
 | 
					 | 
				
			||||||
	rcClient      *rockscache.Client
 | 
					 | 
				
			||||||
	keys          []string
 | 
					 | 
				
			||||||
	maxRetryTimes int
 | 
					 | 
				
			||||||
	retryInterval time.Duration
 | 
					 | 
				
			||||||
	redisClient   redis.UniversalClient
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *metaCacheRedis) Copy() metaCache {
 | 
					 | 
				
			||||||
	var keys []string
 | 
					 | 
				
			||||||
	if len(m.keys) > 0 {
 | 
					 | 
				
			||||||
		keys = make([]string, 0, len(m.keys)*2)
 | 
					 | 
				
			||||||
		keys = append(keys, m.keys...)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return &metaCacheRedis{
 | 
					 | 
				
			||||||
		topic:         m.topic,
 | 
					 | 
				
			||||||
		rcClient:      m.rcClient,
 | 
					 | 
				
			||||||
		keys:          keys,
 | 
					 | 
				
			||||||
		maxRetryTimes: m.maxRetryTimes,
 | 
					 | 
				
			||||||
		retryInterval: m.retryInterval,
 | 
					 | 
				
			||||||
		redisClient:   m.redisClient,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *metaCacheRedis) SetTopic(topic string) {
 | 
					 | 
				
			||||||
	m.topic = topic
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *metaCacheRedis) SetRawRedisClient(cli redis.UniversalClient) {
 | 
					 | 
				
			||||||
	m.redisClient = cli
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *metaCacheRedis) ExecDel(ctx context.Context, distinct ...bool) error {
 | 
					 | 
				
			||||||
	if len(distinct) > 0 && distinct[0] {
 | 
					 | 
				
			||||||
		m.keys = datautil.Distinct(m.keys)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if len(m.keys) > 0 {
 | 
					 | 
				
			||||||
		log.ZDebug(ctx, "delete cache", "topic", m.topic, "keys", m.keys)
 | 
					 | 
				
			||||||
		for _, key := range m.keys {
 | 
					 | 
				
			||||||
			for i := 0; i < m.maxRetryTimes; i++ {
 | 
					 | 
				
			||||||
				if err := m.rcClient.TagAsDeleted(key); err != nil {
 | 
					 | 
				
			||||||
					log.ZError(ctx, "delete cache failed", err, "key", key)
 | 
					 | 
				
			||||||
					time.Sleep(m.retryInterval)
 | 
					 | 
				
			||||||
					continue
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				break
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if pk := getPublishKey(m.topic, m.keys); len(pk) > 0 {
 | 
					 | 
				
			||||||
			data, err := json.Marshal(pk)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				log.ZError(ctx, "keys json marshal failed", err, "topic", m.topic, "keys", pk)
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				if err := m.redisClient.Publish(ctx, m.topic, string(data)).Err(); err != nil {
 | 
					 | 
				
			||||||
					log.ZError(ctx, "redis publish cache delete error", err, "topic", m.topic, "keys", pk)
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *metaCacheRedis) DelKey(ctx context.Context, key string) error {
 | 
					 | 
				
			||||||
	return m.rcClient.TagAsDeleted2(ctx, key)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *metaCacheRedis) AddKeys(keys ...string) {
 | 
					 | 
				
			||||||
	m.keys = append(m.keys, keys...)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *metaCacheRedis) ClearKeys() {
 | 
					 | 
				
			||||||
	m.keys = []string{}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (m *metaCacheRedis) GetPreDelKeys() []string {
 | 
					 | 
				
			||||||
	return m.keys
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func GetDefaultOpt() rockscache.Options {
 | 
					 | 
				
			||||||
	opts := rockscache.NewDefaultOptions()
 | 
					 | 
				
			||||||
	opts.StrongConsistency = true
 | 
					 | 
				
			||||||
	opts.RandomExpireAdjustment = 0.2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return opts
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func getCache[T any](ctx context.Context, rcClient *rockscache.Client, key string, expire time.Duration, fn func(ctx context.Context) (T, error)) (T, error) {
 | 
					 | 
				
			||||||
	var t T
 | 
					 | 
				
			||||||
	var write bool
 | 
					 | 
				
			||||||
	v, err := rcClient.Fetch2(ctx, key, expire, func() (s string, err error) {
 | 
					 | 
				
			||||||
		t, err = fn(ctx)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return "", err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		bs, err := json.Marshal(t)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return "", errs.WrapMsg(err, "marshal failed")
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		write = true
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return string(bs), nil
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return t, errs.Wrap(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if write {
 | 
					 | 
				
			||||||
		return t, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if v == "" {
 | 
					 | 
				
			||||||
		return t, errs.ErrRecordNotFound.WrapMsg("cache is not found")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	err = json.Unmarshal([]byte(v), &t)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		errInfo := fmt.Sprintf("cache json.Unmarshal failed, key:%s, value:%s, expire:%s", key, v, expire)
 | 
					 | 
				
			||||||
		return t, errs.WrapMsg(err, errInfo)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return t, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// func batchGetCache[T any](ctx context.Context, rcClient *rockscache.Client, keys []string, expire time.Duration, keyIndexFn func(t T, keys []string) (int, error), fn func(ctx context.Context) ([]T,
 | 
					 | 
				
			||||||
// error)) ([]T, error) {
 | 
					 | 
				
			||||||
//	batchMap, err := rcClient.FetchBatch2(ctx, keys, expire, func(idxs []int) (m map[int]string, err error) {
 | 
					 | 
				
			||||||
//		values := make(map[int]string)
 | 
					 | 
				
			||||||
//		tArrays, err := fn(ctx)
 | 
					 | 
				
			||||||
//		if err != nil {
 | 
					 | 
				
			||||||
//			return nil, err
 | 
					 | 
				
			||||||
//		}
 | 
					 | 
				
			||||||
//		for _, v := range tArrays {
 | 
					 | 
				
			||||||
//			index, err := keyIndexFn(v, keys)
 | 
					 | 
				
			||||||
//			if err != nil {
 | 
					 | 
				
			||||||
//				continue
 | 
					 | 
				
			||||||
//			}
 | 
					 | 
				
			||||||
//			bs, err := json.Marshal(v)
 | 
					 | 
				
			||||||
//			if err != nil {
 | 
					 | 
				
			||||||
//				return nil, utils.Wrap(err, "marshal failed")
 | 
					 | 
				
			||||||
//			}
 | 
					 | 
				
			||||||
//			values[index] = string(bs)
 | 
					 | 
				
			||||||
//		}
 | 
					 | 
				
			||||||
//		return values, nil
 | 
					 | 
				
			||||||
//	})
 | 
					 | 
				
			||||||
//	if err != nil {
 | 
					 | 
				
			||||||
//		return nil, err
 | 
					 | 
				
			||||||
//	}
 | 
					 | 
				
			||||||
//	var tArrays []T
 | 
					 | 
				
			||||||
//	for _, v := range batchMap {
 | 
					 | 
				
			||||||
//		if v != "" {
 | 
					 | 
				
			||||||
//			var t T
 | 
					 | 
				
			||||||
//			err = json.Unmarshal([]byte(v), &t)
 | 
					 | 
				
			||||||
//			if err != nil {
 | 
					 | 
				
			||||||
//				return nil, utils.Wrap(err, "unmarshal failed")
 | 
					 | 
				
			||||||
//			}
 | 
					 | 
				
			||||||
//			tArrays = append(tArrays, t)
 | 
					 | 
				
			||||||
//		}
 | 
					 | 
				
			||||||
//	}
 | 
					 | 
				
			||||||
//	return tArrays, nil
 | 
					 | 
				
			||||||
//}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func batchGetCache2[T any, K comparable](
 | 
					 | 
				
			||||||
	ctx context.Context,
 | 
					 | 
				
			||||||
	rcClient *rockscache.Client,
 | 
					 | 
				
			||||||
	expire time.Duration,
 | 
					 | 
				
			||||||
	keys []K,
 | 
					 | 
				
			||||||
	keyFn func(key K) string,
 | 
					 | 
				
			||||||
	fns func(ctx context.Context, key K) (T, error),
 | 
					 | 
				
			||||||
) ([]T, error) {
 | 
					 | 
				
			||||||
	if len(keys) == 0 {
 | 
					 | 
				
			||||||
		return nil, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	res := make([]T, 0, len(keys))
 | 
					 | 
				
			||||||
	for _, key := range keys {
 | 
					 | 
				
			||||||
		val, err := getCache(ctx, rcClient, keyFn(key), expire, func(ctx context.Context) (T, error) {
 | 
					 | 
				
			||||||
			return fns(ctx, key)
 | 
					 | 
				
			||||||
		})
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			if errs.ErrRecordNotFound.Is(specialerror.ErrCode(errs.Unwrap(err))) {
 | 
					 | 
				
			||||||
				continue
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return nil, errs.Wrap(err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		res = append(res, val)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return res, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// func batchGetCacheMap[T any](
 | 
					 | 
				
			||||||
//	ctx context.Context,
 | 
					 | 
				
			||||||
//	rcClient *rockscache.Client,
 | 
					 | 
				
			||||||
//	keys, originKeys []string,
 | 
					 | 
				
			||||||
//	expire time.Duration,
 | 
					 | 
				
			||||||
//	keyIndexFn func(s string, keys []string) (int, error),
 | 
					 | 
				
			||||||
//	fn func(ctx context.Context) (map[string]T, error),
 | 
					 | 
				
			||||||
// ) (map[string]T, error) {
 | 
					 | 
				
			||||||
//	batchMap, err := rcClient.FetchBatch2(ctx, keys, expire, func(idxs []int) (m map[int]string, err error) {
 | 
					 | 
				
			||||||
//		tArrays, err := fn(ctx)
 | 
					 | 
				
			||||||
//		if err != nil {
 | 
					 | 
				
			||||||
//			return nil, err
 | 
					 | 
				
			||||||
//		}
 | 
					 | 
				
			||||||
//		values := make(map[int]string)
 | 
					 | 
				
			||||||
//		for k, v := range tArrays {
 | 
					 | 
				
			||||||
//			index, err := keyIndexFn(k, originKeys)
 | 
					 | 
				
			||||||
//			if err != nil {
 | 
					 | 
				
			||||||
//				continue
 | 
					 | 
				
			||||||
//			}
 | 
					 | 
				
			||||||
//			bs, err := json.Marshal(v)
 | 
					 | 
				
			||||||
//			if err != nil {
 | 
					 | 
				
			||||||
//				return nil, utils.Wrap(err, "marshal failed")
 | 
					 | 
				
			||||||
//			}
 | 
					 | 
				
			||||||
//			values[index] = string(bs)
 | 
					 | 
				
			||||||
//		}
 | 
					 | 
				
			||||||
//		return values, nil
 | 
					 | 
				
			||||||
//	})
 | 
					 | 
				
			||||||
//	if err != nil {
 | 
					 | 
				
			||||||
//		return nil, err
 | 
					 | 
				
			||||||
//	}
 | 
					 | 
				
			||||||
//	tMap := make(map[string]T)
 | 
					 | 
				
			||||||
//	for i, v := range batchMap {
 | 
					 | 
				
			||||||
//		if v != "" {
 | 
					 | 
				
			||||||
//			var t T
 | 
					 | 
				
			||||||
//			err = json.Unmarshal([]byte(v), &t)
 | 
					 | 
				
			||||||
//			if err != nil {
 | 
					 | 
				
			||||||
//				return nil, utils.Wrap(err, "unmarshal failed")
 | 
					 | 
				
			||||||
//			}
 | 
					 | 
				
			||||||
//			tMap[originKeys[i]] = t
 | 
					 | 
				
			||||||
//		}
 | 
					 | 
				
			||||||
//	}
 | 
					 | 
				
			||||||
//	return tMap, nil
 | 
					 | 
				
			||||||
//}
 | 
					 | 
				
			||||||
							
								
								
									
										85
									
								
								pkg/common/db/cache/third.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										85
									
								
								pkg/common/db/cache/third.go
									
									
									
									
										vendored
									
									
								
							@ -1,85 +0,0 @@
 | 
				
			|||||||
package cache
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"context"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/tools/errs"
 | 
					 | 
				
			||||||
	"github.com/redis/go-redis/v9"
 | 
					 | 
				
			||||||
	"strconv"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type ThirdCache interface {
 | 
					 | 
				
			||||||
	SetFcmToken(ctx context.Context, account string, platformID int, fcmToken string, expireTime int64) (err error)
 | 
					 | 
				
			||||||
	GetFcmToken(ctx context.Context, account string, platformID int) (string, error)
 | 
					 | 
				
			||||||
	DelFcmToken(ctx context.Context, account string, platformID int) error
 | 
					 | 
				
			||||||
	IncrUserBadgeUnreadCountSum(ctx context.Context, userID string) (int, error)
 | 
					 | 
				
			||||||
	SetUserBadgeUnreadCountSum(ctx context.Context, userID string, value int) error
 | 
					 | 
				
			||||||
	GetUserBadgeUnreadCountSum(ctx context.Context, userID string) (int, error)
 | 
					 | 
				
			||||||
	SetGetuiToken(ctx context.Context, token string, expireTime int64) error
 | 
					 | 
				
			||||||
	GetGetuiToken(ctx context.Context) (string, error)
 | 
					 | 
				
			||||||
	SetGetuiTaskID(ctx context.Context, taskID string, expireTime int64) error
 | 
					 | 
				
			||||||
	GetGetuiTaskID(ctx context.Context) (string, error)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewThirdCache(rdb redis.UniversalClient) ThirdCache {
 | 
					 | 
				
			||||||
	return &thirdCache{rdb: rdb}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type thirdCache struct {
 | 
					 | 
				
			||||||
	rdb redis.UniversalClient
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *thirdCache) SetFcmToken(ctx context.Context, account string, platformID int, fcmToken string, expireTime int64) (err error) {
 | 
					 | 
				
			||||||
	return errs.Wrap(c.rdb.Set(ctx, FCM_TOKEN+account+":"+strconv.Itoa(platformID), fcmToken, time.Duration(expireTime)*time.Second).Err())
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *thirdCache) GetFcmToken(ctx context.Context, account string, platformID int) (string, error) {
 | 
					 | 
				
			||||||
	val, err := c.rdb.Get(ctx, FCM_TOKEN+account+":"+strconv.Itoa(platformID)).Result()
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return "", errs.Wrap(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return val, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *thirdCache) DelFcmToken(ctx context.Context, account string, platformID int) error {
 | 
					 | 
				
			||||||
	return errs.Wrap(c.rdb.Del(ctx, FCM_TOKEN+account+":"+strconv.Itoa(platformID)).Err())
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *thirdCache) IncrUserBadgeUnreadCountSum(ctx context.Context, userID string) (int, error) {
 | 
					 | 
				
			||||||
	seq, err := c.rdb.Incr(ctx, userBadgeUnreadCountSum+userID).Result()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return int(seq), errs.Wrap(err)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *thirdCache) SetUserBadgeUnreadCountSum(ctx context.Context, userID string, value int) error {
 | 
					 | 
				
			||||||
	return errs.Wrap(c.rdb.Set(ctx, userBadgeUnreadCountSum+userID, value, 0).Err())
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *thirdCache) GetUserBadgeUnreadCountSum(ctx context.Context, userID string) (int, error) {
 | 
					 | 
				
			||||||
	val, err := c.rdb.Get(ctx, userBadgeUnreadCountSum+userID).Int()
 | 
					 | 
				
			||||||
	return val, errs.Wrap(err)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *thirdCache) SetGetuiToken(ctx context.Context, token string, expireTime int64) error {
 | 
					 | 
				
			||||||
	return errs.Wrap(c.rdb.Set(ctx, getuiToken, token, time.Duration(expireTime)*time.Second).Err())
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *thirdCache) GetGetuiToken(ctx context.Context) (string, error) {
 | 
					 | 
				
			||||||
	val, err := c.rdb.Get(ctx, getuiToken).Result()
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return "", errs.Wrap(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return val, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *thirdCache) SetGetuiTaskID(ctx context.Context, taskID string, expireTime int64) error {
 | 
					 | 
				
			||||||
	return errs.Wrap(c.rdb.Set(ctx, getuiTaskID, taskID, time.Duration(expireTime)*time.Second).Err())
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *thirdCache) GetGetuiTaskID(ctx context.Context) (string, error) {
 | 
					 | 
				
			||||||
	val, err := c.rdb.Get(ctx, getuiTaskID).Result()
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return "", errs.Wrap(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return val, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,15 +0,0 @@
 | 
				
			|||||||
// Copyright © 2024 OpenIM. All rights reserved.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
					 | 
				
			||||||
// you may not use this file except in compliance with the License.
 | 
					 | 
				
			||||||
// You may obtain a copy of the License at
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//     http://www.apache.org/licenses/LICENSE-2.0
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Unless required by applicable law or agreed to in writing, software
 | 
					 | 
				
			||||||
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
					 | 
				
			||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
					 | 
				
			||||||
// See the License for the specific language governing permissions and
 | 
					 | 
				
			||||||
// limitations under the License.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package relation // import "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
							
								
								
									
										17
									
								
								pkg/common/storage/cache/batchdeleter.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								pkg/common/storage/cache/batchdeleter.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					package cache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// BatchDeleter interface defines a set of methods for batch deleting cache and publishing deletion information.
 | 
				
			||||||
 | 
					type BatchDeleter interface {
 | 
				
			||||||
 | 
						//ChainExecDel method is used for chain calls and must call Clone to prevent memory pollution.
 | 
				
			||||||
 | 
						ChainExecDel(ctx context.Context) error
 | 
				
			||||||
 | 
						//ExecDelWithKeys method directly takes keys for deletion.
 | 
				
			||||||
 | 
						ExecDelWithKeys(ctx context.Context, keys []string) error
 | 
				
			||||||
 | 
						//Clone method creates a copy of the BatchDeleter to avoid modifying the original object.
 | 
				
			||||||
 | 
						Clone() BatchDeleter
 | 
				
			||||||
 | 
						//AddKeys method adds keys to be deleted.
 | 
				
			||||||
 | 
						AddKeys(keys ...string)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										27
									
								
								pkg/common/storage/cache/black.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								pkg/common/storage/cache/black.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					// Copyright © 2023 OpenIM. All rights reserved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package cache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type BlackCache interface {
 | 
				
			||||||
 | 
						BatchDeleter
 | 
				
			||||||
 | 
						CloneBlackCache() BlackCache
 | 
				
			||||||
 | 
						GetBlackIDs(ctx context.Context, userID string) (blackIDs []string, err error)
 | 
				
			||||||
 | 
						// del user's blackIDs msgCache, exec when a user's black list changed
 | 
				
			||||||
 | 
						DelBlackIDs(ctx context.Context, userID string) BlackCache
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -12,4 +12,4 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package cachekey // import "github.com/openimsdk/open-im-server/v3/pkg/common/cachekey"
 | 
					package cachekey // import "github.com/openimsdk/open-im-server/v3/pkg/common/storage/cachekey"
 | 
				
			||||||
							
								
								
									
										70
									
								
								pkg/common/storage/cache/cachekey/msg.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								pkg/common/storage/cache/cachekey/msg.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,70 @@
 | 
				
			|||||||
 | 
					// Copyright © 2024 OpenIM. All rights reserved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package cachekey
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/openimsdk/protocol/constant"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						messageCache         = "MESSAGE_CACHE:"
 | 
				
			||||||
 | 
						messageDelUserList   = "MESSAGE_DEL_USER_LIST:"
 | 
				
			||||||
 | 
						userDelMessagesList  = "USER_DEL_MESSAGES_LIST:"
 | 
				
			||||||
 | 
						sendMsgFailedFlag    = "SEND_MSG_FAILED_FLAG:"
 | 
				
			||||||
 | 
						exTypeKeyLocker      = "EX_LOCK:"
 | 
				
			||||||
 | 
						reactionExSingle     = "EX_SINGLE_"
 | 
				
			||||||
 | 
						reactionWriteGroup   = "EX_GROUP_"
 | 
				
			||||||
 | 
						reactionReadGroup    = "EX_SUPER_GROUP_"
 | 
				
			||||||
 | 
						reactionNotification = "EX_NOTIFICATION_"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetAllMessageCacheKey(conversationID string) string {
 | 
				
			||||||
 | 
						return messageCache + conversationID + "_*"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetMessageCacheKey(conversationID string, seq int64) string {
 | 
				
			||||||
 | 
						return messageCache + conversationID + "_" + strconv.Itoa(int(seq))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetMessageDelUserListKey(conversationID string, seq int64) string {
 | 
				
			||||||
 | 
						return messageDelUserList + conversationID + ":" + strconv.Itoa(int(seq))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetUserDelListKey(conversationID, userID string) string {
 | 
				
			||||||
 | 
						return userDelMessagesList + conversationID + ":" + userID
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetMessageReactionExKey(clientMsgID string, sessionType int32) string {
 | 
				
			||||||
 | 
						switch sessionType {
 | 
				
			||||||
 | 
						case constant.SingleChatType:
 | 
				
			||||||
 | 
							return reactionExSingle + clientMsgID
 | 
				
			||||||
 | 
						case constant.WriteGroupChatType:
 | 
				
			||||||
 | 
							return reactionWriteGroup + clientMsgID
 | 
				
			||||||
 | 
						case constant.ReadGroupChatType:
 | 
				
			||||||
 | 
							return reactionReadGroup + clientMsgID
 | 
				
			||||||
 | 
						case constant.NotificationChatType:
 | 
				
			||||||
 | 
							return reactionNotification + clientMsgID
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func GetLockMessageTypeKey(clientMsgID string, TypeKey string) string {
 | 
				
			||||||
 | 
						return exTypeKeyLocker + clientMsgID + "_" + TypeKey
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetSendMsgKey(id string) string {
 | 
				
			||||||
 | 
						return sendMsgFailedFlag + id
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										40
									
								
								pkg/common/storage/cache/cachekey/s3.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								pkg/common/storage/cache/cachekey/s3.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					// Copyright © 2024 OpenIM. All rights reserved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package cachekey
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						object         = "OBJECT:"
 | 
				
			||||||
 | 
						s3             = "S3:"
 | 
				
			||||||
 | 
						minioImageInfo = "MINIO:IMAGE:"
 | 
				
			||||||
 | 
						minioThumbnail = "MINIO:THUMBNAIL:"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetObjectKey(engine string, name string) string {
 | 
				
			||||||
 | 
						return object + engine + ":" + name
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetS3Key(engine string, name string) string {
 | 
				
			||||||
 | 
						return s3 + engine + ":" + name
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetObjectImageInfoKey(key string) string {
 | 
				
			||||||
 | 
						return minioImageInfo + key
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetMinioImageThumbnailKey(key string, format string, width int, height int) string {
 | 
				
			||||||
 | 
						return minioThumbnail + format + ":w" + strconv.Itoa(width) + ":h" + strconv.Itoa(height) + ":" + key
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										38
									
								
								pkg/common/storage/cache/cachekey/seq.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								pkg/common/storage/cache/cachekey/seq.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					// Copyright © 2024 OpenIM. All rights reserved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package cachekey
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						maxSeq                 = "MAX_SEQ:"
 | 
				
			||||||
 | 
						minSeq                 = "MIN_SEQ:"
 | 
				
			||||||
 | 
						conversationUserMinSeq = "CON_USER_MIN_SEQ:"
 | 
				
			||||||
 | 
						hasReadSeq             = "HAS_READ_SEQ:"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetMaxSeqKey(conversationID string) string {
 | 
				
			||||||
 | 
						return maxSeq + conversationID
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetMinSeqKey(conversationID string) string {
 | 
				
			||||||
 | 
						return minSeq + conversationID
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetHasReadSeqKey(conversationID string, userID string) string {
 | 
				
			||||||
 | 
						return hasReadSeq + userID + ":" + conversationID
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetConversationUserMinSeqKey(conversationID, userID string) string {
 | 
				
			||||||
 | 
						return conversationUserMinSeq + conversationID + "u:" + userID
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										41
									
								
								pkg/common/storage/cache/cachekey/third.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								pkg/common/storage/cache/cachekey/third.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					// Copyright © 2024 OpenIM. All rights reserved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package cachekey
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						getuiToken              = "GETUI_TOKEN"
 | 
				
			||||||
 | 
						getuiTaskID             = "GETUI_TASK_ID"
 | 
				
			||||||
 | 
						fmcToken                = "FCM_TOKEN:"
 | 
				
			||||||
 | 
						userBadgeUnreadCountSum = "USER_BADGE_UNREAD_COUNT_SUM:"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetFcmAccountTokenKey(account string, platformID int) string {
 | 
				
			||||||
 | 
						return fmcToken + account + ":" + strconv.Itoa(platformID)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetUserBadgeUnreadCountSumKey(userID string) string {
 | 
				
			||||||
 | 
						return userBadgeUnreadCountSum + userID
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetGetuiTokenKey() string {
 | 
				
			||||||
 | 
						return getuiToken
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func GetGetuiTaskIDKey() string {
 | 
				
			||||||
 | 
						return getuiTaskID
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -17,6 +17,7 @@ package cachekey
 | 
				
			|||||||
const (
 | 
					const (
 | 
				
			||||||
	UserInfoKey             = "USER_INFO:"
 | 
						UserInfoKey             = "USER_INFO:"
 | 
				
			||||||
	UserGlobalRecvMsgOptKey = "USER_GLOBAL_RECV_MSG_OPT_KEY:"
 | 
						UserGlobalRecvMsgOptKey = "USER_GLOBAL_RECV_MSG_OPT_KEY:"
 | 
				
			||||||
 | 
						olineStatusKey          = "ONLINE_STATUS:"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func GetUserInfoKey(userID string) string {
 | 
					func GetUserInfoKey(userID string) string {
 | 
				
			||||||
@ -26,3 +27,7 @@ func GetUserInfoKey(userID string) string {
 | 
				
			|||||||
func GetUserGlobalRecvMsgOptKey(userID string) string {
 | 
					func GetUserGlobalRecvMsgOptKey(userID string) string {
 | 
				
			||||||
	return UserGlobalRecvMsgOptKey + userID
 | 
						return UserGlobalRecvMsgOptKey + userID
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetOnlineStatusKey(modKey string) string {
 | 
				
			||||||
 | 
						return olineStatusKey + modKey
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										60
									
								
								pkg/common/storage/cache/conversation.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								pkg/common/storage/cache/conversation.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,60 @@
 | 
				
			|||||||
 | 
					// Copyright © 2023 OpenIM. All rights reserved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package cache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// arg fn will exec when no data in msgCache.
 | 
				
			||||||
 | 
					type ConversationCache interface {
 | 
				
			||||||
 | 
						BatchDeleter
 | 
				
			||||||
 | 
						CloneConversationCache() ConversationCache
 | 
				
			||||||
 | 
						// get user's conversationIDs from msgCache
 | 
				
			||||||
 | 
						GetUserConversationIDs(ctx context.Context, ownerUserID string) ([]string, error)
 | 
				
			||||||
 | 
						DelConversationIDs(userIDs ...string) ConversationCache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						GetUserConversationIDsHash(ctx context.Context, ownerUserID string) (hash uint64, err error)
 | 
				
			||||||
 | 
						DelUserConversationIDsHash(ownerUserIDs ...string) ConversationCache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// get one conversation from msgCache
 | 
				
			||||||
 | 
						GetConversation(ctx context.Context, ownerUserID, conversationID string) (*relationtb.Conversation, error)
 | 
				
			||||||
 | 
						DelConversations(ownerUserID string, conversationIDs ...string) ConversationCache
 | 
				
			||||||
 | 
						DelUsersConversation(conversationID string, ownerUserIDs ...string) ConversationCache
 | 
				
			||||||
 | 
						// get one conversation from msgCache
 | 
				
			||||||
 | 
						GetConversations(ctx context.Context, ownerUserID string,
 | 
				
			||||||
 | 
							conversationIDs []string) ([]*relationtb.Conversation, error)
 | 
				
			||||||
 | 
						// get one user's all conversations from msgCache
 | 
				
			||||||
 | 
						GetUserAllConversations(ctx context.Context, ownerUserID string) ([]*relationtb.Conversation, error)
 | 
				
			||||||
 | 
						// get user conversation recv msg from msgCache
 | 
				
			||||||
 | 
						GetUserRecvMsgOpt(ctx context.Context, ownerUserID, conversationID string) (opt int, err error)
 | 
				
			||||||
 | 
						DelUserRecvMsgOpt(ownerUserID, conversationID string) ConversationCache
 | 
				
			||||||
 | 
						// get one super group recv msg but do not notification userID list
 | 
				
			||||||
 | 
						// GetSuperGroupRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) (userIDs []string, err error)
 | 
				
			||||||
 | 
						DelSuperGroupRecvMsgNotNotifyUserIDs(groupID string) ConversationCache
 | 
				
			||||||
 | 
						// get one super group recv msg but do not notification userID list hash
 | 
				
			||||||
 | 
						// GetSuperGroupRecvMsgNotNotifyUserIDsHash(ctx context.Context, groupID string) (hash uint64, err error)
 | 
				
			||||||
 | 
						DelSuperGroupRecvMsgNotNotifyUserIDsHash(groupID string) ConversationCache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (map[string]int64, error)
 | 
				
			||||||
 | 
						DelUserAllHasReadSeqs(ownerUserID string, conversationIDs ...string) ConversationCache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						GetConversationsByConversationID(ctx context.Context,
 | 
				
			||||||
 | 
							conversationIDs []string) ([]*relationtb.Conversation, error)
 | 
				
			||||||
 | 
						DelConversationByConversationID(conversationIDs ...string) ConversationCache
 | 
				
			||||||
 | 
						GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error)
 | 
				
			||||||
 | 
						DelConversationNotReceiveMessageUserIDs(conversationIDs ...string) ConversationCache
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -12,4 +12,4 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package cache // import "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
 | 
					package cache // import "github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
 | 
				
			||||||
							
								
								
									
										35
									
								
								pkg/common/storage/cache/friend.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								pkg/common/storage/cache/friend.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					// Copyright © 2023 OpenIM. All rights reserved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package cache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// FriendCache is an interface for caching friend-related data.
 | 
				
			||||||
 | 
					type FriendCache interface {
 | 
				
			||||||
 | 
						BatchDeleter
 | 
				
			||||||
 | 
						CloneFriendCache() FriendCache
 | 
				
			||||||
 | 
						GetFriendIDs(ctx context.Context, ownerUserID string) (friendIDs []string, err error)
 | 
				
			||||||
 | 
						// Called when friendID list changed
 | 
				
			||||||
 | 
						DelFriendIDs(ownerUserID ...string) FriendCache
 | 
				
			||||||
 | 
						// Get single friendInfo from the cache
 | 
				
			||||||
 | 
						GetFriend(ctx context.Context, ownerUserID, friendUserID string) (friend *relationtb.Friend, err error)
 | 
				
			||||||
 | 
						// Delete friend when friend info changed
 | 
				
			||||||
 | 
						DelFriend(ownerUserID, friendUserID string) FriendCache
 | 
				
			||||||
 | 
						// Delete friends when friends' info changed
 | 
				
			||||||
 | 
						DelFriends(ownerUserID string, friendUserIDs []string) FriendCache
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										62
									
								
								pkg/common/storage/cache/group.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								pkg/common/storage/cache/group.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,62 @@
 | 
				
			|||||||
 | 
					// Copyright © 2023 OpenIM. All rights reserved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package cache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/common"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type GroupHash interface {
 | 
				
			||||||
 | 
						GetGroupHash(ctx context.Context, groupID string) (uint64, error)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type GroupCache interface {
 | 
				
			||||||
 | 
						BatchDeleter
 | 
				
			||||||
 | 
						CloneGroupCache() GroupCache
 | 
				
			||||||
 | 
						GetGroupsInfo(ctx context.Context, groupIDs []string) (groups []*model.Group, err error)
 | 
				
			||||||
 | 
						GetGroupInfo(ctx context.Context, groupID string) (group *model.Group, err error)
 | 
				
			||||||
 | 
						DelGroupsInfo(groupIDs ...string) GroupCache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						GetGroupMembersHash(ctx context.Context, groupID string) (hashCode uint64, err error)
 | 
				
			||||||
 | 
						GetGroupMemberHashMap(ctx context.Context, groupIDs []string) (map[string]*common.GroupSimpleUserID, error)
 | 
				
			||||||
 | 
						DelGroupMembersHash(groupID string) GroupCache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						GetGroupMemberIDs(ctx context.Context, groupID string) (groupMemberIDs []string, err error)
 | 
				
			||||||
 | 
						GetGroupsMemberIDs(ctx context.Context, groupIDs []string) (groupMemberIDs map[string][]string, err error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DelGroupMemberIDs(groupID string) GroupCache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						GetJoinedGroupIDs(ctx context.Context, userID string) (joinedGroupIDs []string, err error)
 | 
				
			||||||
 | 
						DelJoinedGroupID(userID ...string) GroupCache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						GetGroupMemberInfo(ctx context.Context, groupID, userID string) (groupMember *model.GroupMember, err error)
 | 
				
			||||||
 | 
						GetGroupMembersInfo(ctx context.Context, groupID string, userID []string) (groupMembers []*model.GroupMember, err error)
 | 
				
			||||||
 | 
						GetAllGroupMembersInfo(ctx context.Context, groupID string) (groupMembers []*model.GroupMember, err error)
 | 
				
			||||||
 | 
						GetGroupMembersPage(ctx context.Context, groupID string, userID []string, showNumber, pageNumber int32) (total uint32, groupMembers []*model.GroupMember, err error)
 | 
				
			||||||
 | 
						FindGroupMemberUser(ctx context.Context, groupIDs []string, userID string) ([]*model.GroupMember, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						GetGroupRoleLevelMemberIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error)
 | 
				
			||||||
 | 
						GetGroupOwner(ctx context.Context, groupID string) (*model.GroupMember, error)
 | 
				
			||||||
 | 
						GetGroupsOwner(ctx context.Context, groupIDs []string) ([]*model.GroupMember, error)
 | 
				
			||||||
 | 
						DelGroupRoleLevel(groupID string, roleLevel []int32) GroupCache
 | 
				
			||||||
 | 
						DelGroupAllRoleLevel(groupID string) GroupCache
 | 
				
			||||||
 | 
						DelGroupMembersInfo(groupID string, userID ...string) GroupCache
 | 
				
			||||||
 | 
						GetGroupRoleLevelMemberInfo(ctx context.Context, groupID string, roleLevel int32) ([]*model.GroupMember, error)
 | 
				
			||||||
 | 
						GetGroupRolesLevelMemberInfo(ctx context.Context, groupID string, roleLevels []int32) ([]*model.GroupMember, error)
 | 
				
			||||||
 | 
						GetGroupMemberNum(ctx context.Context, groupID string) (memberNum int64, err error)
 | 
				
			||||||
 | 
						DelGroupsMemberNum(groupID ...string) GroupCache
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										43
									
								
								pkg/common/storage/cache/msg.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								pkg/common/storage/cache/msg.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					// Copyright © 2023 OpenIM. All rights reserved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package cache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/openimsdk/protocol/sdkws"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type MsgCache interface {
 | 
				
			||||||
 | 
						GetMessagesBySeq(ctx context.Context, conversationID string, seqs []int64) (seqMsg []*sdkws.MsgData, failedSeqList []int64, err error)
 | 
				
			||||||
 | 
						SetMessageToCache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) (int, error)
 | 
				
			||||||
 | 
						UserDeleteMsgs(ctx context.Context, conversationID string, seqs []int64, userID string) error
 | 
				
			||||||
 | 
						DelUserDeleteMsgsList(ctx context.Context, conversationID string, seqs []int64)
 | 
				
			||||||
 | 
						DeleteMessages(ctx context.Context, conversationID string, seqs []int64) error
 | 
				
			||||||
 | 
						GetUserDelList(ctx context.Context, userID, conversationID string) (seqs []int64, err error)
 | 
				
			||||||
 | 
						CleanUpOneConversationAllMsg(ctx context.Context, conversationID string) error
 | 
				
			||||||
 | 
						DelMsgFromCache(ctx context.Context, userID string, seqList []int64) error
 | 
				
			||||||
 | 
						SetSendMsgStatus(ctx context.Context, id string, status int32) error
 | 
				
			||||||
 | 
						GetSendMsgStatus(ctx context.Context, id string) (int32, error)
 | 
				
			||||||
 | 
						JudgeMessageReactionExist(ctx context.Context, clientMsgID string, sessionType int32) (bool, error)
 | 
				
			||||||
 | 
						GetOneMessageAllReactionList(ctx context.Context, clientMsgID string, sessionType int32) (map[string]string, error)
 | 
				
			||||||
 | 
						DeleteOneMessageKey(ctx context.Context, clientMsgID string, sessionType int32, subKey string) error
 | 
				
			||||||
 | 
						SetMessageReactionExpire(ctx context.Context, clientMsgID string, sessionType int32, expiration time.Duration) (bool, error)
 | 
				
			||||||
 | 
						GetMessageTypeKeyValue(ctx context.Context, clientMsgID string, sessionType int32, typeKey string) (string, error)
 | 
				
			||||||
 | 
						SetMessageTypeKeyValue(ctx context.Context, clientMsgID string, sessionType int32, typeKey, value string) error
 | 
				
			||||||
 | 
						LockMessageTypeKey(ctx context.Context, clientMsgID string, TypeKey string) error
 | 
				
			||||||
 | 
						UnLockMessageTypeKey(ctx context.Context, clientMsgID string, TypeKey string) error
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										211
									
								
								pkg/common/storage/cache/redis/batchdeleter.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										211
									
								
								pkg/common/storage/cache/redis/batchdeleter.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,211 @@
 | 
				
			|||||||
 | 
					// Copyright © 2023 OpenIM. All rights reserved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package redis
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"github.com/dtm-labs/rockscache"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/localcache"
 | 
				
			||||||
 | 
						"github.com/openimsdk/tools/errs"
 | 
				
			||||||
 | 
						"github.com/openimsdk/tools/log"
 | 
				
			||||||
 | 
						"github.com/openimsdk/tools/mw/specialerror"
 | 
				
			||||||
 | 
						"github.com/openimsdk/tools/utils/datautil"
 | 
				
			||||||
 | 
						"github.com/redis/go-redis/v9"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// BatchDeleterRedis is a concrete implementation of the BatchDeleter interface based on Redis and RocksCache.
 | 
				
			||||||
 | 
					type BatchDeleterRedis struct {
 | 
				
			||||||
 | 
						redisClient    redis.UniversalClient
 | 
				
			||||||
 | 
						keys           []string
 | 
				
			||||||
 | 
						rocksClient    *rockscache.Client
 | 
				
			||||||
 | 
						redisPubTopics []string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewBatchDeleterRedis creates a new BatchDeleterRedis instance.
 | 
				
			||||||
 | 
					func NewBatchDeleterRedis(redisClient redis.UniversalClient, options *rockscache.Options, redisPubTopics []string) *BatchDeleterRedis {
 | 
				
			||||||
 | 
						return &BatchDeleterRedis{
 | 
				
			||||||
 | 
							redisClient:    redisClient,
 | 
				
			||||||
 | 
							rocksClient:    rockscache.NewClient(redisClient, *options),
 | 
				
			||||||
 | 
							redisPubTopics: redisPubTopics,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ExecDelWithKeys directly takes keys for batch deletion and publishes deletion information.
 | 
				
			||||||
 | 
					func (c *BatchDeleterRedis) ExecDelWithKeys(ctx context.Context, keys []string) error {
 | 
				
			||||||
 | 
						distinctKeys := datautil.Distinct(keys)
 | 
				
			||||||
 | 
						return c.execDel(ctx, distinctKeys)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ChainExecDel is used for chain calls for batch deletion. It must call Clone to prevent memory pollution.
 | 
				
			||||||
 | 
					func (c *BatchDeleterRedis) ChainExecDel(ctx context.Context) error {
 | 
				
			||||||
 | 
						distinctKeys := datautil.Distinct(c.keys)
 | 
				
			||||||
 | 
						return c.execDel(ctx, distinctKeys)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// execDel performs batch deletion and publishes the keys that have been deleted to update the local cache information of other nodes.
 | 
				
			||||||
 | 
					func (c *BatchDeleterRedis) execDel(ctx context.Context, keys []string) error {
 | 
				
			||||||
 | 
						if len(keys) > 0 {
 | 
				
			||||||
 | 
							log.ZDebug(ctx, "delete cache", "topic", c.redisPubTopics, "keys", keys)
 | 
				
			||||||
 | 
							slotMapKeys, err := groupKeysBySlot(ctx, c.redisClient, keys)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// Batch delete keys
 | 
				
			||||||
 | 
							for slot, singleSlotKeys := range slotMapKeys {
 | 
				
			||||||
 | 
								if err := c.rocksClient.TagAsDeletedBatch2(ctx, singleSlotKeys); err != nil {
 | 
				
			||||||
 | 
									log.ZWarn(ctx, "Batch delete cache failed", err, "slot", slot, "keys", singleSlotKeys)
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// Publish the keys that have been deleted to Redis to update the local cache information of other nodes
 | 
				
			||||||
 | 
							if len(c.redisPubTopics) > 0 && len(keys) > 0 {
 | 
				
			||||||
 | 
								keysByTopic := localcache.GetPublishKeysByTopic(c.redisPubTopics, keys)
 | 
				
			||||||
 | 
								for topic, keys := range keysByTopic {
 | 
				
			||||||
 | 
									if len(keys) > 0 {
 | 
				
			||||||
 | 
										data, err := json.Marshal(keys)
 | 
				
			||||||
 | 
										if err != nil {
 | 
				
			||||||
 | 
											log.ZWarn(ctx, "keys json marshal failed", err, "topic", topic, "keys", keys)
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											if err := c.redisClient.Publish(ctx, topic, string(data)).Err(); err != nil {
 | 
				
			||||||
 | 
												log.ZWarn(ctx, "redis publish cache delete error", err, "topic", topic, "keys", keys)
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Clone creates a copy of BatchDeleterRedis for chain calls to prevent memory pollution.
 | 
				
			||||||
 | 
					func (c *BatchDeleterRedis) Clone() cache.BatchDeleter {
 | 
				
			||||||
 | 
						return &BatchDeleterRedis{
 | 
				
			||||||
 | 
							redisClient:    c.redisClient,
 | 
				
			||||||
 | 
							keys:           c.keys,
 | 
				
			||||||
 | 
							rocksClient:    c.rocksClient,
 | 
				
			||||||
 | 
							redisPubTopics: c.redisPubTopics,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AddKeys adds keys to be deleted.
 | 
				
			||||||
 | 
					func (c *BatchDeleterRedis) AddKeys(keys ...string) {
 | 
				
			||||||
 | 
						c.keys = append(c.keys, keys...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetRocksCacheOptions returns the default configuration options for RocksCache.
 | 
				
			||||||
 | 
					func GetRocksCacheOptions() *rockscache.Options {
 | 
				
			||||||
 | 
						opts := rockscache.NewDefaultOptions()
 | 
				
			||||||
 | 
						opts.StrongConsistency = true
 | 
				
			||||||
 | 
						opts.RandomExpireAdjustment = 0.2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &opts
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// groupKeysBySlot groups keys by their Redis cluster hash slots.
 | 
				
			||||||
 | 
					func groupKeysBySlot(ctx context.Context, redisClient redis.UniversalClient, keys []string) (map[int64][]string, error) {
 | 
				
			||||||
 | 
						slots := make(map[int64][]string)
 | 
				
			||||||
 | 
						clusterClient, isCluster := redisClient.(*redis.ClusterClient)
 | 
				
			||||||
 | 
						if isCluster {
 | 
				
			||||||
 | 
							pipe := clusterClient.Pipeline()
 | 
				
			||||||
 | 
							cmds := make([]*redis.IntCmd, len(keys))
 | 
				
			||||||
 | 
							for i, key := range keys {
 | 
				
			||||||
 | 
								cmds[i] = pipe.ClusterKeySlot(ctx, key)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							_, err := pipe.Exec(ctx)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, errs.WrapMsg(err, "get slot err")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for i, cmd := range cmds {
 | 
				
			||||||
 | 
								slot, err := cmd.Result()
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									log.ZWarn(ctx, "some key get slot err", err, "key", keys[i])
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								slots[slot] = append(slots[slot], keys[i])
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							// If not a cluster client, put all keys in the same slot (0)
 | 
				
			||||||
 | 
							slots[0] = keys
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return slots, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getCache[T any](ctx context.Context, rcClient *rockscache.Client, key string, expire time.Duration, fn func(ctx context.Context) (T, error)) (T, error) {
 | 
				
			||||||
 | 
						var t T
 | 
				
			||||||
 | 
						var write bool
 | 
				
			||||||
 | 
						v, err := rcClient.Fetch2(ctx, key, expire, func() (s string, err error) {
 | 
				
			||||||
 | 
							t, err = fn(ctx)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return "", err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							bs, err := json.Marshal(t)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return "", errs.WrapMsg(err, "marshal failed")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							write = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return string(bs), nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return t, errs.Wrap(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if write {
 | 
				
			||||||
 | 
							return t, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if v == "" {
 | 
				
			||||||
 | 
							return t, errs.ErrRecordNotFound.WrapMsg("cache is not found")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err = json.Unmarshal([]byte(v), &t)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							errInfo := fmt.Sprintf("cache json.Unmarshal failed, key:%s, value:%s, expire:%s", key, v, expire)
 | 
				
			||||||
 | 
							return t, errs.WrapMsg(err, errInfo)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return t, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func batchGetCache[T any, K comparable](
 | 
				
			||||||
 | 
						ctx context.Context,
 | 
				
			||||||
 | 
						rcClient *rockscache.Client,
 | 
				
			||||||
 | 
						expire time.Duration,
 | 
				
			||||||
 | 
						keys []K,
 | 
				
			||||||
 | 
						keyFn func(key K) string,
 | 
				
			||||||
 | 
						fns func(ctx context.Context, key K) (T, error),
 | 
				
			||||||
 | 
					) ([]T, error) {
 | 
				
			||||||
 | 
						if len(keys) == 0 {
 | 
				
			||||||
 | 
							return nil, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						res := make([]T, 0, len(keys))
 | 
				
			||||||
 | 
						for _, key := range keys {
 | 
				
			||||||
 | 
							val, err := getCache(ctx, rcClient, keyFn(key), expire, func(ctx context.Context) (T, error) {
 | 
				
			||||||
 | 
								return fns(ctx, key)
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								if errs.ErrRecordNotFound.Is(specialerror.ErrCode(errs.Unwrap(err))) {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return nil, errs.Wrap(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							res = append(res, val)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return res, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -12,63 +12,49 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package cache
 | 
					package redis
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/dtm-labs/rockscache"
 | 
						"github.com/dtm-labs/rockscache"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/cachekey"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
				
			||||||
	relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/cachekey"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
 | 
				
			||||||
	"github.com/openimsdk/tools/log"
 | 
						"github.com/openimsdk/tools/log"
 | 
				
			||||||
	"github.com/redis/go-redis/v9"
 | 
						"github.com/redis/go-redis/v9"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	blackIDsKey     = "BLACK_IDS:"
 | 
					 | 
				
			||||||
	blackExpireTime = time.Second * 60 * 60 * 12
 | 
						blackExpireTime = time.Second * 60 * 60 * 12
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// args fn will exec when no data in msgCache.
 | 
					 | 
				
			||||||
type BlackCache interface {
 | 
					 | 
				
			||||||
	// get blackIDs from msgCache
 | 
					 | 
				
			||||||
	metaCache
 | 
					 | 
				
			||||||
	NewCache() BlackCache
 | 
					 | 
				
			||||||
	GetBlackIDs(ctx context.Context, userID string) (blackIDs []string, err error)
 | 
					 | 
				
			||||||
	// del user's blackIDs msgCache, exec when a user's black list changed
 | 
					 | 
				
			||||||
	DelBlackIDs(ctx context.Context, userID string) BlackCache
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type BlackCacheRedis struct {
 | 
					type BlackCacheRedis struct {
 | 
				
			||||||
	metaCache
 | 
						cache.BatchDeleter
 | 
				
			||||||
	expireTime time.Duration
 | 
						expireTime time.Duration
 | 
				
			||||||
	rcClient   *rockscache.Client
 | 
						rcClient   *rockscache.Client
 | 
				
			||||||
	blackDB    relationtb.BlackModelInterface
 | 
						blackDB    database.Black
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewBlackCacheRedis(rdb redis.UniversalClient, localCache *config.LocalCache, blackDB relationtb.BlackModelInterface, options rockscache.Options) BlackCache {
 | 
					func NewBlackCacheRedis(rdb redis.UniversalClient, localCache *config.LocalCache, blackDB database.Black, options *rockscache.Options) cache.BlackCache {
 | 
				
			||||||
	rcClient := rockscache.NewClient(rdb, options)
 | 
						batchHandler := NewBatchDeleterRedis(rdb, options, []string{localCache.Friend.Topic})
 | 
				
			||||||
	mc := NewMetaCacheRedis(rcClient)
 | 
					 | 
				
			||||||
	b := localCache.Friend
 | 
						b := localCache.Friend
 | 
				
			||||||
	log.ZDebug(context.Background(), "black local cache init", "Topic", b.Topic, "SlotNum", b.SlotNum, "SlotSize", b.SlotSize, "enable", b.Enable())
 | 
						log.ZDebug(context.Background(), "black local cache init", "Topic", b.Topic, "SlotNum", b.SlotNum, "SlotSize", b.SlotSize, "enable", b.Enable())
 | 
				
			||||||
	mc.SetTopic(b.Topic)
 | 
					 | 
				
			||||||
	mc.SetRawRedisClient(rdb)
 | 
					 | 
				
			||||||
	return &BlackCacheRedis{
 | 
						return &BlackCacheRedis{
 | 
				
			||||||
		expireTime: blackExpireTime,
 | 
							BatchDeleter: batchHandler,
 | 
				
			||||||
		rcClient:   rcClient,
 | 
							expireTime:   blackExpireTime,
 | 
				
			||||||
		metaCache:  mc,
 | 
							rcClient:     rockscache.NewClient(rdb, *options),
 | 
				
			||||||
		blackDB:    blackDB,
 | 
							blackDB:      blackDB,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (b *BlackCacheRedis) NewCache() BlackCache {
 | 
					func (b *BlackCacheRedis) CloneBlackCache() cache.BlackCache {
 | 
				
			||||||
	return &BlackCacheRedis{
 | 
						return &BlackCacheRedis{
 | 
				
			||||||
		expireTime: b.expireTime,
 | 
							BatchDeleter: b.BatchDeleter.Clone(),
 | 
				
			||||||
		rcClient:   b.rcClient,
 | 
							expireTime:   b.expireTime,
 | 
				
			||||||
		blackDB:    b.blackDB,
 | 
							rcClient:     b.rcClient,
 | 
				
			||||||
		metaCache:  b.Copy(),
 | 
							blackDB:      b.blackDB,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -88,8 +74,8 @@ func (b *BlackCacheRedis) GetBlackIDs(ctx context.Context, userID string) (black
 | 
				
			|||||||
	)
 | 
						)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (b *BlackCacheRedis) DelBlackIDs(ctx context.Context, userID string) BlackCache {
 | 
					func (b *BlackCacheRedis) DelBlackIDs(_ context.Context, userID string) cache.BlackCache {
 | 
				
			||||||
	cache := b.NewCache()
 | 
						cache := b.CloneBlackCache()
 | 
				
			||||||
	cache.AddKeys(b.getBlackIDsKey(userID))
 | 
						cache.AddKeys(b.getBlackIDsKey(userID))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return cache
 | 
						return cache
 | 
				
			||||||
							
								
								
									
										246
									
								
								pkg/common/storage/cache/redis/conversation.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										246
									
								
								pkg/common/storage/cache/redis/conversation.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,246 @@
 | 
				
			|||||||
 | 
					// Copyright © 2023 OpenIM. All rights reserved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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/cache"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/cachekey"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
 | 
						"github.com/openimsdk/tools/log"
 | 
				
			||||||
 | 
						"github.com/openimsdk/tools/utils/datautil"
 | 
				
			||||||
 | 
						"github.com/openimsdk/tools/utils/encrypt"
 | 
				
			||||||
 | 
						"github.com/redis/go-redis/v9"
 | 
				
			||||||
 | 
						"math/big"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						conversationExpireTime = time.Second * 60 * 60 * 12
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewConversationRedis(rdb redis.UniversalClient, localCache *config.LocalCache, opts *rockscache.Options, db database.Conversation) cache.ConversationCache {
 | 
				
			||||||
 | 
						batchHandler := NewBatchDeleterRedis(rdb, opts, []string{localCache.Conversation.Topic})
 | 
				
			||||||
 | 
						c := localCache.Conversation
 | 
				
			||||||
 | 
						log.ZDebug(context.Background(), "black local cache init", "Topic", c.Topic, "SlotNum", c.SlotNum, "SlotSize", c.SlotSize, "enable", c.Enable())
 | 
				
			||||||
 | 
						return &ConversationRedisCache{
 | 
				
			||||||
 | 
							BatchDeleter:   batchHandler,
 | 
				
			||||||
 | 
							rcClient:       rockscache.NewClient(rdb, *opts),
 | 
				
			||||||
 | 
							conversationDB: db,
 | 
				
			||||||
 | 
							expireTime:     conversationExpireTime,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ConversationRedisCache struct {
 | 
				
			||||||
 | 
						cache.BatchDeleter
 | 
				
			||||||
 | 
						rcClient       *rockscache.Client
 | 
				
			||||||
 | 
						conversationDB database.Conversation
 | 
				
			||||||
 | 
						expireTime     time.Duration
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) CloneConversationCache() cache.ConversationCache {
 | 
				
			||||||
 | 
						return &ConversationRedisCache{
 | 
				
			||||||
 | 
							BatchDeleter:   c.BatchDeleter.Clone(),
 | 
				
			||||||
 | 
							rcClient:       c.rcClient,
 | 
				
			||||||
 | 
							conversationDB: c.conversationDB,
 | 
				
			||||||
 | 
							expireTime:     c.expireTime,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) getConversationKey(ownerUserID, conversationID string) string {
 | 
				
			||||||
 | 
						return cachekey.GetConversationKey(ownerUserID, conversationID)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) getConversationIDsKey(ownerUserID string) string {
 | 
				
			||||||
 | 
						return cachekey.GetConversationIDsKey(ownerUserID)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) getSuperGroupRecvNotNotifyUserIDsKey(groupID string) string {
 | 
				
			||||||
 | 
						return cachekey.GetSuperGroupRecvNotNotifyUserIDsKey(groupID)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) getRecvMsgOptKey(ownerUserID, conversationID string) string {
 | 
				
			||||||
 | 
						return cachekey.GetRecvMsgOptKey(ownerUserID, conversationID)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) getSuperGroupRecvNotNotifyUserIDsHashKey(groupID string) string {
 | 
				
			||||||
 | 
						return cachekey.GetSuperGroupRecvNotNotifyUserIDsHashKey(groupID)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) getConversationHasReadSeqKey(ownerUserID, conversationID string) string {
 | 
				
			||||||
 | 
						return cachekey.GetConversationHasReadSeqKey(ownerUserID, conversationID)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) getConversationNotReceiveMessageUserIDsKey(conversationID string) string {
 | 
				
			||||||
 | 
						return cachekey.GetConversationNotReceiveMessageUserIDsKey(conversationID)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) getUserConversationIDsHashKey(ownerUserID string) string {
 | 
				
			||||||
 | 
						return cachekey.GetUserConversationIDsHashKey(ownerUserID)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) GetUserConversationIDs(ctx context.Context, ownerUserID string) ([]string, error) {
 | 
				
			||||||
 | 
						return getCache(ctx, c.rcClient, c.getConversationIDsKey(ownerUserID), c.expireTime, func(ctx context.Context) ([]string, error) {
 | 
				
			||||||
 | 
							return c.conversationDB.FindUserIDAllConversationID(ctx, ownerUserID)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) DelConversationIDs(userIDs ...string) cache.ConversationCache {
 | 
				
			||||||
 | 
						keys := make([]string, 0, len(userIDs))
 | 
				
			||||||
 | 
						for _, userID := range userIDs {
 | 
				
			||||||
 | 
							keys = append(keys, c.getConversationIDsKey(userID))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						cache := c.CloneConversationCache()
 | 
				
			||||||
 | 
						cache.AddKeys(keys...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cache
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) GetUserConversationIDsHash(ctx context.Context, ownerUserID string) (hash uint64, err error) {
 | 
				
			||||||
 | 
						return getCache(
 | 
				
			||||||
 | 
							ctx,
 | 
				
			||||||
 | 
							c.rcClient,
 | 
				
			||||||
 | 
							c.getUserConversationIDsHashKey(ownerUserID),
 | 
				
			||||||
 | 
							c.expireTime,
 | 
				
			||||||
 | 
							func(ctx context.Context) (uint64, error) {
 | 
				
			||||||
 | 
								conversationIDs, err := c.GetUserConversationIDs(ctx, ownerUserID)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return 0, err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								datautil.Sort(conversationIDs, true)
 | 
				
			||||||
 | 
								bi := big.NewInt(0)
 | 
				
			||||||
 | 
								bi.SetString(encrypt.Md5(strings.Join(conversationIDs, ";"))[0:8], 16)
 | 
				
			||||||
 | 
								return bi.Uint64(), nil
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) DelUserConversationIDsHash(ownerUserIDs ...string) cache.ConversationCache {
 | 
				
			||||||
 | 
						keys := make([]string, 0, len(ownerUserIDs))
 | 
				
			||||||
 | 
						for _, ownerUserID := range ownerUserIDs {
 | 
				
			||||||
 | 
							keys = append(keys, c.getUserConversationIDsHashKey(ownerUserID))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						cache := c.CloneConversationCache()
 | 
				
			||||||
 | 
						cache.AddKeys(keys...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cache
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) GetConversation(ctx context.Context, ownerUserID, conversationID string) (*model.Conversation, error) {
 | 
				
			||||||
 | 
						return getCache(ctx, c.rcClient, c.getConversationKey(ownerUserID, conversationID), c.expireTime, func(ctx context.Context) (*model.Conversation, error) {
 | 
				
			||||||
 | 
							return c.conversationDB.Take(ctx, ownerUserID, conversationID)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) DelConversations(ownerUserID string, conversationIDs ...string) cache.ConversationCache {
 | 
				
			||||||
 | 
						keys := make([]string, 0, len(conversationIDs))
 | 
				
			||||||
 | 
						for _, conversationID := range conversationIDs {
 | 
				
			||||||
 | 
							keys = append(keys, c.getConversationKey(ownerUserID, conversationID))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						cache := c.CloneConversationCache()
 | 
				
			||||||
 | 
						cache.AddKeys(keys...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cache
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) GetConversations(ctx context.Context, ownerUserID string, conversationIDs []string) ([]*model.Conversation, error) {
 | 
				
			||||||
 | 
						return batchGetCache(ctx, c.rcClient, c.expireTime, conversationIDs, func(conversationID string) string {
 | 
				
			||||||
 | 
							return c.getConversationKey(ownerUserID, conversationID)
 | 
				
			||||||
 | 
						}, func(ctx context.Context, conversationID string) (*model.Conversation, error) {
 | 
				
			||||||
 | 
							return c.conversationDB.Take(ctx, ownerUserID, conversationID)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) GetUserAllConversations(ctx context.Context, ownerUserID string) ([]*model.Conversation, error) {
 | 
				
			||||||
 | 
						conversationIDs, err := c.GetUserConversationIDs(ctx, ownerUserID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return c.GetConversations(ctx, ownerUserID, conversationIDs)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) GetUserRecvMsgOpt(ctx context.Context, ownerUserID, conversationID string) (opt int, err error) {
 | 
				
			||||||
 | 
						return getCache(ctx, c.rcClient, c.getRecvMsgOptKey(ownerUserID, conversationID), c.expireTime, func(ctx context.Context) (opt int, err error) {
 | 
				
			||||||
 | 
							return c.conversationDB.GetUserRecvMsgOpt(ctx, ownerUserID, conversationID)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) DelUsersConversation(conversationID string, ownerUserIDs ...string) cache.ConversationCache {
 | 
				
			||||||
 | 
						keys := make([]string, 0, len(ownerUserIDs))
 | 
				
			||||||
 | 
						for _, ownerUserID := range ownerUserIDs {
 | 
				
			||||||
 | 
							keys = append(keys, c.getConversationKey(ownerUserID, conversationID))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						cache := c.CloneConversationCache()
 | 
				
			||||||
 | 
						cache.AddKeys(keys...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cache
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) DelUserRecvMsgOpt(ownerUserID, conversationID string) cache.ConversationCache {
 | 
				
			||||||
 | 
						cache := c.CloneConversationCache()
 | 
				
			||||||
 | 
						cache.AddKeys(c.getRecvMsgOptKey(ownerUserID, conversationID))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cache
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) DelSuperGroupRecvMsgNotNotifyUserIDs(groupID string) cache.ConversationCache {
 | 
				
			||||||
 | 
						cache := c.CloneConversationCache()
 | 
				
			||||||
 | 
						cache.AddKeys(c.getSuperGroupRecvNotNotifyUserIDsKey(groupID))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cache
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) DelSuperGroupRecvMsgNotNotifyUserIDsHash(groupID string) cache.ConversationCache {
 | 
				
			||||||
 | 
						cache := c.CloneConversationCache()
 | 
				
			||||||
 | 
						cache.AddKeys(c.getSuperGroupRecvNotNotifyUserIDsHashKey(groupID))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cache
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) DelUserAllHasReadSeqs(ownerUserID string, conversationIDs ...string) cache.ConversationCache {
 | 
				
			||||||
 | 
						cache := c.CloneConversationCache()
 | 
				
			||||||
 | 
						for _, conversationID := range conversationIDs {
 | 
				
			||||||
 | 
							cache.AddKeys(c.getConversationHasReadSeqKey(ownerUserID, conversationID))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cache
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*model.Conversation, error) {
 | 
				
			||||||
 | 
						panic("implement me")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) DelConversationByConversationID(conversationIDs ...string) cache.ConversationCache {
 | 
				
			||||||
 | 
						panic("implement me")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error) {
 | 
				
			||||||
 | 
						return getCache(ctx, c.rcClient, c.getConversationNotReceiveMessageUserIDsKey(conversationID), c.expireTime, func(ctx context.Context) ([]string, error) {
 | 
				
			||||||
 | 
							return c.conversationDB.GetConversationNotReceiveMessageUserIDs(ctx, conversationID)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ConversationRedisCache) DelConversationNotReceiveMessageUserIDs(conversationIDs ...string) cache.ConversationCache {
 | 
				
			||||||
 | 
						cache := c.CloneConversationCache()
 | 
				
			||||||
 | 
						for _, conversationID := range conversationIDs {
 | 
				
			||||||
 | 
							cache.AddKeys(c.getConversationNotReceiveMessageUserIDsKey(conversationID))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cache
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										15
									
								
								pkg/common/storage/cache/redis/doc.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								pkg/common/storage/cache/redis/doc.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					// Copyright © 2023 OpenIM. All rights reserved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package redis
 | 
				
			||||||
@ -12,75 +12,54 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package cache
 | 
					package redis
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/dtm-labs/rockscache"
 | 
						"github.com/dtm-labs/rockscache"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/cachekey"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
				
			||||||
	relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/cachekey"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"github.com/openimsdk/tools/log"
 | 
						"github.com/openimsdk/tools/log"
 | 
				
			||||||
	"github.com/openimsdk/tools/utils/datautil"
 | 
						"github.com/openimsdk/tools/utils/datautil"
 | 
				
			||||||
	"github.com/redis/go-redis/v9"
 | 
						"github.com/redis/go-redis/v9"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	friendExpireTime = time.Second * 60 * 60 * 12
 | 
						friendExpireTime = time.Second * 60 * 60 * 12
 | 
				
			||||||
	// FriendIDsKey        = "FRIEND_IDS:"
 | 
					 | 
				
			||||||
	// TwoWayFriendsIDsKey = "COMMON_FRIENDS_IDS:"
 | 
					 | 
				
			||||||
	// friendKey           = "FRIEND_INFO:".
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// FriendCache is an interface for caching friend-related data.
 | 
					 | 
				
			||||||
type FriendCache interface {
 | 
					 | 
				
			||||||
	metaCache
 | 
					 | 
				
			||||||
	NewCache() FriendCache
 | 
					 | 
				
			||||||
	GetFriendIDs(ctx context.Context, ownerUserID string) (friendIDs []string, err error)
 | 
					 | 
				
			||||||
	// Called when friendID list changed
 | 
					 | 
				
			||||||
	DelFriendIDs(ownerUserID ...string) FriendCache
 | 
					 | 
				
			||||||
	// Get single friendInfo from the cache
 | 
					 | 
				
			||||||
	GetFriend(ctx context.Context, ownerUserID, friendUserID string) (friend *relationtb.FriendModel, err error)
 | 
					 | 
				
			||||||
	// Delete friend when friend info changed
 | 
					 | 
				
			||||||
	DelFriend(ownerUserID, friendUserID string) FriendCache
 | 
					 | 
				
			||||||
	// Delete friends when friends' info changed
 | 
					 | 
				
			||||||
	DelFriends(ownerUserID string, friendUserIDs []string) FriendCache
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// FriendCacheRedis is an implementation of the FriendCache interface using Redis.
 | 
					// FriendCacheRedis is an implementation of the FriendCache interface using Redis.
 | 
				
			||||||
type FriendCacheRedis struct {
 | 
					type FriendCacheRedis struct {
 | 
				
			||||||
	metaCache
 | 
						cache.BatchDeleter
 | 
				
			||||||
	friendDB   relationtb.FriendModelInterface
 | 
						friendDB   database.Friend
 | 
				
			||||||
	expireTime time.Duration
 | 
						expireTime time.Duration
 | 
				
			||||||
	rcClient   *rockscache.Client
 | 
						rcClient   *rockscache.Client
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewFriendCacheRedis creates a new instance of FriendCacheRedis.
 | 
					// NewFriendCacheRedis creates a new instance of FriendCacheRedis.
 | 
				
			||||||
func NewFriendCacheRedis(rdb redis.UniversalClient, localCache *config.LocalCache, friendDB relationtb.FriendModelInterface,
 | 
					func NewFriendCacheRedis(rdb redis.UniversalClient, localCache *config.LocalCache, friendDB database.Friend,
 | 
				
			||||||
	options rockscache.Options) FriendCache {
 | 
						options *rockscache.Options) cache.FriendCache {
 | 
				
			||||||
	rcClient := rockscache.NewClient(rdb, options)
 | 
						batchHandler := NewBatchDeleterRedis(rdb, options, []string{localCache.Friend.Topic})
 | 
				
			||||||
	mc := NewMetaCacheRedis(rcClient)
 | 
					 | 
				
			||||||
	f := localCache.Friend
 | 
						f := localCache.Friend
 | 
				
			||||||
	log.ZDebug(context.Background(), "friend local cache init", "Topic", f.Topic, "SlotNum", f.SlotNum, "SlotSize", f.SlotSize, "enable", f.Enable())
 | 
						log.ZDebug(context.Background(), "friend local cache init", "Topic", f.Topic, "SlotNum", f.SlotNum, "SlotSize", f.SlotSize, "enable", f.Enable())
 | 
				
			||||||
	mc.SetTopic(f.Topic)
 | 
					 | 
				
			||||||
	mc.SetRawRedisClient(rdb)
 | 
					 | 
				
			||||||
	return &FriendCacheRedis{
 | 
						return &FriendCacheRedis{
 | 
				
			||||||
		metaCache:  mc,
 | 
							BatchDeleter: batchHandler,
 | 
				
			||||||
		friendDB:   friendDB,
 | 
							friendDB:     friendDB,
 | 
				
			||||||
		expireTime: friendExpireTime,
 | 
							expireTime:   friendExpireTime,
 | 
				
			||||||
		rcClient:   rcClient,
 | 
							rcClient:     rockscache.NewClient(rdb, *options),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewCache creates a new instance of FriendCacheRedis with the same configuration.
 | 
					func (f *FriendCacheRedis) CloneFriendCache() cache.FriendCache {
 | 
				
			||||||
func (f *FriendCacheRedis) NewCache() FriendCache {
 | 
					 | 
				
			||||||
	return &FriendCacheRedis{
 | 
						return &FriendCacheRedis{
 | 
				
			||||||
		rcClient:   f.rcClient,
 | 
							BatchDeleter: f.BatchDeleter.Clone(),
 | 
				
			||||||
		metaCache:  f.Copy(),
 | 
							friendDB:     f.friendDB,
 | 
				
			||||||
		friendDB:   f.friendDB,
 | 
							expireTime:   f.expireTime,
 | 
				
			||||||
		expireTime: f.expireTime,
 | 
							rcClient:     f.rcClient,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -107,15 +86,15 @@ func (f *FriendCacheRedis) GetFriendIDs(ctx context.Context, ownerUserID string)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DelFriendIDs deletes friend IDs from the cache.
 | 
					// DelFriendIDs deletes friend IDs from the cache.
 | 
				
			||||||
func (f *FriendCacheRedis) DelFriendIDs(ownerUserIDs ...string) FriendCache {
 | 
					func (f *FriendCacheRedis) DelFriendIDs(ownerUserIDs ...string) cache.FriendCache {
 | 
				
			||||||
	newGroupCache := f.NewCache()
 | 
						newFriendCache := f.CloneFriendCache()
 | 
				
			||||||
	keys := make([]string, 0, len(ownerUserIDs))
 | 
						keys := make([]string, 0, len(ownerUserIDs))
 | 
				
			||||||
	for _, userID := range ownerUserIDs {
 | 
						for _, userID := range ownerUserIDs {
 | 
				
			||||||
		keys = append(keys, f.getFriendIDsKey(userID))
 | 
							keys = append(keys, f.getFriendIDsKey(userID))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	newGroupCache.AddKeys(keys...)
 | 
						newFriendCache.AddKeys(keys...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return newGroupCache
 | 
						return newFriendCache
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetTwoWayFriendIDs retrieves two-way friend IDs from the cache.
 | 
					// GetTwoWayFriendIDs retrieves two-way friend IDs from the cache.
 | 
				
			||||||
@ -138,32 +117,32 @@ func (f *FriendCacheRedis) GetTwoWayFriendIDs(ctx context.Context, ownerUserID s
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DelTwoWayFriendIDs deletes two-way friend IDs from the cache.
 | 
					// DelTwoWayFriendIDs deletes two-way friend IDs from the cache.
 | 
				
			||||||
func (f *FriendCacheRedis) DelTwoWayFriendIDs(ctx context.Context, ownerUserID string) FriendCache {
 | 
					func (f *FriendCacheRedis) DelTwoWayFriendIDs(ctx context.Context, ownerUserID string) cache.FriendCache {
 | 
				
			||||||
	newFriendCache := f.NewCache()
 | 
						newFriendCache := f.CloneFriendCache()
 | 
				
			||||||
	newFriendCache.AddKeys(f.getTwoWayFriendsIDsKey(ownerUserID))
 | 
						newFriendCache.AddKeys(f.getTwoWayFriendsIDsKey(ownerUserID))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return newFriendCache
 | 
						return newFriendCache
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetFriend retrieves friend info from the cache or the database if not found.
 | 
					// GetFriend retrieves friend info from the cache or the database if not found.
 | 
				
			||||||
func (f *FriendCacheRedis) GetFriend(ctx context.Context, ownerUserID, friendUserID string) (friend *relationtb.FriendModel, err error) {
 | 
					func (f *FriendCacheRedis) GetFriend(ctx context.Context, ownerUserID, friendUserID string) (friend *model.Friend, err error) {
 | 
				
			||||||
	return getCache(ctx, f.rcClient, f.getFriendKey(ownerUserID,
 | 
						return getCache(ctx, f.rcClient, f.getFriendKey(ownerUserID,
 | 
				
			||||||
		friendUserID), f.expireTime, func(ctx context.Context) (*relationtb.FriendModel, error) {
 | 
							friendUserID), f.expireTime, func(ctx context.Context) (*model.Friend, error) {
 | 
				
			||||||
		return f.friendDB.Take(ctx, ownerUserID, friendUserID)
 | 
							return f.friendDB.Take(ctx, ownerUserID, friendUserID)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DelFriend deletes friend info from the cache.
 | 
					// DelFriend deletes friend info from the cache.
 | 
				
			||||||
func (f *FriendCacheRedis) DelFriend(ownerUserID, friendUserID string) FriendCache {
 | 
					func (f *FriendCacheRedis) DelFriend(ownerUserID, friendUserID string) cache.FriendCache {
 | 
				
			||||||
	newFriendCache := f.NewCache()
 | 
						newFriendCache := f.CloneFriendCache()
 | 
				
			||||||
	newFriendCache.AddKeys(f.getFriendKey(ownerUserID, friendUserID))
 | 
						newFriendCache.AddKeys(f.getFriendKey(ownerUserID, friendUserID))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return newFriendCache
 | 
						return newFriendCache
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DelFriends deletes multiple friend infos from the cache.
 | 
					// DelFriends deletes multiple friend infos from the cache.
 | 
				
			||||||
func (f *FriendCacheRedis) DelFriends(ownerUserID string, friendUserIDs []string) FriendCache {
 | 
					func (f *FriendCacheRedis) DelFriends(ownerUserID string, friendUserIDs []string) cache.FriendCache {
 | 
				
			||||||
	newFriendCache := f.NewCache()
 | 
						newFriendCache := f.CloneFriendCache()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, friendUserID := range friendUserIDs {
 | 
						for _, friendUserID := range friendUserIDs {
 | 
				
			||||||
		key := f.getFriendKey(ownerUserID, friendUserID)
 | 
							key := f.getFriendKey(ownerUserID, friendUserID)
 | 
				
			||||||
@ -12,110 +12,74 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package cache
 | 
					package redis
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/dtm-labs/rockscache"
 | 
						"github.com/dtm-labs/rockscache"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/cachekey"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
				
			||||||
	relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/cachekey"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/common"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"github.com/openimsdk/protocol/constant"
 | 
						"github.com/openimsdk/protocol/constant"
 | 
				
			||||||
	"github.com/openimsdk/tools/errs"
 | 
						"github.com/openimsdk/tools/errs"
 | 
				
			||||||
	"github.com/openimsdk/tools/log"
 | 
						"github.com/openimsdk/tools/log"
 | 
				
			||||||
	"github.com/openimsdk/tools/utils/datautil"
 | 
						"github.com/openimsdk/tools/utils/datautil"
 | 
				
			||||||
	"github.com/redis/go-redis/v9"
 | 
						"github.com/redis/go-redis/v9"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	groupExpireTime = time.Second * 60 * 60 * 12
 | 
						groupExpireTime = time.Second * 60 * 60 * 12
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type GroupHash interface {
 | 
					var errIndex = errs.New("err index")
 | 
				
			||||||
	GetGroupHash(ctx context.Context, groupID string) (uint64, error)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type GroupCache interface {
 | 
					 | 
				
			||||||
	metaCache
 | 
					 | 
				
			||||||
	NewCache() GroupCache
 | 
					 | 
				
			||||||
	GetGroupsInfo(ctx context.Context, groupIDs []string) (groups []*relationtb.GroupModel, err error)
 | 
					 | 
				
			||||||
	GetGroupInfo(ctx context.Context, groupID string) (group *relationtb.GroupModel, err error)
 | 
					 | 
				
			||||||
	DelGroupsInfo(groupIDs ...string) GroupCache
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	GetGroupMembersHash(ctx context.Context, groupID string) (hashCode uint64, err error)
 | 
					 | 
				
			||||||
	GetGroupMemberHashMap(ctx context.Context, groupIDs []string) (map[string]*relationtb.GroupSimpleUserID, error)
 | 
					 | 
				
			||||||
	DelGroupMembersHash(groupID string) GroupCache
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	GetGroupMemberIDs(ctx context.Context, groupID string) (groupMemberIDs []string, err error)
 | 
					 | 
				
			||||||
	GetGroupsMemberIDs(ctx context.Context, groupIDs []string) (groupMemberIDs map[string][]string, err error)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	DelGroupMemberIDs(groupID string) GroupCache
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	GetJoinedGroupIDs(ctx context.Context, userID string) (joinedGroupIDs []string, err error)
 | 
					 | 
				
			||||||
	DelJoinedGroupID(userID ...string) GroupCache
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	GetGroupMemberInfo(ctx context.Context, groupID, userID string) (groupMember *relationtb.GroupMemberModel, err error)
 | 
					 | 
				
			||||||
	GetGroupMembersInfo(ctx context.Context, groupID string, userID []string) (groupMembers []*relationtb.GroupMemberModel, err error)
 | 
					 | 
				
			||||||
	GetAllGroupMembersInfo(ctx context.Context, groupID string) (groupMembers []*relationtb.GroupMemberModel, err error)
 | 
					 | 
				
			||||||
	GetGroupMembersPage(ctx context.Context, groupID string, userID []string, showNumber, pageNumber int32) (total uint32, groupMembers []*relationtb.GroupMemberModel, err error)
 | 
					 | 
				
			||||||
	FindGroupMemberUser(ctx context.Context, groupIDs []string, userID string) ([]*relationtb.GroupMemberModel, error)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	GetGroupRoleLevelMemberIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error)
 | 
					 | 
				
			||||||
	GetGroupOwner(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error)
 | 
					 | 
				
			||||||
	GetGroupsOwner(ctx context.Context, groupIDs []string) ([]*relationtb.GroupMemberModel, error)
 | 
					 | 
				
			||||||
	DelGroupRoleLevel(groupID string, roleLevel []int32) GroupCache
 | 
					 | 
				
			||||||
	DelGroupAllRoleLevel(groupID string) GroupCache
 | 
					 | 
				
			||||||
	DelGroupMembersInfo(groupID string, userID ...string) GroupCache
 | 
					 | 
				
			||||||
	GetGroupRoleLevelMemberInfo(ctx context.Context, groupID string, roleLevel int32) ([]*relationtb.GroupMemberModel, error)
 | 
					 | 
				
			||||||
	GetGroupRolesLevelMemberInfo(ctx context.Context, groupID string, roleLevels []int32) ([]*relationtb.GroupMemberModel, error)
 | 
					 | 
				
			||||||
	GetGroupMemberNum(ctx context.Context, groupID string) (memberNum int64, err error)
 | 
					 | 
				
			||||||
	DelGroupsMemberNum(groupID ...string) GroupCache
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
type GroupCacheRedis struct {
 | 
					type GroupCacheRedis struct {
 | 
				
			||||||
	metaCache
 | 
						cache.BatchDeleter
 | 
				
			||||||
	groupDB        relationtb.GroupModelInterface
 | 
						groupDB        database.Group
 | 
				
			||||||
	groupMemberDB  relationtb.GroupMemberModelInterface
 | 
						groupMemberDB  database.GroupMember
 | 
				
			||||||
	groupRequestDB relationtb.GroupRequestModelInterface
 | 
						groupRequestDB database.GroupRequest
 | 
				
			||||||
	expireTime     time.Duration
 | 
						expireTime     time.Duration
 | 
				
			||||||
	rcClient       *rockscache.Client
 | 
						rcClient       *rockscache.Client
 | 
				
			||||||
	groupHash      GroupHash
 | 
						groupHash      cache.GroupHash
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewGroupCacheRedis(
 | 
					func NewGroupCacheRedis(
 | 
				
			||||||
	rdb redis.UniversalClient,
 | 
						rdb redis.UniversalClient,
 | 
				
			||||||
	localCache *config.LocalCache,
 | 
						localCache *config.LocalCache,
 | 
				
			||||||
	groupDB relationtb.GroupModelInterface,
 | 
						groupDB database.Group,
 | 
				
			||||||
	groupMemberDB relationtb.GroupMemberModelInterface,
 | 
						groupMemberDB database.GroupMember,
 | 
				
			||||||
	groupRequestDB relationtb.GroupRequestModelInterface,
 | 
						groupRequestDB database.GroupRequest,
 | 
				
			||||||
	hashCode GroupHash,
 | 
						hashCode cache.GroupHash,
 | 
				
			||||||
	opts rockscache.Options,
 | 
						opts *rockscache.Options,
 | 
				
			||||||
) GroupCache {
 | 
					) cache.GroupCache {
 | 
				
			||||||
	rcClient := rockscache.NewClient(rdb, opts)
 | 
						batchHandler := NewBatchDeleterRedis(rdb, opts, []string{localCache.Group.Topic})
 | 
				
			||||||
	mc := NewMetaCacheRedis(rcClient)
 | 
					 | 
				
			||||||
	g := localCache.Group
 | 
						g := localCache.Group
 | 
				
			||||||
	mc.SetTopic(g.Topic)
 | 
					 | 
				
			||||||
	log.ZDebug(context.Background(), "group local cache init", "Topic", g.Topic, "SlotNum", g.SlotNum, "SlotSize", g.SlotSize, "enable", g.Enable())
 | 
						log.ZDebug(context.Background(), "group local cache init", "Topic", g.Topic, "SlotNum", g.SlotNum, "SlotSize", g.SlotSize, "enable", g.Enable())
 | 
				
			||||||
	mc.SetRawRedisClient(rdb)
 | 
					
 | 
				
			||||||
	return &GroupCacheRedis{
 | 
						return &GroupCacheRedis{
 | 
				
			||||||
		rcClient: rcClient, expireTime: groupExpireTime,
 | 
							BatchDeleter:   batchHandler,
 | 
				
			||||||
		groupDB: groupDB, groupMemberDB: groupMemberDB, groupRequestDB: groupRequestDB,
 | 
							rcClient:       rockscache.NewClient(rdb, *opts),
 | 
				
			||||||
		groupHash: hashCode,
 | 
							expireTime:     groupExpireTime,
 | 
				
			||||||
		metaCache: mc,
 | 
							groupDB:        groupDB,
 | 
				
			||||||
 | 
							groupMemberDB:  groupMemberDB,
 | 
				
			||||||
 | 
							groupRequestDB: groupRequestDB,
 | 
				
			||||||
 | 
							groupHash:      hashCode,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupCacheRedis) NewCache() GroupCache {
 | 
					func (g *GroupCacheRedis) CloneGroupCache() cache.GroupCache {
 | 
				
			||||||
	return &GroupCacheRedis{
 | 
						return &GroupCacheRedis{
 | 
				
			||||||
 | 
							BatchDeleter:   g.BatchDeleter.Clone(),
 | 
				
			||||||
		rcClient:       g.rcClient,
 | 
							rcClient:       g.rcClient,
 | 
				
			||||||
		expireTime:     g.expireTime,
 | 
							expireTime:     g.expireTime,
 | 
				
			||||||
		groupDB:        g.groupDB,
 | 
							groupDB:        g.groupDB,
 | 
				
			||||||
		groupMemberDB:  g.groupMemberDB,
 | 
							groupMemberDB:  g.groupMemberDB,
 | 
				
			||||||
		groupRequestDB: g.groupRequestDB,
 | 
							groupRequestDB: g.groupRequestDB,
 | 
				
			||||||
		metaCache:      g.Copy(),
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -147,7 +111,7 @@ func (g *GroupCacheRedis) getGroupRoleLevelMemberIDsKey(groupID string, roleLeve
 | 
				
			|||||||
	return cachekey.GetGroupRoleLevelMemberIDsKey(groupID, roleLevel)
 | 
						return cachekey.GetGroupRoleLevelMemberIDsKey(groupID, roleLevel)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupCacheRedis) GetGroupIndex(group *relationtb.GroupModel, keys []string) (int, error) {
 | 
					func (g *GroupCacheRedis) GetGroupIndex(group *model.Group, keys []string) (int, error) {
 | 
				
			||||||
	key := g.getGroupInfoKey(group.GroupID)
 | 
						key := g.getGroupInfoKey(group.GroupID)
 | 
				
			||||||
	for i, _key := range keys {
 | 
						for i, _key := range keys {
 | 
				
			||||||
		if _key == key {
 | 
							if _key == key {
 | 
				
			||||||
@ -158,7 +122,7 @@ func (g *GroupCacheRedis) GetGroupIndex(group *relationtb.GroupModel, keys []str
 | 
				
			|||||||
	return 0, errIndex
 | 
						return 0, errIndex
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupCacheRedis) GetGroupMemberIndex(groupMember *relationtb.GroupMemberModel, keys []string) (int, error) {
 | 
					func (g *GroupCacheRedis) GetGroupMemberIndex(groupMember *model.GroupMember, keys []string) (int, error) {
 | 
				
			||||||
	key := g.getGroupMemberInfoKey(groupMember.GroupID, groupMember.UserID)
 | 
						key := g.getGroupMemberInfoKey(groupMember.GroupID, groupMember.UserID)
 | 
				
			||||||
	for i, _key := range keys {
 | 
						for i, _key := range keys {
 | 
				
			||||||
		if _key == key {
 | 
							if _key == key {
 | 
				
			||||||
@ -169,22 +133,22 @@ func (g *GroupCacheRedis) GetGroupMemberIndex(groupMember *relationtb.GroupMembe
 | 
				
			|||||||
	return 0, errIndex
 | 
						return 0, errIndex
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupCacheRedis) GetGroupsInfo(ctx context.Context, groupIDs []string) (groups []*relationtb.GroupModel, err error) {
 | 
					func (g *GroupCacheRedis) GetGroupsInfo(ctx context.Context, groupIDs []string) (groups []*model.Group, err error) {
 | 
				
			||||||
	return batchGetCache2(ctx, g.rcClient, g.expireTime, groupIDs, func(groupID string) string {
 | 
						return batchGetCache(ctx, g.rcClient, g.expireTime, groupIDs, func(groupID string) string {
 | 
				
			||||||
		return g.getGroupInfoKey(groupID)
 | 
							return g.getGroupInfoKey(groupID)
 | 
				
			||||||
	}, func(ctx context.Context, groupID string) (*relationtb.GroupModel, error) {
 | 
						}, func(ctx context.Context, groupID string) (*model.Group, error) {
 | 
				
			||||||
		return g.groupDB.Take(ctx, groupID)
 | 
							return g.groupDB.Take(ctx, groupID)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupCacheRedis) GetGroupInfo(ctx context.Context, groupID string) (group *relationtb.GroupModel, err error) {
 | 
					func (g *GroupCacheRedis) GetGroupInfo(ctx context.Context, groupID string) (group *model.Group, err error) {
 | 
				
			||||||
	return getCache(ctx, g.rcClient, g.getGroupInfoKey(groupID), g.expireTime, func(ctx context.Context) (*relationtb.GroupModel, error) {
 | 
						return getCache(ctx, g.rcClient, g.getGroupInfoKey(groupID), g.expireTime, func(ctx context.Context) (*model.Group, error) {
 | 
				
			||||||
		return g.groupDB.Take(ctx, groupID)
 | 
							return g.groupDB.Take(ctx, groupID)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupCacheRedis) DelGroupsInfo(groupIDs ...string) GroupCache {
 | 
					func (g *GroupCacheRedis) DelGroupsInfo(groupIDs ...string) cache.GroupCache {
 | 
				
			||||||
	newGroupCache := g.NewCache()
 | 
						newGroupCache := g.CloneGroupCache()
 | 
				
			||||||
	keys := make([]string, 0, len(groupIDs))
 | 
						keys := make([]string, 0, len(groupIDs))
 | 
				
			||||||
	for _, groupID := range groupIDs {
 | 
						for _, groupID := range groupIDs {
 | 
				
			||||||
		keys = append(keys, g.getGroupInfoKey(groupID))
 | 
							keys = append(keys, g.getGroupInfoKey(groupID))
 | 
				
			||||||
@ -194,8 +158,8 @@ func (g *GroupCacheRedis) DelGroupsInfo(groupIDs ...string) GroupCache {
 | 
				
			|||||||
	return newGroupCache
 | 
						return newGroupCache
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupCacheRedis) DelGroupsOwner(groupIDs ...string) GroupCache {
 | 
					func (g *GroupCacheRedis) DelGroupsOwner(groupIDs ...string) cache.GroupCache {
 | 
				
			||||||
	newGroupCache := g.NewCache()
 | 
						newGroupCache := g.CloneGroupCache()
 | 
				
			||||||
	keys := make([]string, 0, len(groupIDs))
 | 
						keys := make([]string, 0, len(groupIDs))
 | 
				
			||||||
	for _, groupID := range groupIDs {
 | 
						for _, groupID := range groupIDs {
 | 
				
			||||||
		keys = append(keys, g.getGroupRoleLevelMemberIDsKey(groupID, constant.GroupOwner))
 | 
							keys = append(keys, g.getGroupRoleLevelMemberIDsKey(groupID, constant.GroupOwner))
 | 
				
			||||||
@ -205,8 +169,8 @@ func (g *GroupCacheRedis) DelGroupsOwner(groupIDs ...string) GroupCache {
 | 
				
			|||||||
	return newGroupCache
 | 
						return newGroupCache
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupCacheRedis) DelGroupRoleLevel(groupID string, roleLevels []int32) GroupCache {
 | 
					func (g *GroupCacheRedis) DelGroupRoleLevel(groupID string, roleLevels []int32) cache.GroupCache {
 | 
				
			||||||
	newGroupCache := g.NewCache()
 | 
						newGroupCache := g.CloneGroupCache()
 | 
				
			||||||
	keys := make([]string, 0, len(roleLevels))
 | 
						keys := make([]string, 0, len(roleLevels))
 | 
				
			||||||
	for _, roleLevel := range roleLevels {
 | 
						for _, roleLevel := range roleLevels {
 | 
				
			||||||
		keys = append(keys, g.getGroupRoleLevelMemberIDsKey(groupID, roleLevel))
 | 
							keys = append(keys, g.getGroupRoleLevelMemberIDsKey(groupID, roleLevel))
 | 
				
			||||||
@ -215,7 +179,7 @@ func (g *GroupCacheRedis) DelGroupRoleLevel(groupID string, roleLevels []int32)
 | 
				
			|||||||
	return newGroupCache
 | 
						return newGroupCache
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupCacheRedis) DelGroupAllRoleLevel(groupID string) GroupCache {
 | 
					func (g *GroupCacheRedis) DelGroupAllRoleLevel(groupID string) cache.GroupCache {
 | 
				
			||||||
	return g.DelGroupRoleLevel(groupID, []int32{constant.GroupOwner, constant.GroupAdmin, constant.GroupOrdinaryUsers})
 | 
						return g.DelGroupRoleLevel(groupID, []int32{constant.GroupOwner, constant.GroupAdmin, constant.GroupOrdinaryUsers})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -228,11 +192,11 @@ func (g *GroupCacheRedis) GetGroupMembersHash(ctx context.Context, groupID strin
 | 
				
			|||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupCacheRedis) GetGroupMemberHashMap(ctx context.Context, groupIDs []string) (map[string]*relationtb.GroupSimpleUserID, error) {
 | 
					func (g *GroupCacheRedis) GetGroupMemberHashMap(ctx context.Context, groupIDs []string) (map[string]*common.GroupSimpleUserID, error) {
 | 
				
			||||||
	if g.groupHash == nil {
 | 
						if g.groupHash == nil {
 | 
				
			||||||
		return nil, errs.ErrInternalServer.WrapMsg("group hash is nil")
 | 
							return nil, errs.ErrInternalServer.WrapMsg("group hash is nil")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	res := make(map[string]*relationtb.GroupSimpleUserID)
 | 
						res := make(map[string]*common.GroupSimpleUserID)
 | 
				
			||||||
	for _, groupID := range groupIDs {
 | 
						for _, groupID := range groupIDs {
 | 
				
			||||||
		hash, err := g.GetGroupMembersHash(ctx, groupID)
 | 
							hash, err := g.GetGroupMembersHash(ctx, groupID)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
@ -243,14 +207,14 @@ func (g *GroupCacheRedis) GetGroupMemberHashMap(ctx context.Context, groupIDs []
 | 
				
			|||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		res[groupID] = &relationtb.GroupSimpleUserID{Hash: hash, MemberNum: uint32(num)}
 | 
							res[groupID] = &common.GroupSimpleUserID{Hash: hash, MemberNum: uint32(num)}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return res, nil
 | 
						return res, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupCacheRedis) DelGroupMembersHash(groupID string) GroupCache {
 | 
					func (g *GroupCacheRedis) DelGroupMembersHash(groupID string) cache.GroupCache {
 | 
				
			||||||
	cache := g.NewCache()
 | 
						cache := g.CloneGroupCache()
 | 
				
			||||||
	cache.AddKeys(g.getGroupMembersHashKey(groupID))
 | 
						cache.AddKeys(g.getGroupMembersHashKey(groupID))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return cache
 | 
						return cache
 | 
				
			||||||
@ -275,8 +239,8 @@ func (g *GroupCacheRedis) GetGroupsMemberIDs(ctx context.Context, groupIDs []str
 | 
				
			|||||||
	return m, nil
 | 
						return m, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupCacheRedis) DelGroupMemberIDs(groupID string) GroupCache {
 | 
					func (g *GroupCacheRedis) DelGroupMemberIDs(groupID string) cache.GroupCache {
 | 
				
			||||||
	cache := g.NewCache()
 | 
						cache := g.CloneGroupCache()
 | 
				
			||||||
	cache.AddKeys(g.getGroupMemberIDsKey(groupID))
 | 
						cache.AddKeys(g.getGroupMemberIDsKey(groupID))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return cache
 | 
						return cache
 | 
				
			||||||
@ -288,27 +252,27 @@ func (g *GroupCacheRedis) GetJoinedGroupIDs(ctx context.Context, userID string)
 | 
				
			|||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupCacheRedis) DelJoinedGroupID(userIDs ...string) GroupCache {
 | 
					func (g *GroupCacheRedis) DelJoinedGroupID(userIDs ...string) cache.GroupCache {
 | 
				
			||||||
	keys := make([]string, 0, len(userIDs))
 | 
						keys := make([]string, 0, len(userIDs))
 | 
				
			||||||
	for _, userID := range userIDs {
 | 
						for _, userID := range userIDs {
 | 
				
			||||||
		keys = append(keys, g.getJoinedGroupsKey(userID))
 | 
							keys = append(keys, g.getJoinedGroupsKey(userID))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	cache := g.NewCache()
 | 
						cache := g.CloneGroupCache()
 | 
				
			||||||
	cache.AddKeys(keys...)
 | 
						cache.AddKeys(keys...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return cache
 | 
						return cache
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupCacheRedis) GetGroupMemberInfo(ctx context.Context, groupID, userID string) (groupMember *relationtb.GroupMemberModel, err error) {
 | 
					func (g *GroupCacheRedis) GetGroupMemberInfo(ctx context.Context, groupID, userID string) (groupMember *model.GroupMember, err error) {
 | 
				
			||||||
	return getCache(ctx, g.rcClient, g.getGroupMemberInfoKey(groupID, userID), g.expireTime, func(ctx context.Context) (*relationtb.GroupMemberModel, error) {
 | 
						return getCache(ctx, g.rcClient, g.getGroupMemberInfoKey(groupID, userID), g.expireTime, func(ctx context.Context) (*model.GroupMember, error) {
 | 
				
			||||||
		return g.groupMemberDB.Take(ctx, groupID, userID)
 | 
							return g.groupMemberDB.Take(ctx, groupID, userID)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupCacheRedis) GetGroupMembersInfo(ctx context.Context, groupID string, userIDs []string) ([]*relationtb.GroupMemberModel, error) {
 | 
					func (g *GroupCacheRedis) GetGroupMembersInfo(ctx context.Context, groupID string, userIDs []string) ([]*model.GroupMember, error) {
 | 
				
			||||||
	return batchGetCache2(ctx, g.rcClient, g.expireTime, userIDs, func(userID string) string {
 | 
						return batchGetCache(ctx, g.rcClient, g.expireTime, userIDs, func(userID string) string {
 | 
				
			||||||
		return g.getGroupMemberInfoKey(groupID, userID)
 | 
							return g.getGroupMemberInfoKey(groupID, userID)
 | 
				
			||||||
	}, func(ctx context.Context, userID string) (*relationtb.GroupMemberModel, error) {
 | 
						}, func(ctx context.Context, userID string) (*model.GroupMember, error) {
 | 
				
			||||||
		return g.groupMemberDB.Take(ctx, groupID, userID)
 | 
							return g.groupMemberDB.Take(ctx, groupID, userID)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -318,7 +282,7 @@ func (g *GroupCacheRedis) GetGroupMembersPage(
 | 
				
			|||||||
	groupID string,
 | 
						groupID string,
 | 
				
			||||||
	userIDs []string,
 | 
						userIDs []string,
 | 
				
			||||||
	showNumber, pageNumber int32,
 | 
						showNumber, pageNumber int32,
 | 
				
			||||||
) (total uint32, groupMembers []*relationtb.GroupMemberModel, err error) {
 | 
					) (total uint32, groupMembers []*model.GroupMember, err error) {
 | 
				
			||||||
	groupMemberIDs, err := g.GetGroupMemberIDs(ctx, groupID)
 | 
						groupMemberIDs, err := g.GetGroupMemberIDs(ctx, groupID)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return 0, nil, err
 | 
							return 0, nil, err
 | 
				
			||||||
@ -333,7 +297,7 @@ func (g *GroupCacheRedis) GetGroupMembersPage(
 | 
				
			|||||||
	return uint32(len(userIDs)), groupMembers, err
 | 
						return uint32(len(userIDs)), groupMembers, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupCacheRedis) GetAllGroupMembersInfo(ctx context.Context, groupID string) (groupMembers []*relationtb.GroupMemberModel, err error) {
 | 
					func (g *GroupCacheRedis) GetAllGroupMembersInfo(ctx context.Context, groupID string) (groupMembers []*model.GroupMember, err error) {
 | 
				
			||||||
	groupMemberIDs, err := g.GetGroupMemberIDs(ctx, groupID)
 | 
						groupMemberIDs, err := g.GetGroupMemberIDs(ctx, groupID)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
@ -342,7 +306,7 @@ func (g *GroupCacheRedis) GetAllGroupMembersInfo(ctx context.Context, groupID st
 | 
				
			|||||||
	return g.GetGroupMembersInfo(ctx, groupID, groupMemberIDs)
 | 
						return g.GetGroupMembersInfo(ctx, groupID, groupMemberIDs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupCacheRedis) GetAllGroupMemberInfo(ctx context.Context, groupID string) ([]*relationtb.GroupMemberModel, error) {
 | 
					func (g *GroupCacheRedis) GetAllGroupMemberInfo(ctx context.Context, groupID string) ([]*model.GroupMember, error) {
 | 
				
			||||||
	groupMemberIDs, err := g.GetGroupMemberIDs(ctx, groupID)
 | 
						groupMemberIDs, err := g.GetGroupMemberIDs(ctx, groupID)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
@ -350,12 +314,12 @@ func (g *GroupCacheRedis) GetAllGroupMemberInfo(ctx context.Context, groupID str
 | 
				
			|||||||
	return g.GetGroupMembersInfo(ctx, groupID, groupMemberIDs)
 | 
						return g.GetGroupMembersInfo(ctx, groupID, groupMemberIDs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupCacheRedis) DelGroupMembersInfo(groupID string, userIDs ...string) GroupCache {
 | 
					func (g *GroupCacheRedis) DelGroupMembersInfo(groupID string, userIDs ...string) cache.GroupCache {
 | 
				
			||||||
	keys := make([]string, 0, len(userIDs))
 | 
						keys := make([]string, 0, len(userIDs))
 | 
				
			||||||
	for _, userID := range userIDs {
 | 
						for _, userID := range userIDs {
 | 
				
			||||||
		keys = append(keys, g.getGroupMemberInfoKey(groupID, userID))
 | 
							keys = append(keys, g.getGroupMemberInfoKey(groupID, userID))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	cache := g.NewCache()
 | 
						cache := g.CloneGroupCache()
 | 
				
			||||||
	cache.AddKeys(keys...)
 | 
						cache.AddKeys(keys...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return cache
 | 
						return cache
 | 
				
			||||||
@ -367,18 +331,18 @@ func (g *GroupCacheRedis) GetGroupMemberNum(ctx context.Context, groupID string)
 | 
				
			|||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupCacheRedis) DelGroupsMemberNum(groupID ...string) GroupCache {
 | 
					func (g *GroupCacheRedis) DelGroupsMemberNum(groupID ...string) cache.GroupCache {
 | 
				
			||||||
	keys := make([]string, 0, len(groupID))
 | 
						keys := make([]string, 0, len(groupID))
 | 
				
			||||||
	for _, groupID := range groupID {
 | 
						for _, groupID := range groupID {
 | 
				
			||||||
		keys = append(keys, g.getGroupMemberNumKey(groupID))
 | 
							keys = append(keys, g.getGroupMemberNumKey(groupID))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	cache := g.NewCache()
 | 
						cache := g.CloneGroupCache()
 | 
				
			||||||
	cache.AddKeys(keys...)
 | 
						cache.AddKeys(keys...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return cache
 | 
						return cache
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupCacheRedis) GetGroupOwner(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error) {
 | 
					func (g *GroupCacheRedis) GetGroupOwner(ctx context.Context, groupID string) (*model.GroupMember, error) {
 | 
				
			||||||
	members, err := g.GetGroupRoleLevelMemberInfo(ctx, groupID, constant.GroupOwner)
 | 
						members, err := g.GetGroupRoleLevelMemberInfo(ctx, groupID, constant.GroupOwner)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
@ -389,8 +353,8 @@ func (g *GroupCacheRedis) GetGroupOwner(ctx context.Context, groupID string) (*r
 | 
				
			|||||||
	return members[0], nil
 | 
						return members[0], nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupCacheRedis) GetGroupsOwner(ctx context.Context, groupIDs []string) ([]*relationtb.GroupMemberModel, error) {
 | 
					func (g *GroupCacheRedis) GetGroupsOwner(ctx context.Context, groupIDs []string) ([]*model.GroupMember, error) {
 | 
				
			||||||
	members := make([]*relationtb.GroupMemberModel, 0, len(groupIDs))
 | 
						members := make([]*model.GroupMember, 0, len(groupIDs))
 | 
				
			||||||
	for _, groupID := range groupIDs {
 | 
						for _, groupID := range groupIDs {
 | 
				
			||||||
		items, err := g.GetGroupRoleLevelMemberInfo(ctx, groupID, constant.GroupOwner)
 | 
							items, err := g.GetGroupRoleLevelMemberInfo(ctx, groupID, constant.GroupOwner)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
@ -409,7 +373,7 @@ func (g *GroupCacheRedis) GetGroupRoleLevelMemberIDs(ctx context.Context, groupI
 | 
				
			|||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupCacheRedis) GetGroupRoleLevelMemberInfo(ctx context.Context, groupID string, roleLevel int32) ([]*relationtb.GroupMemberModel, error) {
 | 
					func (g *GroupCacheRedis) GetGroupRoleLevelMemberInfo(ctx context.Context, groupID string, roleLevel int32) ([]*model.GroupMember, error) {
 | 
				
			||||||
	userIDs, err := g.GetGroupRoleLevelMemberIDs(ctx, groupID, roleLevel)
 | 
						userIDs, err := g.GetGroupRoleLevelMemberIDs(ctx, groupID, roleLevel)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
@ -417,7 +381,7 @@ func (g *GroupCacheRedis) GetGroupRoleLevelMemberInfo(ctx context.Context, group
 | 
				
			|||||||
	return g.GetGroupMembersInfo(ctx, groupID, userIDs)
 | 
						return g.GetGroupMembersInfo(ctx, groupID, userIDs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupCacheRedis) GetGroupRolesLevelMemberInfo(ctx context.Context, groupID string, roleLevels []int32) ([]*relationtb.GroupMemberModel, error) {
 | 
					func (g *GroupCacheRedis) GetGroupRolesLevelMemberInfo(ctx context.Context, groupID string, roleLevels []int32) ([]*model.GroupMember, error) {
 | 
				
			||||||
	var userIDs []string
 | 
						var userIDs []string
 | 
				
			||||||
	for _, roleLevel := range roleLevels {
 | 
						for _, roleLevel := range roleLevels {
 | 
				
			||||||
		ids, err := g.GetGroupRoleLevelMemberIDs(ctx, groupID, roleLevel)
 | 
							ids, err := g.GetGroupRoleLevelMemberIDs(ctx, groupID, roleLevel)
 | 
				
			||||||
@ -429,16 +393,16 @@ func (g *GroupCacheRedis) GetGroupRolesLevelMemberInfo(ctx context.Context, grou
 | 
				
			|||||||
	return g.GetGroupMembersInfo(ctx, groupID, userIDs)
 | 
						return g.GetGroupMembersInfo(ctx, groupID, userIDs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *GroupCacheRedis) FindGroupMemberUser(ctx context.Context, groupIDs []string, userID string) (_ []*relationtb.GroupMemberModel, err error) {
 | 
					func (g *GroupCacheRedis) FindGroupMemberUser(ctx context.Context, groupIDs []string, userID string) (_ []*model.GroupMember, err error) {
 | 
				
			||||||
	if len(groupIDs) == 0 {
 | 
						if len(groupIDs) == 0 {
 | 
				
			||||||
		groupIDs, err = g.GetJoinedGroupIDs(ctx, userID)
 | 
							groupIDs, err = g.GetJoinedGroupIDs(ctx, userID)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return batchGetCache2(ctx, g.rcClient, g.expireTime, groupIDs, func(groupID string) string {
 | 
						return batchGetCache(ctx, g.rcClient, g.expireTime, groupIDs, func(groupID string) string {
 | 
				
			||||||
		return g.getGroupMemberInfoKey(groupID, userID)
 | 
							return g.getGroupMemberInfoKey(groupID, userID)
 | 
				
			||||||
	}, func(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error) {
 | 
						}, func(ctx context.Context, groupID string) (*model.GroupMember, error) {
 | 
				
			||||||
		return g.groupMemberDB.Take(ctx, groupID, userID)
 | 
							return g.groupMemberDB.Take(ctx, groupID, userID)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										15
									
								
								pkg/common/storage/cache/redis/meta_cache.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								pkg/common/storage/cache/redis/meta_cache.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					// Copyright © 2023 OpenIM. All rights reserved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package redis
 | 
				
			||||||
@ -12,15 +12,14 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package cache
 | 
					package redis
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"strconv"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/gogo/protobuf/jsonpb"
 | 
						"github.com/gogo/protobuf/jsonpb"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/cachekey"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
 | 
				
			||||||
	"github.com/openimsdk/protocol/constant"
 | 
						"github.com/openimsdk/protocol/constant"
 | 
				
			||||||
	"github.com/openimsdk/protocol/sdkws"
 | 
						"github.com/openimsdk/protocol/sdkws"
 | 
				
			||||||
@ -29,78 +28,48 @@ import (
 | 
				
			|||||||
	"github.com/openimsdk/tools/utils/stringutil"
 | 
						"github.com/openimsdk/tools/utils/stringutil"
 | 
				
			||||||
	"github.com/redis/go-redis/v9"
 | 
						"github.com/redis/go-redis/v9"
 | 
				
			||||||
	"golang.org/x/sync/errgroup"
 | 
						"golang.org/x/sync/errgroup"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const msgCacheTimeout = 86400 * time.Second
 | 
					const msgCacheTimeout = 86400 * time.Second
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	maxSeq                 = "MAX_SEQ:"
 | 
					 | 
				
			||||||
	minSeq                 = "MIN_SEQ:"
 | 
					 | 
				
			||||||
	conversationUserMinSeq = "CON_USER_MIN_SEQ:"
 | 
					 | 
				
			||||||
	hasReadSeq             = "HAS_READ_SEQ:"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	getuiToken  = "GETUI_TOKEN"
 | 
					 | 
				
			||||||
	getuiTaskID = "GETUI_TASK_ID"
 | 
					 | 
				
			||||||
	FCM_TOKEN   = "FCM_TOKEN:"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	messageCache            = "MESSAGE_CACHE:"
 | 
					 | 
				
			||||||
	messageDelUserList      = "MESSAGE_DEL_USER_LIST:"
 | 
					 | 
				
			||||||
	userDelMessagesList     = "USER_DEL_MESSAGES_LIST:"
 | 
					 | 
				
			||||||
	sendMsgFailedFlag       = "SEND_MSG_FAILED_FLAG:"
 | 
					 | 
				
			||||||
	userBadgeUnreadCountSum = "USER_BADGE_UNREAD_COUNT_SUM:"
 | 
					 | 
				
			||||||
	exTypeKeyLocker         = "EX_LOCK:"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var concurrentLimit = 3
 | 
					var concurrentLimit = 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//type MsgModel interface {
 | 
					func NewMsgCache(client redis.UniversalClient, redisEnablePipeline bool) cache.MsgCache {
 | 
				
			||||||
//	SeqCache
 | 
					 | 
				
			||||||
//	ThirdCache
 | 
					 | 
				
			||||||
//	MsgCache
 | 
					 | 
				
			||||||
//}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type MsgCache interface {
 | 
					 | 
				
			||||||
	GetMessagesBySeq(ctx context.Context, conversationID string, seqs []int64) (seqMsg []*sdkws.MsgData, failedSeqList []int64, err error)
 | 
					 | 
				
			||||||
	SetMessageToCache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) (int, error)
 | 
					 | 
				
			||||||
	UserDeleteMsgs(ctx context.Context, conversationID string, seqs []int64, userID string) error
 | 
					 | 
				
			||||||
	DelUserDeleteMsgsList(ctx context.Context, conversationID string, seqs []int64)
 | 
					 | 
				
			||||||
	DeleteMessages(ctx context.Context, conversationID string, seqs []int64) error
 | 
					 | 
				
			||||||
	GetUserDelList(ctx context.Context, userID, conversationID string) (seqs []int64, err error)
 | 
					 | 
				
			||||||
	CleanUpOneConversationAllMsg(ctx context.Context, conversationID string) error
 | 
					 | 
				
			||||||
	DelMsgFromCache(ctx context.Context, userID string, seqList []int64) error
 | 
					 | 
				
			||||||
	SetSendMsgStatus(ctx context.Context, id string, status int32) error
 | 
					 | 
				
			||||||
	GetSendMsgStatus(ctx context.Context, id string) (int32, error)
 | 
					 | 
				
			||||||
	JudgeMessageReactionExist(ctx context.Context, clientMsgID string, sessionType int32) (bool, error)
 | 
					 | 
				
			||||||
	GetOneMessageAllReactionList(ctx context.Context, clientMsgID string, sessionType int32) (map[string]string, error)
 | 
					 | 
				
			||||||
	DeleteOneMessageKey(ctx context.Context, clientMsgID string, sessionType int32, subKey string) error
 | 
					 | 
				
			||||||
	SetMessageReactionExpire(ctx context.Context, clientMsgID string, sessionType int32, expiration time.Duration) (bool, error)
 | 
					 | 
				
			||||||
	GetMessageTypeKeyValue(ctx context.Context, clientMsgID string, sessionType int32, typeKey string) (string, error)
 | 
					 | 
				
			||||||
	SetMessageTypeKeyValue(ctx context.Context, clientMsgID string, sessionType int32, typeKey, value string) error
 | 
					 | 
				
			||||||
	LockMessageTypeKey(ctx context.Context, clientMsgID string, TypeKey string) error
 | 
					 | 
				
			||||||
	UnLockMessageTypeKey(ctx context.Context, clientMsgID string, TypeKey string) error
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//func NewMsgCacheModel(client redis.UniversalClient, msgCacheTimeout int, redisConf *config.Redis) MsgModel {
 | 
					 | 
				
			||||||
//	return &msgCache{rdb: client, msgCacheTimeout: msgCacheTimeout, redisConf: redisConf}
 | 
					 | 
				
			||||||
//}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewMsgCache(client redis.UniversalClient, redisEnablePipeline bool) MsgCache {
 | 
					 | 
				
			||||||
	return &msgCache{rdb: client, msgCacheTimeout: msgCacheTimeout, redisEnablePipeline: redisEnablePipeline}
 | 
						return &msgCache{rdb: client, msgCacheTimeout: msgCacheTimeout, redisEnablePipeline: redisEnablePipeline}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type msgCache struct {
 | 
					type msgCache struct {
 | 
				
			||||||
	metaCache
 | 
					 | 
				
			||||||
	rdb                 redis.UniversalClient
 | 
						rdb                 redis.UniversalClient
 | 
				
			||||||
	msgCacheTimeout     time.Duration
 | 
						msgCacheTimeout     time.Duration
 | 
				
			||||||
	redisEnablePipeline bool
 | 
						redisEnablePipeline bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *msgCache) allMessageCacheKey(conversationID string) string {
 | 
					func (c *msgCache) getAllMessageCacheKey(conversationID string) string {
 | 
				
			||||||
	return messageCache + conversationID + "_*"
 | 
						return cachekey.GetAllMessageCacheKey(conversationID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *msgCache) getMessageCacheKey(conversationID string, seq int64) string {
 | 
					func (c *msgCache) getMessageCacheKey(conversationID string, seq int64) string {
 | 
				
			||||||
	return messageCache + conversationID + "_" + strconv.Itoa(int(seq))
 | 
						return cachekey.GetMessageCacheKey(conversationID, seq)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (c *msgCache) getMessageDelUserListKey(conversationID string, seq int64) string {
 | 
				
			||||||
 | 
						return cachekey.GetMessageDelUserListKey(conversationID, seq)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *msgCache) getUserDelList(conversationID, userID string) string {
 | 
				
			||||||
 | 
						return cachekey.GetUserDelListKey(conversationID, userID)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *msgCache) getSendMsgKey(id string) string {
 | 
				
			||||||
 | 
						return cachekey.GetSendMsgKey(id)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *msgCache) getLockMessageTypeKey(clientMsgID string, TypeKey string) string {
 | 
				
			||||||
 | 
						return cachekey.GetLockMessageTypeKey(clientMsgID, TypeKey)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *msgCache) getMessageReactionExPrefix(clientMsgID string, sessionType int32) string {
 | 
				
			||||||
 | 
						return cachekey.GetMessageReactionExKey(clientMsgID, sessionType)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *msgCache) SetMessageToCache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) (int, error) {
 | 
					func (c *msgCache) SetMessageToCache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) (int, error) {
 | 
				
			||||||
@ -164,14 +133,6 @@ func (c *msgCache) ParallelSetMessageToCache(ctx context.Context, conversationID
 | 
				
			|||||||
	return len(msgs), nil
 | 
						return len(msgs), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *msgCache) getMessageDelUserListKey(conversationID string, seq int64) string {
 | 
					 | 
				
			||||||
	return messageDelUserList + conversationID + ":" + strconv.Itoa(int(seq))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *msgCache) getUserDelList(conversationID, userID string) string {
 | 
					 | 
				
			||||||
	return userDelMessagesList + conversationID + ":" + userID
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *msgCache) UserDeleteMsgs(ctx context.Context, conversationID string, seqs []int64, userID string) error {
 | 
					func (c *msgCache) UserDeleteMsgs(ctx context.Context, conversationID string, seqs []int64, userID string) error {
 | 
				
			||||||
	for _, seq := range seqs {
 | 
						for _, seq := range seqs {
 | 
				
			||||||
		delUserListKey := c.getMessageDelUserListKey(conversationID, seq)
 | 
							delUserListKey := c.getMessageDelUserListKey(conversationID, seq)
 | 
				
			||||||
@ -193,27 +154,6 @@ func (c *msgCache) UserDeleteMsgs(ctx context.Context, conversationID string, se
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
	// pipe := c.rdb.Pipeline()
 | 
					 | 
				
			||||||
	// for _, seq := range seqs {
 | 
					 | 
				
			||||||
	//	delUserListKey := c.getMessageDelUserListKey(conversationID, seq)
 | 
					 | 
				
			||||||
	//	userDelListKey := c.getUserDelList(conversationID, userID)
 | 
					 | 
				
			||||||
	//	err := pipe.SAdd(ctx, delUserListKey, userID).Err()
 | 
					 | 
				
			||||||
	//	if err != nil {
 | 
					 | 
				
			||||||
	//		return errs.Wrap(err)
 | 
					 | 
				
			||||||
	//	}
 | 
					 | 
				
			||||||
	//	err = pipe.SAdd(ctx, userDelListKey, seq).Err()
 | 
					 | 
				
			||||||
	//	if err != nil {
 | 
					 | 
				
			||||||
	//		return errs.Wrap(err)
 | 
					 | 
				
			||||||
	//	}
 | 
					 | 
				
			||||||
	//	if err := pipe.Expire(ctx, delUserListKey, time.Duration(config.Config.MsgCacheTimeout)*time.Second).Err(); err != nil {
 | 
					 | 
				
			||||||
	//		return errs.Wrap(err)
 | 
					 | 
				
			||||||
	//	}
 | 
					 | 
				
			||||||
	//	if err := pipe.Expire(ctx, userDelListKey, time.Duration(config.Config.MsgCacheTimeout)*time.Second).Err(); err != nil {
 | 
					 | 
				
			||||||
	//		return errs.Wrap(err)
 | 
					 | 
				
			||||||
	//	}
 | 
					 | 
				
			||||||
	//}
 | 
					 | 
				
			||||||
	// _, err := pipe.Exec(ctx)
 | 
					 | 
				
			||||||
	// return errs.Wrap(err)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *msgCache) GetUserDelList(ctx context.Context, userID, conversationID string) (seqs []int64, err error) {
 | 
					func (c *msgCache) GetUserDelList(ctx context.Context, userID, conversationID string) (seqs []int64, err error) {
 | 
				
			||||||
@ -253,42 +193,6 @@ func (c *msgCache) DelUserDeleteMsgsList(ctx context.Context, conversationID str
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// for _, seq := range seqs {
 | 
					 | 
				
			||||||
	//	delUsers, err := c.rdb.SMembers(ctx, c.getMessageDelUserListKey(conversationID, seq)).Result()
 | 
					 | 
				
			||||||
	//	if err != nil {
 | 
					 | 
				
			||||||
	//		log.ZWarn(ctx, "DelUserDeleteMsgsList failed", err, "conversationID", conversationID, "seq", seq)
 | 
					 | 
				
			||||||
	//		continue
 | 
					 | 
				
			||||||
	//	}
 | 
					 | 
				
			||||||
	//	if len(delUsers) > 0 {
 | 
					 | 
				
			||||||
	//		pipe := c.rdb.Pipeline()
 | 
					 | 
				
			||||||
	//		var failedFlag bool
 | 
					 | 
				
			||||||
	//		for _, userID := range delUsers {
 | 
					 | 
				
			||||||
	//			err = pipe.SRem(ctx, c.getUserDelList(conversationID, userID), seq).Err()
 | 
					 | 
				
			||||||
	//			if err != nil {
 | 
					 | 
				
			||||||
	//				failedFlag = true
 | 
					 | 
				
			||||||
	//				log.ZWarn(
 | 
					 | 
				
			||||||
	//					ctx,
 | 
					 | 
				
			||||||
	//					"DelUserDeleteMsgsList failed",
 | 
					 | 
				
			||||||
	//					err,
 | 
					 | 
				
			||||||
	//					"conversationID",
 | 
					 | 
				
			||||||
	//					conversationID,
 | 
					 | 
				
			||||||
	//					"seq",
 | 
					 | 
				
			||||||
	//					seq,
 | 
					 | 
				
			||||||
	//					"userID",
 | 
					 | 
				
			||||||
	//					userID,
 | 
					 | 
				
			||||||
	//				)
 | 
					 | 
				
			||||||
	//			}
 | 
					 | 
				
			||||||
	//		}
 | 
					 | 
				
			||||||
	//		if !failedFlag {
 | 
					 | 
				
			||||||
	//			if err := pipe.Del(ctx, c.getMessageDelUserListKey(conversationID, seq)).Err(); err != nil {
 | 
					 | 
				
			||||||
	//				log.ZWarn(ctx, "DelUserDeleteMsgsList failed", err, "conversationID", conversationID, "seq", seq)
 | 
					 | 
				
			||||||
	//			}
 | 
					 | 
				
			||||||
	//		}
 | 
					 | 
				
			||||||
	//		if _, err := pipe.Exec(ctx); err != nil {
 | 
					 | 
				
			||||||
	//			log.ZError(ctx, "pipe exec failed", err, "conversationID", conversationID, "seq", seq)
 | 
					 | 
				
			||||||
	//		}
 | 
					 | 
				
			||||||
	//	}
 | 
					 | 
				
			||||||
	//}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *msgCache) DeleteMessages(ctx context.Context, conversationID string, seqs []int64) error {
 | 
					func (c *msgCache) DeleteMessages(ctx context.Context, conversationID string, seqs []int64) error {
 | 
				
			||||||
@ -338,7 +242,7 @@ func (c *msgCache) PipeDeleteMessages(ctx context.Context, conversationID string
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *msgCache) CleanUpOneConversationAllMsg(ctx context.Context, conversationID string) error {
 | 
					func (c *msgCache) CleanUpOneConversationAllMsg(ctx context.Context, conversationID string) error {
 | 
				
			||||||
	vals, err := c.rdb.Keys(ctx, c.allMessageCacheKey(conversationID)).Result()
 | 
						vals, err := c.rdb.Keys(ctx, c.getAllMessageCacheKey(conversationID)).Result()
 | 
				
			||||||
	if errors.Is(err, redis.Nil) {
 | 
						if errors.Is(err, redis.Nil) {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -383,42 +287,24 @@ func (c *msgCache) DelMsgFromCache(ctx context.Context, userID string, seqs []in
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *msgCache) SetSendMsgStatus(ctx context.Context, id string, status int32) error {
 | 
					func (c *msgCache) SetSendMsgStatus(ctx context.Context, id string, status int32) error {
 | 
				
			||||||
	return errs.Wrap(c.rdb.Set(ctx, sendMsgFailedFlag+id, status, time.Hour*24).Err())
 | 
						return errs.Wrap(c.rdb.Set(ctx, c.getSendMsgKey(id), status, time.Hour*24).Err())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *msgCache) GetSendMsgStatus(ctx context.Context, id string) (int32, error) {
 | 
					func (c *msgCache) GetSendMsgStatus(ctx context.Context, id string) (int32, error) {
 | 
				
			||||||
	result, err := c.rdb.Get(ctx, sendMsgFailedFlag+id).Int()
 | 
						result, err := c.rdb.Get(ctx, c.getSendMsgKey(id)).Int()
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return int32(result), errs.Wrap(err)
 | 
						return int32(result), errs.Wrap(err)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *msgCache) LockMessageTypeKey(ctx context.Context, clientMsgID string, TypeKey string) error {
 | 
					func (c *msgCache) LockMessageTypeKey(ctx context.Context, clientMsgID string, TypeKey string) error {
 | 
				
			||||||
	key := exTypeKeyLocker + clientMsgID + "_" + TypeKey
 | 
						key := c.getLockMessageTypeKey(clientMsgID, TypeKey)
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return errs.Wrap(c.rdb.SetNX(ctx, key, 1, time.Minute).Err())
 | 
						return errs.Wrap(c.rdb.SetNX(ctx, key, 1, time.Minute).Err())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *msgCache) UnLockMessageTypeKey(ctx context.Context, clientMsgID string, TypeKey string) error {
 | 
					func (c *msgCache) UnLockMessageTypeKey(ctx context.Context, clientMsgID string, TypeKey string) error {
 | 
				
			||||||
	key := exTypeKeyLocker + clientMsgID + "_" + TypeKey
 | 
						key := c.getLockMessageTypeKey(clientMsgID, TypeKey)
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return errs.Wrap(c.rdb.Del(ctx, key).Err())
 | 
						return errs.Wrap(c.rdb.Del(ctx, key).Err())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *msgCache) getMessageReactionExPrefix(clientMsgID string, sessionType int32) string {
 | 
					 | 
				
			||||||
	switch sessionType {
 | 
					 | 
				
			||||||
	case constant.SingleChatType:
 | 
					 | 
				
			||||||
		return "EX_SINGLE_" + clientMsgID
 | 
					 | 
				
			||||||
	case constant.WriteGroupChatType:
 | 
					 | 
				
			||||||
		return "EX_GROUP_" + clientMsgID
 | 
					 | 
				
			||||||
	case constant.ReadGroupChatType:
 | 
					 | 
				
			||||||
		return "EX_SUPER_GROUP_" + clientMsgID
 | 
					 | 
				
			||||||
	case constant.NotificationChatType:
 | 
					 | 
				
			||||||
		return "EX_NOTIFICATION" + clientMsgID
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ""
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *msgCache) JudgeMessageReactionExist(ctx context.Context, clientMsgID string, sessionType int32) (bool, error) {
 | 
					func (c *msgCache) JudgeMessageReactionExist(ctx context.Context, clientMsgID string, sessionType int32) (bool, error) {
 | 
				
			||||||
	n, err := c.rdb.Exists(ctx, c.getMessageReactionExPrefix(clientMsgID, sessionType)).Result()
 | 
						n, err := c.rdb.Exists(ctx, c.getMessageReactionExPrefix(clientMsgID, sessionType)).Result()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -12,17 +12,16 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package cache
 | 
					package redis
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"math/rand"
 | 
					 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/openimsdk/protocol/sdkws"
 | 
						"github.com/openimsdk/protocol/sdkws"
 | 
				
			||||||
	"github.com/redis/go-redis/v9"
 | 
						"github.com/redis/go-redis/v9"
 | 
				
			||||||
	"github.com/stretchr/testify/assert"
 | 
						"github.com/stretchr/testify/assert"
 | 
				
			||||||
 | 
						"math/rand"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestParallelSetMessageToCache(t *testing.T) {
 | 
					func TestParallelSetMessageToCache(t *testing.T) {
 | 
				
			||||||
@ -12,55 +12,55 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package cache
 | 
					package redis
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"github.com/dtm-labs/rockscache"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/cachekey"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
 | 
						"github.com/openimsdk/tools/s3"
 | 
				
			||||||
	"github.com/openimsdk/tools/s3/cont"
 | 
						"github.com/openimsdk/tools/s3/cont"
 | 
				
			||||||
	"github.com/openimsdk/tools/s3/minio"
 | 
						"github.com/openimsdk/tools/s3/minio"
 | 
				
			||||||
	"strconv"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/dtm-labs/rockscache"
 | 
					 | 
				
			||||||
	relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/tools/s3"
 | 
					 | 
				
			||||||
	"github.com/redis/go-redis/v9"
 | 
						"github.com/redis/go-redis/v9"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type ObjectCache interface {
 | 
					func NewObjectCacheRedis(rdb redis.UniversalClient, objDB database.ObjectInfo) cache.ObjectCache {
 | 
				
			||||||
	metaCache
 | 
						opts := rockscache.NewDefaultOptions()
 | 
				
			||||||
	GetName(ctx context.Context, engine string, name string) (*relationtb.ObjectModel, error)
 | 
						batchHandler := NewBatchDeleterRedis(rdb, &opts, nil)
 | 
				
			||||||
	DelObjectName(engine string, names ...string) ObjectCache
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewObjectCacheRedis(rdb redis.UniversalClient, objDB relationtb.ObjectInfoModelInterface) ObjectCache {
 | 
					 | 
				
			||||||
	rcClient := rockscache.NewClient(rdb, rockscache.NewDefaultOptions())
 | 
					 | 
				
			||||||
	return &objectCacheRedis{
 | 
						return &objectCacheRedis{
 | 
				
			||||||
		rcClient:   rcClient,
 | 
							BatchDeleter: batchHandler,
 | 
				
			||||||
		expireTime: time.Hour * 12,
 | 
							rcClient:     rockscache.NewClient(rdb, opts),
 | 
				
			||||||
		objDB:      objDB,
 | 
							expireTime:   time.Hour * 12,
 | 
				
			||||||
		metaCache:  NewMetaCacheRedis(rcClient),
 | 
							objDB:        objDB,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type objectCacheRedis struct {
 | 
					type objectCacheRedis struct {
 | 
				
			||||||
	metaCache
 | 
						cache.BatchDeleter
 | 
				
			||||||
	objDB      relationtb.ObjectInfoModelInterface
 | 
						objDB      database.ObjectInfo
 | 
				
			||||||
	rcClient   *rockscache.Client
 | 
						rcClient   *rockscache.Client
 | 
				
			||||||
	expireTime time.Duration
 | 
						expireTime time.Duration
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *objectCacheRedis) NewCache() ObjectCache {
 | 
					func (g *objectCacheRedis) getObjectKey(engine string, name string) string {
 | 
				
			||||||
 | 
						return cachekey.GetObjectKey(engine, name)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (g *objectCacheRedis) CloneObjectCache() cache.ObjectCache {
 | 
				
			||||||
	return &objectCacheRedis{
 | 
						return &objectCacheRedis{
 | 
				
			||||||
		rcClient:   g.rcClient,
 | 
							BatchDeleter: g.BatchDeleter.Clone(),
 | 
				
			||||||
		expireTime: g.expireTime,
 | 
							rcClient:     g.rcClient,
 | 
				
			||||||
		objDB:      g.objDB,
 | 
							expireTime:   g.expireTime,
 | 
				
			||||||
		metaCache:  NewMetaCacheRedis(g.rcClient, g.metaCache.GetPreDelKeys()...),
 | 
							objDB:        g.objDB,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *objectCacheRedis) DelObjectName(engine string, names ...string) ObjectCache {
 | 
					func (g *objectCacheRedis) DelObjectName(engine string, names ...string) cache.ObjectCache {
 | 
				
			||||||
	objectCache := g.NewCache()
 | 
						objectCache := g.CloneObjectCache()
 | 
				
			||||||
	keys := make([]string, 0, len(names))
 | 
						keys := make([]string, 0, len(names))
 | 
				
			||||||
	for _, name := range names {
 | 
						for _, name := range names {
 | 
				
			||||||
		keys = append(keys, g.getObjectKey(name, engine))
 | 
							keys = append(keys, g.getObjectKey(name, engine))
 | 
				
			||||||
@ -69,60 +69,40 @@ func (g *objectCacheRedis) DelObjectName(engine string, names ...string) ObjectC
 | 
				
			|||||||
	return objectCache
 | 
						return objectCache
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *objectCacheRedis) getObjectKey(engine string, name string) string {
 | 
					func (g *objectCacheRedis) GetName(ctx context.Context, engine string, name string) (*model.Object, error) {
 | 
				
			||||||
	return "OBJECT:" + engine + ":" + name
 | 
						return getCache(ctx, g.rcClient, g.getObjectKey(name, engine), g.expireTime, func(ctx context.Context) (*model.Object, error) {
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (g *objectCacheRedis) GetName(ctx context.Context, engine string, name string) (*relationtb.ObjectModel, error) {
 | 
					 | 
				
			||||||
	return getCache(ctx, g.rcClient, g.getObjectKey(name, engine), g.expireTime, func(ctx context.Context) (*relationtb.ObjectModel, error) {
 | 
					 | 
				
			||||||
		return g.objDB.Take(ctx, engine, name)
 | 
							return g.objDB.Take(ctx, engine, name)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type S3Cache interface {
 | 
					 | 
				
			||||||
	metaCache
 | 
					 | 
				
			||||||
	GetKey(ctx context.Context, engine string, key string) (*s3.ObjectInfo, error)
 | 
					 | 
				
			||||||
	DelS3Key(engine string, keys ...string) S3Cache
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewS3Cache(rdb redis.UniversalClient, s3 s3.Interface) cont.S3Cache {
 | 
					func NewS3Cache(rdb redis.UniversalClient, s3 s3.Interface) cont.S3Cache {
 | 
				
			||||||
	rcClient := rockscache.NewClient(rdb, rockscache.NewDefaultOptions())
 | 
						opts := rockscache.NewDefaultOptions()
 | 
				
			||||||
 | 
						batchHandler := NewBatchDeleterRedis(rdb, &opts, nil)
 | 
				
			||||||
	return &s3CacheRedis{
 | 
						return &s3CacheRedis{
 | 
				
			||||||
		rcClient:   rcClient,
 | 
							BatchDeleter: batchHandler,
 | 
				
			||||||
		expireTime: time.Hour * 12,
 | 
							rcClient:     rockscache.NewClient(rdb, opts),
 | 
				
			||||||
		s3:         s3,
 | 
							expireTime:   time.Hour * 12,
 | 
				
			||||||
		metaCache:  NewMetaCacheRedis(rcClient),
 | 
							s3:           s3,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type s3CacheRedis struct {
 | 
					type s3CacheRedis struct {
 | 
				
			||||||
	metaCache
 | 
						cache.BatchDeleter
 | 
				
			||||||
	s3         s3.Interface
 | 
						s3         s3.Interface
 | 
				
			||||||
	rcClient   *rockscache.Client
 | 
						rcClient   *rockscache.Client
 | 
				
			||||||
	expireTime time.Duration
 | 
						expireTime time.Duration
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *s3CacheRedis) newCache() *s3CacheRedis {
 | 
					func (g *s3CacheRedis) getS3Key(engine string, name string) string {
 | 
				
			||||||
	return &s3CacheRedis{
 | 
						return cachekey.GetS3Key(engine, name)
 | 
				
			||||||
		rcClient:   g.rcClient,
 | 
					 | 
				
			||||||
		expireTime: g.expireTime,
 | 
					 | 
				
			||||||
		s3:         g.s3,
 | 
					 | 
				
			||||||
		metaCache:  NewMetaCacheRedis(g.rcClient, g.metaCache.GetPreDelKeys()...),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *s3CacheRedis) DelS3Key(ctx context.Context, engine string, keys ...string) error {
 | 
					func (g *s3CacheRedis) DelS3Key(ctx context.Context, engine string, keys ...string) error {
 | 
				
			||||||
	s3cache := g.newCache()
 | 
					 | 
				
			||||||
	ks := make([]string, 0, len(keys))
 | 
						ks := make([]string, 0, len(keys))
 | 
				
			||||||
	for _, key := range keys {
 | 
						for _, key := range keys {
 | 
				
			||||||
		ks = append(ks, g.getS3Key(engine, key))
 | 
							ks = append(ks, g.getS3Key(engine, key))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	s3cache.AddKeys(ks...)
 | 
						return g.BatchDeleter.ExecDelWithKeys(ctx, ks)
 | 
				
			||||||
	return s3cache.ExecDel(ctx)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (g *s3CacheRedis) getS3Key(engine string, name string) string {
 | 
					 | 
				
			||||||
	return "S3:" + engine + ":" + name
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *s3CacheRedis) GetKey(ctx context.Context, engine string, name string) (*s3.ObjectInfo, error) {
 | 
					func (g *s3CacheRedis) GetKey(ctx context.Context, engine string, name string) (*s3.ObjectInfo, error) {
 | 
				
			||||||
@ -131,59 +111,41 @@ func (g *s3CacheRedis) GetKey(ctx context.Context, engine string, name string) (
 | 
				
			|||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type MinioCache interface {
 | 
					 | 
				
			||||||
	metaCache
 | 
					 | 
				
			||||||
	GetImageObjectKeyInfo(ctx context.Context, key string, fn func(ctx context.Context) (*MinioImageInfo, error)) (*MinioImageInfo, error)
 | 
					 | 
				
			||||||
	GetThumbnailKey(ctx context.Context, key string, format string, width int, height int, minioCache func(ctx context.Context) (string, error)) (string, error)
 | 
					 | 
				
			||||||
	DelObjectImageInfoKey(keys ...string) MinioCache
 | 
					 | 
				
			||||||
	DelImageThumbnailKey(key string, format string, width int, height int) MinioCache
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewMinioCache(rdb redis.UniversalClient) minio.Cache {
 | 
					func NewMinioCache(rdb redis.UniversalClient) minio.Cache {
 | 
				
			||||||
	rcClient := rockscache.NewClient(rdb, rockscache.NewDefaultOptions())
 | 
						opts := rockscache.NewDefaultOptions()
 | 
				
			||||||
 | 
						batchHandler := NewBatchDeleterRedis(rdb, &opts, nil)
 | 
				
			||||||
	return &minioCacheRedis{
 | 
						return &minioCacheRedis{
 | 
				
			||||||
		rcClient:   rcClient,
 | 
							BatchDeleter: batchHandler,
 | 
				
			||||||
		expireTime: time.Hour * 24 * 7,
 | 
							rcClient:     rockscache.NewClient(rdb, opts),
 | 
				
			||||||
		metaCache:  NewMetaCacheRedis(rcClient),
 | 
							expireTime:   time.Hour * 24 * 7,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type minioCacheRedis struct {
 | 
					type minioCacheRedis struct {
 | 
				
			||||||
	metaCache
 | 
						cache.BatchDeleter
 | 
				
			||||||
	rcClient   *rockscache.Client
 | 
						rcClient   *rockscache.Client
 | 
				
			||||||
	expireTime time.Duration
 | 
						expireTime time.Duration
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *minioCacheRedis) newCache() *minioCacheRedis {
 | 
					func (g *minioCacheRedis) getObjectImageInfoKey(key string) string {
 | 
				
			||||||
	return &minioCacheRedis{
 | 
						return cachekey.GetObjectImageInfoKey(key)
 | 
				
			||||||
		rcClient:   g.rcClient,
 | 
					}
 | 
				
			||||||
		expireTime: g.expireTime,
 | 
					
 | 
				
			||||||
		metaCache:  NewMetaCacheRedis(g.rcClient, g.metaCache.GetPreDelKeys()...),
 | 
					func (g *minioCacheRedis) getMinioImageThumbnailKey(key string, format string, width int, height int) string {
 | 
				
			||||||
	}
 | 
						return cachekey.GetMinioImageThumbnailKey(key, format, width, height)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *minioCacheRedis) DelObjectImageInfoKey(ctx context.Context, keys ...string) error {
 | 
					func (g *minioCacheRedis) DelObjectImageInfoKey(ctx context.Context, keys ...string) error {
 | 
				
			||||||
	s3cache := g.newCache()
 | 
					 | 
				
			||||||
	ks := make([]string, 0, len(keys))
 | 
						ks := make([]string, 0, len(keys))
 | 
				
			||||||
	for _, key := range keys {
 | 
						for _, key := range keys {
 | 
				
			||||||
		ks = append(ks, g.getObjectImageInfoKey(key))
 | 
							ks = append(ks, g.getObjectImageInfoKey(key))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	s3cache.AddKeys(ks...)
 | 
						return g.BatchDeleter.ExecDelWithKeys(ctx, ks)
 | 
				
			||||||
	return s3cache.ExecDel(ctx)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *minioCacheRedis) DelImageThumbnailKey(ctx context.Context, key string, format string, width int, height int) error {
 | 
					func (g *minioCacheRedis) DelImageThumbnailKey(ctx context.Context, key string, format string, width int, height int) error {
 | 
				
			||||||
	s3cache := g.newCache()
 | 
						return g.BatchDeleter.ExecDelWithKeys(ctx, []string{g.getMinioImageThumbnailKey(key, format, width, height)})
 | 
				
			||||||
	s3cache.AddKeys(g.getMinioImageThumbnailKey(key, format, width, height))
 | 
					 | 
				
			||||||
	return s3cache.ExecDel(ctx)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *minioCacheRedis) getObjectImageInfoKey(key string) string {
 | 
					 | 
				
			||||||
	return "MINIO:IMAGE:" + key
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (g *minioCacheRedis) getMinioImageThumbnailKey(key string, format string, width int, height int) string {
 | 
					 | 
				
			||||||
	return "MINIO:THUMBNAIL:" + format + ":w" + strconv.Itoa(width) + ":h" + strconv.Itoa(height) + ":" + key
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *minioCacheRedis) GetImageObjectKeyInfo(ctx context.Context, key string, fn func(ctx context.Context) (*minio.ImageInfo, error)) (*minio.ImageInfo, error) {
 | 
					func (g *minioCacheRedis) GetImageObjectKeyInfo(ctx context.Context, key string, fn func(ctx context.Context) (*minio.ImageInfo, error)) (*minio.ImageInfo, error) {
 | 
				
			||||||
@ -197,11 +159,3 @@ func (g *minioCacheRedis) GetImageObjectKeyInfo(ctx context.Context, key string,
 | 
				
			|||||||
func (g *minioCacheRedis) GetThumbnailKey(ctx context.Context, key string, format string, width int, height int, minioCache func(ctx context.Context) (string, error)) (string, error) {
 | 
					func (g *minioCacheRedis) GetThumbnailKey(ctx context.Context, key string, format string, width int, height int, minioCache func(ctx context.Context) (string, error)) (string, error) {
 | 
				
			||||||
	return getCache(ctx, g.rcClient, g.getMinioImageThumbnailKey(key, format, width, height), g.expireTime, minioCache)
 | 
						return getCache(ctx, g.rcClient, g.getMinioImageThumbnailKey(key, format, width, height), g.expireTime, minioCache)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
type MinioImageInfo struct {
 | 
					 | 
				
			||||||
	IsImg  bool   `json:"isImg"`
 | 
					 | 
				
			||||||
	Width  int    `json:"width"`
 | 
					 | 
				
			||||||
	Height int    `json:"height"`
 | 
					 | 
				
			||||||
	Format string `json:"format"`
 | 
					 | 
				
			||||||
	Etag   string `json:"etag"`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,38 +1,29 @@
 | 
				
			|||||||
package cache
 | 
					// Copyright © 2023 OpenIM. All rights reserved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package redis
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/cachekey"
 | 
				
			||||||
	"github.com/openimsdk/tools/errs"
 | 
						"github.com/openimsdk/tools/errs"
 | 
				
			||||||
	"github.com/openimsdk/tools/utils/stringutil"
 | 
						"github.com/openimsdk/tools/utils/stringutil"
 | 
				
			||||||
	"github.com/redis/go-redis/v9"
 | 
						"github.com/redis/go-redis/v9"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type SeqCache interface {
 | 
					func NewSeqCache(rdb redis.UniversalClient) cache.SeqCache {
 | 
				
			||||||
	SetMaxSeq(ctx context.Context, conversationID string, maxSeq int64) error
 | 
					 | 
				
			||||||
	GetMaxSeqs(ctx context.Context, conversationIDs []string) (map[string]int64, error)
 | 
					 | 
				
			||||||
	GetMaxSeq(ctx context.Context, conversationID string) (int64, error)
 | 
					 | 
				
			||||||
	SetMinSeq(ctx context.Context, conversationID string, minSeq int64) error
 | 
					 | 
				
			||||||
	SetMinSeqs(ctx context.Context, seqs map[string]int64) error
 | 
					 | 
				
			||||||
	GetMinSeqs(ctx context.Context, conversationIDs []string) (map[string]int64, error)
 | 
					 | 
				
			||||||
	GetMinSeq(ctx context.Context, conversationID string) (int64, error)
 | 
					 | 
				
			||||||
	GetConversationUserMinSeq(ctx context.Context, conversationID string, userID string) (int64, error)
 | 
					 | 
				
			||||||
	GetConversationUserMinSeqs(ctx context.Context, conversationID string, userIDs []string) (map[string]int64, error)
 | 
					 | 
				
			||||||
	SetConversationUserMinSeq(ctx context.Context, conversationID string, userID string, minSeq int64) error
 | 
					 | 
				
			||||||
	// seqs map: key userID value minSeq
 | 
					 | 
				
			||||||
	SetConversationUserMinSeqs(ctx context.Context, conversationID string, seqs map[string]int64) (err error)
 | 
					 | 
				
			||||||
	// seqs map: key conversationID value minSeq
 | 
					 | 
				
			||||||
	SetUserConversationsMinSeqs(ctx context.Context, userID string, seqs map[string]int64) error
 | 
					 | 
				
			||||||
	// has read seq
 | 
					 | 
				
			||||||
	SetHasReadSeq(ctx context.Context, userID string, conversationID string, hasReadSeq int64) error
 | 
					 | 
				
			||||||
	// k: user, v: seq
 | 
					 | 
				
			||||||
	SetHasReadSeqs(ctx context.Context, conversationID string, hasReadSeqs map[string]int64) error
 | 
					 | 
				
			||||||
	// k: conversation, v :seq
 | 
					 | 
				
			||||||
	UserSetHasReadSeqs(ctx context.Context, userID string, hasReadSeqs map[string]int64) error
 | 
					 | 
				
			||||||
	GetHasReadSeqs(ctx context.Context, userID string, conversationIDs []string) (map[string]int64, error)
 | 
					 | 
				
			||||||
	GetHasReadSeq(ctx context.Context, userID string, conversationID string) (int64, error)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewSeqCache(rdb redis.UniversalClient) SeqCache {
 | 
					 | 
				
			||||||
	return &seqCache{rdb: rdb}
 | 
						return &seqCache{rdb: rdb}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -41,19 +32,19 @@ type seqCache struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *seqCache) getMaxSeqKey(conversationID string) string {
 | 
					func (c *seqCache) getMaxSeqKey(conversationID string) string {
 | 
				
			||||||
	return maxSeq + conversationID
 | 
						return cachekey.GetMaxSeqKey(conversationID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *seqCache) getMinSeqKey(conversationID string) string {
 | 
					func (c *seqCache) getMinSeqKey(conversationID string) string {
 | 
				
			||||||
	return minSeq + conversationID
 | 
						return cachekey.GetMinSeqKey(conversationID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *seqCache) getHasReadSeqKey(conversationID string, userID string) string {
 | 
					func (c *seqCache) getHasReadSeqKey(conversationID string, userID string) string {
 | 
				
			||||||
	return hasReadSeq + userID + ":" + conversationID
 | 
						return cachekey.GetHasReadSeqKey(conversationID, userID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *seqCache) getConversationUserMinSeqKey(conversationID, userID string) string {
 | 
					func (c *seqCache) getConversationUserMinSeqKey(conversationID, userID string) string {
 | 
				
			||||||
	return conversationUserMinSeq + conversationID + "u:" + userID
 | 
						return cachekey.GetConversationUserMinSeqKey(conversationID, userID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *seqCache) setSeq(ctx context.Context, conversationID string, seq int64, getkey func(conversationID string) string) error {
 | 
					func (c *seqCache) setSeq(ctx context.Context, conversationID string, seq int64, getkey func(conversationID string) string) error {
 | 
				
			||||||
							
								
								
									
										103
									
								
								pkg/common/storage/cache/redis/third.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								pkg/common/storage/cache/redis/third.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,103 @@
 | 
				
			|||||||
 | 
					// Copyright © 2023 OpenIM. All rights reserved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package redis
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/cachekey"
 | 
				
			||||||
 | 
						"github.com/openimsdk/tools/errs"
 | 
				
			||||||
 | 
						"github.com/redis/go-redis/v9"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewThirdCache(rdb redis.UniversalClient) cache.ThirdCache {
 | 
				
			||||||
 | 
						return &thirdCache{rdb: rdb}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type thirdCache struct {
 | 
				
			||||||
 | 
						rdb redis.UniversalClient
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *thirdCache) getGetuiTokenKey() string {
 | 
				
			||||||
 | 
						return cachekey.GetGetuiTokenKey()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *thirdCache) getGetuiTaskIDKey() string {
 | 
				
			||||||
 | 
						return cachekey.GetGetuiTaskIDKey()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *thirdCache) getUserBadgeUnreadCountSumKey(userID string) string {
 | 
				
			||||||
 | 
						return cachekey.GetUserBadgeUnreadCountSumKey(userID)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *thirdCache) getFcmAccountTokenKey(account string, platformID int) string {
 | 
				
			||||||
 | 
						return cachekey.GetFcmAccountTokenKey(account, platformID)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *thirdCache) SetFcmToken(ctx context.Context, account string, platformID int, fcmToken string, expireTime int64) (err error) {
 | 
				
			||||||
 | 
						return errs.Wrap(c.rdb.Set(ctx, c.getFcmAccountTokenKey(account, platformID), fcmToken, time.Duration(expireTime)*time.Second).Err())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *thirdCache) GetFcmToken(ctx context.Context, account string, platformID int) (string, error) {
 | 
				
			||||||
 | 
						val, err := c.rdb.Get(ctx, c.getFcmAccountTokenKey(account, platformID)).Result()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", errs.Wrap(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return val, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *thirdCache) DelFcmToken(ctx context.Context, account string, platformID int) error {
 | 
				
			||||||
 | 
						return errs.Wrap(c.rdb.Del(ctx, c.getFcmAccountTokenKey(account, platformID)).Err())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *thirdCache) IncrUserBadgeUnreadCountSum(ctx context.Context, userID string) (int, error) {
 | 
				
			||||||
 | 
						seq, err := c.rdb.Incr(ctx, c.getUserBadgeUnreadCountSumKey(userID)).Result()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return int(seq), errs.Wrap(err)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *thirdCache) SetUserBadgeUnreadCountSum(ctx context.Context, userID string, value int) error {
 | 
				
			||||||
 | 
						return errs.Wrap(c.rdb.Set(ctx, c.getUserBadgeUnreadCountSumKey(userID), value, 0).Err())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *thirdCache) GetUserBadgeUnreadCountSum(ctx context.Context, userID string) (int, error) {
 | 
				
			||||||
 | 
						val, err := c.rdb.Get(ctx, c.getUserBadgeUnreadCountSumKey(userID)).Int()
 | 
				
			||||||
 | 
						return val, errs.Wrap(err)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *thirdCache) SetGetuiToken(ctx context.Context, token string, expireTime int64) error {
 | 
				
			||||||
 | 
						return errs.Wrap(c.rdb.Set(ctx, c.getGetuiTokenKey(), token, time.Duration(expireTime)*time.Second).Err())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *thirdCache) GetGetuiToken(ctx context.Context) (string, error) {
 | 
				
			||||||
 | 
						val, err := c.rdb.Get(ctx, c.getGetuiTokenKey()).Result()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", errs.Wrap(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return val, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *thirdCache) SetGetuiTaskID(ctx context.Context, taskID string, expireTime int64) error {
 | 
				
			||||||
 | 
						return errs.Wrap(c.rdb.Set(ctx, c.getGetuiTaskIDKey(), taskID, time.Duration(expireTime)*time.Second).Err())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *thirdCache) GetGetuiTaskID(ctx context.Context) (string, error) {
 | 
				
			||||||
 | 
						val, err := c.rdb.Get(ctx, c.getGetuiTaskIDKey()).Result()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", errs.Wrap(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return val, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,31 +1,38 @@
 | 
				
			|||||||
package cache
 | 
					// Copyright © 2023 OpenIM. All rights reserved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package redis
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/cachekey"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/cachekey"
 | 
				
			||||||
	"github.com/openimsdk/tools/errs"
 | 
						"github.com/openimsdk/tools/errs"
 | 
				
			||||||
	"github.com/openimsdk/tools/utils/stringutil"
 | 
						"github.com/openimsdk/tools/utils/stringutil"
 | 
				
			||||||
	"github.com/redis/go-redis/v9"
 | 
						"github.com/redis/go-redis/v9"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewTokenCacheModel(rdb redis.UniversalClient) TokenModel {
 | 
					type tokenCache struct {
 | 
				
			||||||
 | 
						rdb redis.UniversalClient
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewTokenCacheModel(rdb redis.UniversalClient) cache.TokenModel {
 | 
				
			||||||
	return &tokenCache{
 | 
						return &tokenCache{
 | 
				
			||||||
		rdb: rdb,
 | 
							rdb: rdb,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type TokenModel interface {
 | 
					 | 
				
			||||||
	AddTokenFlag(ctx context.Context, userID string, platformID int, token string, flag int) error
 | 
					 | 
				
			||||||
	GetTokensWithoutError(ctx context.Context, userID string, platformID int) (map[string]int, error)
 | 
					 | 
				
			||||||
	SetTokenMapByUidPid(ctx context.Context, userID string, platformID int, m map[string]int) error
 | 
					 | 
				
			||||||
	DeleteTokenByUidPid(ctx context.Context, userID string, platformID int, fields []string) error
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type tokenCache struct {
 | 
					 | 
				
			||||||
	rdb redis.UniversalClient
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *tokenCache) AddTokenFlag(ctx context.Context, userID string, platformID int, token string, flag int) error {
 | 
					func (c *tokenCache) AddTokenFlag(ctx context.Context, userID string, platformID int, token string, flag int) error {
 | 
				
			||||||
	return errs.Wrap(c.rdb.HSet(ctx, cachekey.GetTokenKey(userID, platformID), token, flag).Err())
 | 
						return errs.Wrap(c.rdb.HSet(ctx, cachekey.GetTokenKey(userID, platformID), token, flag).Err())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -12,78 +12,66 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package cache
 | 
					package redis
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"hash/crc32"
 | 
					 | 
				
			||||||
	"strconv"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/dtm-labs/rockscache"
 | 
						"github.com/dtm-labs/rockscache"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/cachekey"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
				
			||||||
	relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/cachekey"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"github.com/openimsdk/protocol/constant"
 | 
						"github.com/openimsdk/protocol/constant"
 | 
				
			||||||
	"github.com/openimsdk/protocol/user"
 | 
						"github.com/openimsdk/protocol/user"
 | 
				
			||||||
	"github.com/openimsdk/tools/errs"
 | 
						"github.com/openimsdk/tools/errs"
 | 
				
			||||||
	"github.com/openimsdk/tools/log"
 | 
						"github.com/openimsdk/tools/log"
 | 
				
			||||||
	"github.com/redis/go-redis/v9"
 | 
						"github.com/redis/go-redis/v9"
 | 
				
			||||||
 | 
						"hash/crc32"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	userExpireTime            = time.Second * 60 * 60 * 12
 | 
						userExpireTime            = time.Second * 60 * 60 * 12
 | 
				
			||||||
	olineStatusKey            = "ONLINE_STATUS:"
 | 
					 | 
				
			||||||
	userOlineStatusExpireTime = time.Second * 60 * 60 * 24
 | 
						userOlineStatusExpireTime = time.Second * 60 * 60 * 24
 | 
				
			||||||
	statusMod                 = 501
 | 
						statusMod                 = 501
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type UserCache interface {
 | 
					 | 
				
			||||||
	metaCache
 | 
					 | 
				
			||||||
	NewCache() UserCache
 | 
					 | 
				
			||||||
	GetUserInfo(ctx context.Context, userID string) (userInfo *relationtb.UserModel, err error)
 | 
					 | 
				
			||||||
	GetUsersInfo(ctx context.Context, userIDs []string) ([]*relationtb.UserModel, error)
 | 
					 | 
				
			||||||
	DelUsersInfo(userIDs ...string) UserCache
 | 
					 | 
				
			||||||
	GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error)
 | 
					 | 
				
			||||||
	DelUsersGlobalRecvMsgOpt(userIDs ...string) UserCache
 | 
					 | 
				
			||||||
	GetUserStatus(ctx context.Context, userIDs []string) ([]*user.OnlineStatus, error)
 | 
					 | 
				
			||||||
	SetUserStatus(ctx context.Context, userID string, status, platformID int32) error
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type UserCacheRedis struct {
 | 
					type UserCacheRedis struct {
 | 
				
			||||||
	metaCache
 | 
						cache.BatchDeleter
 | 
				
			||||||
	rdb redis.UniversalClient
 | 
						rdb        redis.UniversalClient
 | 
				
			||||||
	// userDB     relationtb.UserModelInterface
 | 
						userDB     database.User
 | 
				
			||||||
	userDB     relationtb.UserModelInterface
 | 
					 | 
				
			||||||
	expireTime time.Duration
 | 
						expireTime time.Duration
 | 
				
			||||||
	rcClient   *rockscache.Client
 | 
						rcClient   *rockscache.Client
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewUserCacheRedis(rdb redis.UniversalClient, localCache *config.LocalCache, userDB relationtb.UserModelInterface, options rockscache.Options) UserCache {
 | 
					func NewUserCacheRedis(rdb redis.UniversalClient, localCache *config.LocalCache, userDB database.User, options *rockscache.Options) cache.UserCache {
 | 
				
			||||||
	rcClient := rockscache.NewClient(rdb, options)
 | 
						batchHandler := NewBatchDeleterRedis(rdb, options, []string{localCache.User.Topic})
 | 
				
			||||||
	mc := NewMetaCacheRedis(rcClient)
 | 
					 | 
				
			||||||
	u := localCache.User
 | 
						u := localCache.User
 | 
				
			||||||
	log.ZDebug(context.Background(), "user local cache init", "Topic", u.Topic, "SlotNum", u.SlotNum, "SlotSize", u.SlotSize, "enable", u.Enable())
 | 
						log.ZDebug(context.Background(), "user local cache init", "Topic", u.Topic, "SlotNum", u.SlotNum, "SlotSize", u.SlotSize, "enable", u.Enable())
 | 
				
			||||||
	mc.SetTopic(u.Topic)
 | 
					 | 
				
			||||||
	mc.SetRawRedisClient(rdb)
 | 
					 | 
				
			||||||
	return &UserCacheRedis{
 | 
						return &UserCacheRedis{
 | 
				
			||||||
		rdb:        rdb,
 | 
							BatchDeleter: batchHandler,
 | 
				
			||||||
		metaCache:  NewMetaCacheRedis(rcClient),
 | 
							rdb:          rdb,
 | 
				
			||||||
		userDB:     userDB,
 | 
							userDB:       userDB,
 | 
				
			||||||
		expireTime: userExpireTime,
 | 
							expireTime:   userExpireTime,
 | 
				
			||||||
		rcClient:   rcClient,
 | 
							rcClient:     rockscache.NewClient(rdb, *options),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (u *UserCacheRedis) NewCache() UserCache {
 | 
					func (u *UserCacheRedis) getOnlineStatusKey(modKey string) string {
 | 
				
			||||||
 | 
						return cachekey.GetOnlineStatusKey(modKey)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (u *UserCacheRedis) CloneUserCache() cache.UserCache {
 | 
				
			||||||
	return &UserCacheRedis{
 | 
						return &UserCacheRedis{
 | 
				
			||||||
		rdb:        u.rdb,
 | 
							BatchDeleter: u.BatchDeleter.Clone(),
 | 
				
			||||||
		metaCache:  u.Copy(),
 | 
							rdb:          u.rdb,
 | 
				
			||||||
		userDB:     u.userDB,
 | 
							userDB:       u.userDB,
 | 
				
			||||||
		expireTime: u.expireTime,
 | 
							expireTime:   u.expireTime,
 | 
				
			||||||
		rcClient:   u.rcClient,
 | 
							rcClient:     u.rcClient,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -95,26 +83,26 @@ func (u *UserCacheRedis) getUserGlobalRecvMsgOptKey(userID string) string {
 | 
				
			|||||||
	return cachekey.GetUserGlobalRecvMsgOptKey(userID)
 | 
						return cachekey.GetUserGlobalRecvMsgOptKey(userID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (u *UserCacheRedis) GetUserInfo(ctx context.Context, userID string) (userInfo *relationtb.UserModel, err error) {
 | 
					func (u *UserCacheRedis) GetUserInfo(ctx context.Context, userID string) (userInfo *model.User, err error) {
 | 
				
			||||||
	return getCache(ctx, u.rcClient, u.getUserInfoKey(userID), u.expireTime, func(ctx context.Context) (*relationtb.UserModel, error) {
 | 
						return getCache(ctx, u.rcClient, u.getUserInfoKey(userID), u.expireTime, func(ctx context.Context) (*model.User, error) {
 | 
				
			||||||
		return u.userDB.Take(ctx, userID)
 | 
							return u.userDB.Take(ctx, userID)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (u *UserCacheRedis) GetUsersInfo(ctx context.Context, userIDs []string) ([]*relationtb.UserModel, error) {
 | 
					func (u *UserCacheRedis) GetUsersInfo(ctx context.Context, userIDs []string) ([]*model.User, error) {
 | 
				
			||||||
	return batchGetCache2(ctx, u.rcClient, u.expireTime, userIDs, func(userID string) string {
 | 
						return batchGetCache(ctx, u.rcClient, u.expireTime, userIDs, func(userID string) string {
 | 
				
			||||||
		return u.getUserInfoKey(userID)
 | 
							return u.getUserInfoKey(userID)
 | 
				
			||||||
	}, func(ctx context.Context, userID string) (*relationtb.UserModel, error) {
 | 
						}, func(ctx context.Context, userID string) (*model.User, error) {
 | 
				
			||||||
		return u.userDB.Take(ctx, userID)
 | 
							return u.userDB.Take(ctx, userID)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (u *UserCacheRedis) DelUsersInfo(userIDs ...string) UserCache {
 | 
					func (u *UserCacheRedis) DelUsersInfo(userIDs ...string) cache.UserCache {
 | 
				
			||||||
	keys := make([]string, 0, len(userIDs))
 | 
						keys := make([]string, 0, len(userIDs))
 | 
				
			||||||
	for _, userID := range userIDs {
 | 
						for _, userID := range userIDs {
 | 
				
			||||||
		keys = append(keys, u.getUserInfoKey(userID))
 | 
							keys = append(keys, u.getUserInfoKey(userID))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	cache := u.NewCache()
 | 
						cache := u.CloneUserCache()
 | 
				
			||||||
	cache.AddKeys(keys...)
 | 
						cache.AddKeys(keys...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return cache
 | 
						return cache
 | 
				
			||||||
@ -132,12 +120,12 @@ func (u *UserCacheRedis) GetUserGlobalRecvMsgOpt(ctx context.Context, userID str
 | 
				
			|||||||
	)
 | 
						)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (u *UserCacheRedis) DelUsersGlobalRecvMsgOpt(userIDs ...string) UserCache {
 | 
					func (u *UserCacheRedis) DelUsersGlobalRecvMsgOpt(userIDs ...string) cache.UserCache {
 | 
				
			||||||
	keys := make([]string, 0, len(userIDs))
 | 
						keys := make([]string, 0, len(userIDs))
 | 
				
			||||||
	for _, userID := range userIDs {
 | 
						for _, userID := range userIDs {
 | 
				
			||||||
		keys = append(keys, u.getUserGlobalRecvMsgOptKey(userID))
 | 
							keys = append(keys, u.getUserGlobalRecvMsgOptKey(userID))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	cache := u.NewCache()
 | 
						cache := u.CloneUserCache()
 | 
				
			||||||
	cache.AddKeys(keys...)
 | 
						cache.AddKeys(keys...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return cache
 | 
						return cache
 | 
				
			||||||
@ -150,7 +138,7 @@ func (u *UserCacheRedis) GetUserStatus(ctx context.Context, userIDs []string) ([
 | 
				
			|||||||
		UserIDNum := crc32.ChecksumIEEE([]byte(userID))
 | 
							UserIDNum := crc32.ChecksumIEEE([]byte(userID))
 | 
				
			||||||
		modKey := strconv.Itoa(int(UserIDNum % statusMod))
 | 
							modKey := strconv.Itoa(int(UserIDNum % statusMod))
 | 
				
			||||||
		var onlineStatus user.OnlineStatus
 | 
							var onlineStatus user.OnlineStatus
 | 
				
			||||||
		key := olineStatusKey + modKey
 | 
							key := u.getOnlineStatusKey(modKey)
 | 
				
			||||||
		result, err := u.rdb.HGet(ctx, key, userID).Result()
 | 
							result, err := u.rdb.HGet(ctx, key, userID).Result()
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			if errors.Is(err, redis.Nil) {
 | 
								if errors.Is(err, redis.Nil) {
 | 
				
			||||||
@ -182,7 +170,7 @@ func (u *UserCacheRedis) GetUserStatus(ctx context.Context, userIDs []string) ([
 | 
				
			|||||||
func (u *UserCacheRedis) SetUserStatus(ctx context.Context, userID string, status, platformID int32) error {
 | 
					func (u *UserCacheRedis) SetUserStatus(ctx context.Context, userID string, status, platformID int32) error {
 | 
				
			||||||
	UserIDNum := crc32.ChecksumIEEE([]byte(userID))
 | 
						UserIDNum := crc32.ChecksumIEEE([]byte(userID))
 | 
				
			||||||
	modKey := strconv.Itoa(int(UserIDNum % statusMod))
 | 
						modKey := strconv.Itoa(int(UserIDNum % statusMod))
 | 
				
			||||||
	key := olineStatusKey + modKey
 | 
						key := u.getOnlineStatusKey(modKey)
 | 
				
			||||||
	log.ZDebug(ctx, "SetUserStatus args", "userID", userID, "status", status, "platformID", platformID, "modKey", modKey, "key", key)
 | 
						log.ZDebug(ctx, "SetUserStatus args", "userID", userID, "status", status, "platformID", platformID, "modKey", modKey, "key", key)
 | 
				
			||||||
	isNewKey, err := u.rdb.Exists(ctx, key).Result()
 | 
						isNewKey, err := u.rdb.Exists(ctx, key).Result()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
							
								
								
									
										51
									
								
								pkg/common/storage/cache/s3.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								pkg/common/storage/cache/s3.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					// Copyright © 2023 OpenIM. All rights reserved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package cache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
 | 
						"github.com/openimsdk/tools/s3"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ObjectCache interface {
 | 
				
			||||||
 | 
						BatchDeleter
 | 
				
			||||||
 | 
						CloneObjectCache() ObjectCache
 | 
				
			||||||
 | 
						GetName(ctx context.Context, engine string, name string) (*relationtb.Object, error)
 | 
				
			||||||
 | 
						DelObjectName(engine string, names ...string) ObjectCache
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type S3Cache interface {
 | 
				
			||||||
 | 
						BatchDeleter
 | 
				
			||||||
 | 
						GetKey(ctx context.Context, engine string, key string) (*s3.ObjectInfo, error)
 | 
				
			||||||
 | 
						DelS3Key(engine string, keys ...string) S3Cache
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO integrating minio.Cache and MinioCache interfaces.
 | 
				
			||||||
 | 
					type MinioCache interface {
 | 
				
			||||||
 | 
						BatchDeleter
 | 
				
			||||||
 | 
						GetImageObjectKeyInfo(ctx context.Context, key string, fn func(ctx context.Context) (*MinioImageInfo, error)) (*MinioImageInfo, error)
 | 
				
			||||||
 | 
						GetThumbnailKey(ctx context.Context, key string, format string, width int, height int, minioCache func(ctx context.Context) (string, error)) (string, error)
 | 
				
			||||||
 | 
						DelObjectImageInfoKey(keys ...string) MinioCache
 | 
				
			||||||
 | 
						DelImageThumbnailKey(key string, format string, width int, height int) MinioCache
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type MinioImageInfo struct {
 | 
				
			||||||
 | 
						IsImg  bool   `json:"isImg"`
 | 
				
			||||||
 | 
						Width  int    `json:"width"`
 | 
				
			||||||
 | 
						Height int    `json:"height"`
 | 
				
			||||||
 | 
						Format string `json:"format"`
 | 
				
			||||||
 | 
						Etag   string `json:"etag"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										30
									
								
								pkg/common/storage/cache/seq.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								pkg/common/storage/cache/seq.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					package cache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SeqCache interface {
 | 
				
			||||||
 | 
						SetMaxSeq(ctx context.Context, conversationID string, maxSeq int64) error
 | 
				
			||||||
 | 
						GetMaxSeqs(ctx context.Context, conversationIDs []string) (map[string]int64, error)
 | 
				
			||||||
 | 
						GetMaxSeq(ctx context.Context, conversationID string) (int64, error)
 | 
				
			||||||
 | 
						SetMinSeq(ctx context.Context, conversationID string, minSeq int64) error
 | 
				
			||||||
 | 
						SetMinSeqs(ctx context.Context, seqs map[string]int64) error
 | 
				
			||||||
 | 
						GetMinSeqs(ctx context.Context, conversationIDs []string) (map[string]int64, error)
 | 
				
			||||||
 | 
						GetMinSeq(ctx context.Context, conversationID string) (int64, error)
 | 
				
			||||||
 | 
						GetConversationUserMinSeq(ctx context.Context, conversationID string, userID string) (int64, error)
 | 
				
			||||||
 | 
						GetConversationUserMinSeqs(ctx context.Context, conversationID string, userIDs []string) (map[string]int64, error)
 | 
				
			||||||
 | 
						SetConversationUserMinSeq(ctx context.Context, conversationID string, userID string, minSeq int64) error
 | 
				
			||||||
 | 
						// seqs map: key userID value minSeq
 | 
				
			||||||
 | 
						SetConversationUserMinSeqs(ctx context.Context, conversationID string, seqs map[string]int64) (err error)
 | 
				
			||||||
 | 
						// seqs map: key conversationID value minSeq
 | 
				
			||||||
 | 
						SetUserConversationsMinSeqs(ctx context.Context, userID string, seqs map[string]int64) error
 | 
				
			||||||
 | 
						// has read seq
 | 
				
			||||||
 | 
						SetHasReadSeq(ctx context.Context, userID string, conversationID string, hasReadSeq int64) error
 | 
				
			||||||
 | 
						// k: user, v: seq
 | 
				
			||||||
 | 
						SetHasReadSeqs(ctx context.Context, conversationID string, hasReadSeqs map[string]int64) error
 | 
				
			||||||
 | 
						// k: conversation, v :seq
 | 
				
			||||||
 | 
						UserSetHasReadSeqs(ctx context.Context, userID string, hasReadSeqs map[string]int64) error
 | 
				
			||||||
 | 
						GetHasReadSeqs(ctx context.Context, userID string, conversationIDs []string) (map[string]int64, error)
 | 
				
			||||||
 | 
						GetHasReadSeq(ctx context.Context, userID string, conversationID string) (int64, error)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								pkg/common/storage/cache/third.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								pkg/common/storage/cache/third.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					package cache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ThirdCache interface {
 | 
				
			||||||
 | 
						SetFcmToken(ctx context.Context, account string, platformID int, fcmToken string, expireTime int64) (err error)
 | 
				
			||||||
 | 
						GetFcmToken(ctx context.Context, account string, platformID int) (string, error)
 | 
				
			||||||
 | 
						DelFcmToken(ctx context.Context, account string, platformID int) error
 | 
				
			||||||
 | 
						IncrUserBadgeUnreadCountSum(ctx context.Context, userID string) (int, error)
 | 
				
			||||||
 | 
						SetUserBadgeUnreadCountSum(ctx context.Context, userID string, value int) error
 | 
				
			||||||
 | 
						GetUserBadgeUnreadCountSum(ctx context.Context, userID string) (int, error)
 | 
				
			||||||
 | 
						SetGetuiToken(ctx context.Context, token string, expireTime int64) error
 | 
				
			||||||
 | 
						GetGetuiToken(ctx context.Context) (string, error)
 | 
				
			||||||
 | 
						SetGetuiTaskID(ctx context.Context, taskID string, expireTime int64) error
 | 
				
			||||||
 | 
						GetGetuiTaskID(ctx context.Context) (string, error)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										12
									
								
								pkg/common/storage/cache/token.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								pkg/common/storage/cache/token.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					package cache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type TokenModel interface {
 | 
				
			||||||
 | 
						AddTokenFlag(ctx context.Context, userID string, platformID int, token string, flag int) error
 | 
				
			||||||
 | 
						GetTokensWithoutError(ctx context.Context, userID string, platformID int) (map[string]int, error)
 | 
				
			||||||
 | 
						SetTokenMapByUidPid(ctx context.Context, userID string, platformID int, m map[string]int) error
 | 
				
			||||||
 | 
						DeleteTokenByUidPid(ctx context.Context, userID string, platformID int, fields []string) error
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										33
									
								
								pkg/common/storage/cache/user.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								pkg/common/storage/cache/user.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					// Copyright © 2023 OpenIM. All rights reserved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package cache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
 | 
						"github.com/openimsdk/protocol/user"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type UserCache interface {
 | 
				
			||||||
 | 
						BatchDeleter
 | 
				
			||||||
 | 
						CloneUserCache() UserCache
 | 
				
			||||||
 | 
						GetUserInfo(ctx context.Context, userID string) (userInfo *relationtb.User, err error)
 | 
				
			||||||
 | 
						GetUsersInfo(ctx context.Context, userIDs []string) ([]*relationtb.User, error)
 | 
				
			||||||
 | 
						DelUsersInfo(userIDs ...string) UserCache
 | 
				
			||||||
 | 
						GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error)
 | 
				
			||||||
 | 
						DelUsersGlobalRecvMsgOpt(userIDs ...string) UserCache
 | 
				
			||||||
 | 
						GetUserStatus(ctx context.Context, userIDs []string) ([]*user.OnlineStatus, error)
 | 
				
			||||||
 | 
						SetUserStatus(ctx context.Context, userID string, status, platformID int32) error
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										26
									
								
								pkg/common/storage/common/types.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								pkg/common/storage/common/types.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					// Copyright © 2023 OpenIM. All rights reserved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package common
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type BatchUpdateGroupMember struct {
 | 
				
			||||||
 | 
						GroupID string
 | 
				
			||||||
 | 
						UserID  string
 | 
				
			||||||
 | 
						Map     map[string]any
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type GroupSimpleUserID struct {
 | 
				
			||||||
 | 
						Hash      uint64
 | 
				
			||||||
 | 
						MemberNum uint32
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -19,7 +19,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"github.com/golang-jwt/jwt/v4"
 | 
						"github.com/golang-jwt/jwt/v4"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/authverify"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/authverify"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
 | 
				
			||||||
	"github.com/openimsdk/protocol/constant"
 | 
						"github.com/openimsdk/protocol/constant"
 | 
				
			||||||
	"github.com/openimsdk/tools/errs"
 | 
						"github.com/openimsdk/tools/errs"
 | 
				
			||||||
	"github.com/openimsdk/tools/tokenverify"
 | 
						"github.com/openimsdk/tools/tokenverify"
 | 
				
			||||||
@ -16,9 +16,9 @@ package controller
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"github.com/openimsdk/tools/db/pagination"
 | 
						"github.com/openimsdk/tools/db/pagination"
 | 
				
			||||||
	"github.com/openimsdk/tools/log"
 | 
						"github.com/openimsdk/tools/log"
 | 
				
			||||||
	"github.com/openimsdk/tools/utils/datautil"
 | 
						"github.com/openimsdk/tools/utils/datautil"
 | 
				
			||||||
@ -26,27 +26,27 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
type BlackDatabase interface {
 | 
					type BlackDatabase interface {
 | 
				
			||||||
	// Create add BlackList
 | 
						// Create add BlackList
 | 
				
			||||||
	Create(ctx context.Context, blacks []*relation.BlackModel) (err error)
 | 
						Create(ctx context.Context, blacks []*model.Black) (err error)
 | 
				
			||||||
	// Delete delete BlackList
 | 
						// Delete delete BlackList
 | 
				
			||||||
	Delete(ctx context.Context, blacks []*relation.BlackModel) (err error)
 | 
						Delete(ctx context.Context, blacks []*model.Black) (err error)
 | 
				
			||||||
	// FindOwnerBlacks get BlackList list
 | 
						// FindOwnerBlacks get BlackList list
 | 
				
			||||||
	FindOwnerBlacks(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, blacks []*relation.BlackModel, err error)
 | 
						FindOwnerBlacks(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, blacks []*model.Black, err error)
 | 
				
			||||||
	FindBlackInfos(ctx context.Context, ownerUserID string, userIDs []string) (blacks []*relation.BlackModel, err error)
 | 
						FindBlackInfos(ctx context.Context, ownerUserID string, userIDs []string) (blacks []*model.Black, err error)
 | 
				
			||||||
	// CheckIn Check whether user2 is in the black list of user1 (inUser1Blacks==true) Check whether user1 is in the black list of user2 (inUser2Blacks==true)
 | 
						// CheckIn Check whether user2 is in the black list of user1 (inUser1Blacks==true) Check whether user1 is in the black list of user2 (inUser2Blacks==true)
 | 
				
			||||||
	CheckIn(ctx context.Context, userID1, userID2 string) (inUser1Blacks bool, inUser2Blacks bool, err error)
 | 
						CheckIn(ctx context.Context, userID1, userID2 string) (inUser1Blacks bool, inUser2Blacks bool, err error)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type blackDatabase struct {
 | 
					type blackDatabase struct {
 | 
				
			||||||
	black relation.BlackModelInterface
 | 
						black database.Black
 | 
				
			||||||
	cache cache.BlackCache
 | 
						cache cache.BlackCache
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewBlackDatabase(black relation.BlackModelInterface, cache cache.BlackCache) BlackDatabase {
 | 
					func NewBlackDatabase(black database.Black, cache cache.BlackCache) BlackDatabase {
 | 
				
			||||||
	return &blackDatabase{black, cache}
 | 
						return &blackDatabase{black, cache}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Create Add Blacklist.
 | 
					// Create Add Blacklist.
 | 
				
			||||||
func (b *blackDatabase) Create(ctx context.Context, blacks []*relation.BlackModel) (err error) {
 | 
					func (b *blackDatabase) Create(ctx context.Context, blacks []*model.Black) (err error) {
 | 
				
			||||||
	if err := b.black.Create(ctx, blacks); err != nil {
 | 
						if err := b.black.Create(ctx, blacks); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -54,7 +54,7 @@ func (b *blackDatabase) Create(ctx context.Context, blacks []*relation.BlackMode
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Delete Delete Blacklist.
 | 
					// Delete Delete Blacklist.
 | 
				
			||||||
func (b *blackDatabase) Delete(ctx context.Context, blacks []*relation.BlackModel) (err error) {
 | 
					func (b *blackDatabase) Delete(ctx context.Context, blacks []*model.Black) (err error) {
 | 
				
			||||||
	if err := b.black.Delete(ctx, blacks); err != nil {
 | 
						if err := b.black.Delete(ctx, blacks); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -62,16 +62,16 @@ func (b *blackDatabase) Delete(ctx context.Context, blacks []*relation.BlackMode
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// FindOwnerBlacks Get Blacklist List.
 | 
					// FindOwnerBlacks Get Blacklist List.
 | 
				
			||||||
func (b *blackDatabase) deleteBlackIDsCache(ctx context.Context, blacks []*relation.BlackModel) (err error) {
 | 
					func (b *blackDatabase) deleteBlackIDsCache(ctx context.Context, blacks []*model.Black) (err error) {
 | 
				
			||||||
	cache := b.cache.NewCache()
 | 
						cache := b.cache.CloneBlackCache()
 | 
				
			||||||
	for _, black := range blacks {
 | 
						for _, black := range blacks {
 | 
				
			||||||
		cache = cache.DelBlackIDs(ctx, black.OwnerUserID)
 | 
							cache = cache.DelBlackIDs(ctx, black.OwnerUserID)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return cache.ExecDel(ctx)
 | 
						return cache.ChainExecDel(ctx)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// FindOwnerBlacks Get Blacklist List.
 | 
					// FindOwnerBlacks Get Blacklist List.
 | 
				
			||||||
func (b *blackDatabase) FindOwnerBlacks(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, blacks []*relation.BlackModel, err error) {
 | 
					func (b *blackDatabase) FindOwnerBlacks(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, blacks []*model.Black, err error) {
 | 
				
			||||||
	return b.black.FindOwnerBlacks(ctx, ownerUserID, pagination)
 | 
						return b.black.FindOwnerBlacks(ctx, ownerUserID, pagination)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -95,6 +95,6 @@ func (b *blackDatabase) FindBlackIDs(ctx context.Context, ownerUserID string) (b
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// FindBlackInfos Get Blacklist List.
 | 
					// FindBlackInfos Get Blacklist List.
 | 
				
			||||||
func (b *blackDatabase) FindBlackInfos(ctx context.Context, ownerUserID string, userIDs []string) (blacks []*relation.BlackModel, err error) {
 | 
					func (b *blackDatabase) FindBlackInfos(ctx context.Context, ownerUserID string, userIDs []string) (blacks []*model.Black, err error) {
 | 
				
			||||||
	return b.black.FindOwnerBlackInfos(ctx, ownerUserID, userIDs)
 | 
						return b.black.FindOwnerBlackInfos(ctx, ownerUserID, userIDs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -16,10 +16,11 @@ package controller
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
 | 
				
			||||||
 | 
						relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
 | 
				
			||||||
	relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
 | 
				
			||||||
	"github.com/openimsdk/protocol/constant"
 | 
						"github.com/openimsdk/protocol/constant"
 | 
				
			||||||
	"github.com/openimsdk/tools/db/pagination"
 | 
						"github.com/openimsdk/tools/db/pagination"
 | 
				
			||||||
@ -33,18 +34,18 @@ type ConversationDatabase interface {
 | 
				
			|||||||
	// UpdateUsersConversationField updates the properties of a conversation for specified users.
 | 
						// UpdateUsersConversationField updates the properties of a conversation for specified users.
 | 
				
			||||||
	UpdateUsersConversationField(ctx context.Context, userIDs []string, conversationID string, args map[string]any) error
 | 
						UpdateUsersConversationField(ctx context.Context, userIDs []string, conversationID string, args map[string]any) error
 | 
				
			||||||
	// CreateConversation creates a batch of new conversations.
 | 
						// CreateConversation creates a batch of new conversations.
 | 
				
			||||||
	CreateConversation(ctx context.Context, conversations []*relationtb.ConversationModel) error
 | 
						CreateConversation(ctx context.Context, conversations []*relationtb.Conversation) error
 | 
				
			||||||
	// SyncPeerUserPrivateConversationTx ensures transactional operation while syncing private conversations between peers.
 | 
						// SyncPeerUserPrivateConversationTx ensures transactional operation while syncing private conversations between peers.
 | 
				
			||||||
	SyncPeerUserPrivateConversationTx(ctx context.Context, conversation []*relationtb.ConversationModel) error
 | 
						SyncPeerUserPrivateConversationTx(ctx context.Context, conversation []*relationtb.Conversation) error
 | 
				
			||||||
	// FindConversations retrieves multiple conversations of a user by conversation IDs.
 | 
						// FindConversations retrieves multiple conversations of a user by conversation IDs.
 | 
				
			||||||
	FindConversations(ctx context.Context, ownerUserID string, conversationIDs []string) ([]*relationtb.ConversationModel, error)
 | 
						FindConversations(ctx context.Context, ownerUserID string, conversationIDs []string) ([]*relationtb.Conversation, error)
 | 
				
			||||||
	// GetUserAllConversation fetches all conversations of a user on the server.
 | 
						// GetUserAllConversation fetches all conversations of a user on the server.
 | 
				
			||||||
	GetUserAllConversation(ctx context.Context, ownerUserID string) ([]*relationtb.ConversationModel, error)
 | 
						GetUserAllConversation(ctx context.Context, ownerUserID string) ([]*relationtb.Conversation, error)
 | 
				
			||||||
	// SetUserConversations sets multiple conversation properties for a user, creates new conversations if they do not exist, or updates them otherwise. This operation is atomic.
 | 
						// SetUserConversations sets multiple conversation properties for a user, creates new conversations if they do not exist, or updates them otherwise. This operation is atomic.
 | 
				
			||||||
	SetUserConversations(ctx context.Context, ownerUserID string, conversations []*relationtb.ConversationModel) error
 | 
						SetUserConversations(ctx context.Context, ownerUserID string, conversations []*relationtb.Conversation) error
 | 
				
			||||||
	// SetUsersConversationFieldTx updates a specific field for multiple users' conversations, creating new conversations if they do not exist, or updates them otherwise. This operation is
 | 
						// SetUsersConversationFieldTx updates a specific field for multiple users' conversations, creating new conversations if they do not exist, or updates them otherwise. This operation is
 | 
				
			||||||
	// transactional.
 | 
						// transactional.
 | 
				
			||||||
	SetUsersConversationFieldTx(ctx context.Context, userIDs []string, conversation *relationtb.ConversationModel, fieldMap map[string]any) error
 | 
						SetUsersConversationFieldTx(ctx context.Context, userIDs []string, conversation *relationtb.Conversation, fieldMap map[string]any) error
 | 
				
			||||||
	// CreateGroupChatConversation creates a group chat conversation for the specified group ID and user IDs.
 | 
						// CreateGroupChatConversation creates a group chat conversation for the specified group ID and user IDs.
 | 
				
			||||||
	CreateGroupChatConversation(ctx context.Context, groupID string, userIDs []string) error
 | 
						CreateGroupChatConversation(ctx context.Context, groupID string, userIDs []string) error
 | 
				
			||||||
	// GetConversationIDs retrieves conversation IDs for a given user.
 | 
						// GetConversationIDs retrieves conversation IDs for a given user.
 | 
				
			||||||
@ -58,16 +59,16 @@ type ConversationDatabase interface {
 | 
				
			|||||||
	// PageConversationIDs paginates through conversation IDs based on the specified pagination settings.
 | 
						// PageConversationIDs paginates through conversation IDs based on the specified pagination settings.
 | 
				
			||||||
	PageConversationIDs(ctx context.Context, pagination pagination.Pagination) (conversationIDs []string, err error)
 | 
						PageConversationIDs(ctx context.Context, pagination pagination.Pagination) (conversationIDs []string, err error)
 | 
				
			||||||
	// GetConversationsByConversationID retrieves conversations by their IDs.
 | 
						// GetConversationsByConversationID retrieves conversations by their IDs.
 | 
				
			||||||
	GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*relationtb.ConversationModel, error)
 | 
						GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*relationtb.Conversation, error)
 | 
				
			||||||
	// GetConversationIDsNeedDestruct fetches conversations that need to be destructed based on specific criteria.
 | 
						// GetConversationIDsNeedDestruct fetches conversations that need to be destructed based on specific criteria.
 | 
				
			||||||
	GetConversationIDsNeedDestruct(ctx context.Context) ([]*relationtb.ConversationModel, error)
 | 
						GetConversationIDsNeedDestruct(ctx context.Context) ([]*relationtb.Conversation, error)
 | 
				
			||||||
	// GetConversationNotReceiveMessageUserIDs gets user IDs for users in a conversation who have not received messages.
 | 
						// GetConversationNotReceiveMessageUserIDs gets user IDs for users in a conversation who have not received messages.
 | 
				
			||||||
	GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error)
 | 
						GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error)
 | 
				
			||||||
	// GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (map[string]int64, error)
 | 
						// GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (map[string]int64, error)
 | 
				
			||||||
	// FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error)
 | 
						// FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewConversationDatabase(conversation relationtb.ConversationModelInterface, cache cache.ConversationCache, tx tx.Tx) ConversationDatabase {
 | 
					func NewConversationDatabase(conversation database.Conversation, cache cache.ConversationCache, tx tx.Tx) ConversationDatabase {
 | 
				
			||||||
	return &conversationDatabase{
 | 
						return &conversationDatabase{
 | 
				
			||||||
		conversationDB: conversation,
 | 
							conversationDB: conversation,
 | 
				
			||||||
		cache:          cache,
 | 
							cache:          cache,
 | 
				
			||||||
@ -76,14 +77,14 @@ func NewConversationDatabase(conversation relationtb.ConversationModelInterface,
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type conversationDatabase struct {
 | 
					type conversationDatabase struct {
 | 
				
			||||||
	conversationDB relationtb.ConversationModelInterface
 | 
						conversationDB database.Conversation
 | 
				
			||||||
	cache          cache.ConversationCache
 | 
						cache          cache.ConversationCache
 | 
				
			||||||
	tx             tx.Tx
 | 
						tx             tx.Tx
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *conversationDatabase) SetUsersConversationFieldTx(ctx context.Context, userIDs []string, conversation *relationtb.ConversationModel, fieldMap map[string]any) (err error) {
 | 
					func (c *conversationDatabase) SetUsersConversationFieldTx(ctx context.Context, userIDs []string, conversation *relationtb.Conversation, fieldMap map[string]any) (err error) {
 | 
				
			||||||
	return c.tx.Transaction(ctx, func(ctx context.Context) error {
 | 
						return c.tx.Transaction(ctx, func(ctx context.Context) error {
 | 
				
			||||||
		cache := c.cache.NewCache()
 | 
							cache := c.cache.CloneConversationCache()
 | 
				
			||||||
		if conversation.GroupID != "" {
 | 
							if conversation.GroupID != "" {
 | 
				
			||||||
			cache = cache.DelSuperGroupRecvMsgNotNotifyUserIDs(conversation.GroupID).DelSuperGroupRecvMsgNotNotifyUserIDsHash(conversation.GroupID)
 | 
								cache = cache.DelSuperGroupRecvMsgNotNotifyUserIDs(conversation.GroupID).DelSuperGroupRecvMsgNotNotifyUserIDsHash(conversation.GroupID)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -108,10 +109,10 @@ func (c *conversationDatabase) SetUsersConversationFieldTx(ctx context.Context,
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		NotUserIDs := stringutil.DifferenceString(haveUserIDs, userIDs)
 | 
							NotUserIDs := stringutil.DifferenceString(haveUserIDs, userIDs)
 | 
				
			||||||
		log.ZDebug(ctx, "SetUsersConversationFieldTx", "NotUserIDs", NotUserIDs, "haveUserIDs", haveUserIDs, "userIDs", userIDs)
 | 
							log.ZDebug(ctx, "SetUsersConversationFieldTx", "NotUserIDs", NotUserIDs, "haveUserIDs", haveUserIDs, "userIDs", userIDs)
 | 
				
			||||||
		var conversations []*relationtb.ConversationModel
 | 
							var conversations []*relationtb.Conversation
 | 
				
			||||||
		now := time.Now()
 | 
							now := time.Now()
 | 
				
			||||||
		for _, v := range NotUserIDs {
 | 
							for _, v := range NotUserIDs {
 | 
				
			||||||
			temp := new(relationtb.ConversationModel)
 | 
								temp := new(relationtb.Conversation)
 | 
				
			||||||
			if err = datautil.CopyStructFields(temp, conversation); err != nil {
 | 
								if err = datautil.CopyStructFields(temp, conversation); err != nil {
 | 
				
			||||||
				return err
 | 
									return err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@ -126,7 +127,7 @@ func (c *conversationDatabase) SetUsersConversationFieldTx(ctx context.Context,
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			cache = cache.DelConversationIDs(NotUserIDs...).DelUserConversationIDsHash(NotUserIDs...).DelConversations(conversation.ConversationID, NotUserIDs...)
 | 
								cache = cache.DelConversationIDs(NotUserIDs...).DelUserConversationIDsHash(NotUserIDs...).DelConversations(conversation.ConversationID, NotUserIDs...)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return cache.ExecDel(ctx)
 | 
							return cache.ChainExecDel(ctx)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -135,31 +136,31 @@ func (c *conversationDatabase) UpdateUsersConversationField(ctx context.Context,
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	cache := c.cache.NewCache()
 | 
						cache := c.cache.CloneConversationCache()
 | 
				
			||||||
	cache = cache.DelUsersConversation(conversationID, userIDs...)
 | 
						cache = cache.DelUsersConversation(conversationID, userIDs...)
 | 
				
			||||||
	if _, ok := args["recv_msg_opt"]; ok {
 | 
						if _, ok := args["recv_msg_opt"]; ok {
 | 
				
			||||||
		cache = cache.DelConversationNotReceiveMessageUserIDs(conversationID)
 | 
							cache = cache.DelConversationNotReceiveMessageUserIDs(conversationID)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return cache.ExecDel(ctx)
 | 
						return cache.ChainExecDel(ctx)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *conversationDatabase) CreateConversation(ctx context.Context, conversations []*relationtb.ConversationModel) error {
 | 
					func (c *conversationDatabase) CreateConversation(ctx context.Context, conversations []*relationtb.Conversation) error {
 | 
				
			||||||
	if err := c.conversationDB.Create(ctx, conversations); err != nil {
 | 
						if err := c.conversationDB.Create(ctx, conversations); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	var userIDs []string
 | 
						var userIDs []string
 | 
				
			||||||
	cache := c.cache.NewCache()
 | 
						cache := c.cache.CloneConversationCache()
 | 
				
			||||||
	for _, conversation := range conversations {
 | 
						for _, conversation := range conversations {
 | 
				
			||||||
		cache = cache.DelConversations(conversation.OwnerUserID, conversation.ConversationID)
 | 
							cache = cache.DelConversations(conversation.OwnerUserID, conversation.ConversationID)
 | 
				
			||||||
		cache = cache.DelConversationNotReceiveMessageUserIDs(conversation.ConversationID)
 | 
							cache = cache.DelConversationNotReceiveMessageUserIDs(conversation.ConversationID)
 | 
				
			||||||
		userIDs = append(userIDs, conversation.OwnerUserID)
 | 
							userIDs = append(userIDs, conversation.OwnerUserID)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return cache.DelConversationIDs(userIDs...).DelUserConversationIDsHash(userIDs...).ExecDel(ctx)
 | 
						return cache.DelConversationIDs(userIDs...).DelUserConversationIDsHash(userIDs...).ChainExecDel(ctx)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *conversationDatabase) SyncPeerUserPrivateConversationTx(ctx context.Context, conversations []*relationtb.ConversationModel) error {
 | 
					func (c *conversationDatabase) SyncPeerUserPrivateConversationTx(ctx context.Context, conversations []*relationtb.Conversation) error {
 | 
				
			||||||
	return c.tx.Transaction(ctx, func(ctx context.Context) error {
 | 
						return c.tx.Transaction(ctx, func(ctx context.Context) error {
 | 
				
			||||||
		cache := c.cache.NewCache()
 | 
							cache := c.cache.CloneConversationCache()
 | 
				
			||||||
		for _, conversation := range conversations {
 | 
							for _, conversation := range conversations {
 | 
				
			||||||
			for _, v := range [][2]string{{conversation.OwnerUserID, conversation.UserID}, {conversation.UserID, conversation.OwnerUserID}} {
 | 
								for _, v := range [][2]string{{conversation.OwnerUserID, conversation.UserID}, {conversation.UserID, conversation.OwnerUserID}} {
 | 
				
			||||||
				ownerUserID := v[0]
 | 
									ownerUserID := v[0]
 | 
				
			||||||
@ -180,33 +181,33 @@ func (c *conversationDatabase) SyncPeerUserPrivateConversationTx(ctx context.Con
 | 
				
			|||||||
					newConversation.UserID = userID
 | 
										newConversation.UserID = userID
 | 
				
			||||||
					newConversation.ConversationID = conversation.ConversationID
 | 
										newConversation.ConversationID = conversation.ConversationID
 | 
				
			||||||
					newConversation.IsPrivateChat = conversation.IsPrivateChat
 | 
										newConversation.IsPrivateChat = conversation.IsPrivateChat
 | 
				
			||||||
					if err := c.conversationDB.Create(ctx, []*relationtb.ConversationModel{&newConversation}); err != nil {
 | 
										if err := c.conversationDB.Create(ctx, []*relationtb.Conversation{&newConversation}); err != nil {
 | 
				
			||||||
						return err
 | 
											return err
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					cache = cache.DelConversationIDs(ownerUserID).DelUserConversationIDsHash(ownerUserID)
 | 
										cache = cache.DelConversationIDs(ownerUserID).DelUserConversationIDsHash(ownerUserID)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return cache.ExecDel(ctx)
 | 
							return cache.ChainExecDel(ctx)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *conversationDatabase) FindConversations(ctx context.Context, ownerUserID string, conversationIDs []string) ([]*relationtb.ConversationModel, error) {
 | 
					func (c *conversationDatabase) FindConversations(ctx context.Context, ownerUserID string, conversationIDs []string) ([]*relationtb.Conversation, error) {
 | 
				
			||||||
	return c.cache.GetConversations(ctx, ownerUserID, conversationIDs)
 | 
						return c.cache.GetConversations(ctx, ownerUserID, conversationIDs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *conversationDatabase) GetConversation(ctx context.Context, ownerUserID string, conversationID string) (*relationtb.ConversationModel, error) {
 | 
					func (c *conversationDatabase) GetConversation(ctx context.Context, ownerUserID string, conversationID string) (*relationtb.Conversation, error) {
 | 
				
			||||||
	return c.cache.GetConversation(ctx, ownerUserID, conversationID)
 | 
						return c.cache.GetConversation(ctx, ownerUserID, conversationID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *conversationDatabase) GetUserAllConversation(ctx context.Context, ownerUserID string) ([]*relationtb.ConversationModel, error) {
 | 
					func (c *conversationDatabase) GetUserAllConversation(ctx context.Context, ownerUserID string) ([]*relationtb.Conversation, error) {
 | 
				
			||||||
	return c.cache.GetUserAllConversations(ctx, ownerUserID)
 | 
						return c.cache.GetUserAllConversations(ctx, ownerUserID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *conversationDatabase) SetUserConversations(ctx context.Context, ownerUserID string, conversations []*relationtb.ConversationModel) error {
 | 
					func (c *conversationDatabase) SetUserConversations(ctx context.Context, ownerUserID string, conversations []*relationtb.Conversation) error {
 | 
				
			||||||
	return c.tx.Transaction(ctx, func(ctx context.Context) error {
 | 
						return c.tx.Transaction(ctx, func(ctx context.Context) error {
 | 
				
			||||||
		cache := c.cache.NewCache()
 | 
							cache := c.cache.CloneConversationCache()
 | 
				
			||||||
		groupIDs := datautil.Distinct(datautil.Filter(conversations, func(e *relationtb.ConversationModel) (string, bool) {
 | 
							groupIDs := datautil.Distinct(datautil.Filter(conversations, func(e *relationtb.Conversation) (string, bool) {
 | 
				
			||||||
			return e.GroupID, e.GroupID != ""
 | 
								return e.GroupID, e.GroupID != ""
 | 
				
			||||||
		}))
 | 
							}))
 | 
				
			||||||
		for _, groupID := range groupIDs {
 | 
							for _, groupID := range groupIDs {
 | 
				
			||||||
@ -234,7 +235,7 @@ func (c *conversationDatabase) SetUserConversations(ctx context.Context, ownerUs
 | 
				
			|||||||
			existConversationIDs = append(existConversationIDs, conversation.ConversationID)
 | 
								existConversationIDs = append(existConversationIDs, conversation.ConversationID)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var notExistConversations []*relationtb.ConversationModel
 | 
							var notExistConversations []*relationtb.Conversation
 | 
				
			||||||
		for _, conversation := range conversations {
 | 
							for _, conversation := range conversations {
 | 
				
			||||||
			if !datautil.Contain(conversation.ConversationID, existConversationIDs...) {
 | 
								if !datautil.Contain(conversation.ConversationID, existConversationIDs...) {
 | 
				
			||||||
				notExistConversations = append(notExistConversations, conversation)
 | 
									notExistConversations = append(notExistConversations, conversation)
 | 
				
			||||||
@ -247,9 +248,9 @@ func (c *conversationDatabase) SetUserConversations(ctx context.Context, ownerUs
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			cache = cache.DelConversationIDs(ownerUserID).
 | 
								cache = cache.DelConversationIDs(ownerUserID).
 | 
				
			||||||
				DelUserConversationIDsHash(ownerUserID).
 | 
									DelUserConversationIDsHash(ownerUserID).
 | 
				
			||||||
				DelConversationNotReceiveMessageUserIDs(datautil.Slice(notExistConversations, func(e *relationtb.ConversationModel) string { return e.ConversationID })...)
 | 
									DelConversationNotReceiveMessageUserIDs(datautil.Slice(notExistConversations, func(e *relationtb.Conversation) string { return e.ConversationID })...)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return cache.ExecDel(ctx)
 | 
							return cache.ChainExecDel(ctx)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -259,16 +260,16 @@ func (c *conversationDatabase) SetUserConversations(ctx context.Context, ownerUs
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (c *conversationDatabase) CreateGroupChatConversation(ctx context.Context, groupID string, userIDs []string) error {
 | 
					func (c *conversationDatabase) CreateGroupChatConversation(ctx context.Context, groupID string, userIDs []string) error {
 | 
				
			||||||
	return c.tx.Transaction(ctx, func(ctx context.Context) error {
 | 
						return c.tx.Transaction(ctx, func(ctx context.Context) error {
 | 
				
			||||||
		cache := c.cache.NewCache()
 | 
							cache := c.cache.CloneConversationCache()
 | 
				
			||||||
		conversationID := msgprocessor.GetConversationIDBySessionType(constant.ReadGroupChatType, groupID)
 | 
							conversationID := msgprocessor.GetConversationIDBySessionType(constant.ReadGroupChatType, groupID)
 | 
				
			||||||
		existConversationUserIDs, err := c.conversationDB.FindUserID(ctx, userIDs, []string{conversationID})
 | 
							existConversationUserIDs, err := c.conversationDB.FindUserID(ctx, userIDs, []string{conversationID})
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		notExistUserIDs := stringutil.DifferenceString(userIDs, existConversationUserIDs)
 | 
							notExistUserIDs := stringutil.DifferenceString(userIDs, existConversationUserIDs)
 | 
				
			||||||
		var conversations []*relationtb.ConversationModel
 | 
							var conversations []*relationtb.Conversation
 | 
				
			||||||
		for _, v := range notExistUserIDs {
 | 
							for _, v := range notExistUserIDs {
 | 
				
			||||||
			conversation := relationtb.ConversationModel{ConversationType: constant.ReadGroupChatType, GroupID: groupID, OwnerUserID: v, ConversationID: conversationID}
 | 
								conversation := relationtb.Conversation{ConversationType: constant.ReadGroupChatType, GroupID: groupID, OwnerUserID: v, ConversationID: conversationID}
 | 
				
			||||||
			conversations = append(conversations, &conversation)
 | 
								conversations = append(conversations, &conversation)
 | 
				
			||||||
			cache = cache.DelConversations(v, conversationID).DelConversationNotReceiveMessageUserIDs(conversationID)
 | 
								cache = cache.DelConversations(v, conversationID).DelConversationNotReceiveMessageUserIDs(conversationID)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -286,7 +287,7 @@ func (c *conversationDatabase) CreateGroupChatConversation(ctx context.Context,
 | 
				
			|||||||
		for _, v := range existConversationUserIDs {
 | 
							for _, v := range existConversationUserIDs {
 | 
				
			||||||
			cache = cache.DelConversations(v, conversationID)
 | 
								cache = cache.DelConversations(v, conversationID)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return cache.ExecDel(ctx)
 | 
							return cache.ChainExecDel(ctx)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -310,11 +311,11 @@ func (c *conversationDatabase) PageConversationIDs(ctx context.Context, paginati
 | 
				
			|||||||
	return c.conversationDB.PageConversationIDs(ctx, pagination)
 | 
						return c.conversationDB.PageConversationIDs(ctx, pagination)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *conversationDatabase) GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*relationtb.ConversationModel, error) {
 | 
					func (c *conversationDatabase) GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*relationtb.Conversation, error) {
 | 
				
			||||||
	return c.conversationDB.GetConversationsByConversationID(ctx, conversationIDs)
 | 
						return c.conversationDB.GetConversationsByConversationID(ctx, conversationIDs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *conversationDatabase) GetConversationIDsNeedDestruct(ctx context.Context) ([]*relationtb.ConversationModel, error) {
 | 
					func (c *conversationDatabase) GetConversationIDsNeedDestruct(ctx context.Context) ([]*relationtb.Conversation, error) {
 | 
				
			||||||
	return c.conversationDB.GetConversationIDsNeedDestruct(ctx)
 | 
						return c.conversationDB.GetConversationIDsNeedDestruct(ctx)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -12,4 +12,4 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package controller // import "github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
 | 
					package controller // import "github.com/openimsdk/open-im-server/v3/pkg/common/storage/controller"
 | 
				
			||||||
@ -17,10 +17,12 @@ package controller
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database/mgo"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/protocol/constant"
 | 
						"github.com/openimsdk/protocol/constant"
 | 
				
			||||||
	"github.com/openimsdk/tools/db/pagination"
 | 
						"github.com/openimsdk/tools/db/pagination"
 | 
				
			||||||
	"github.com/openimsdk/tools/db/tx"
 | 
						"github.com/openimsdk/tools/db/tx"
 | 
				
			||||||
@ -37,14 +39,14 @@ type FriendDatabase interface {
 | 
				
			|||||||
	// AddFriendRequest adds or updates a friend request
 | 
						// AddFriendRequest adds or updates a friend request
 | 
				
			||||||
	AddFriendRequest(ctx context.Context, fromUserID, toUserID string, reqMsg string, ex string) (err error)
 | 
						AddFriendRequest(ctx context.Context, fromUserID, toUserID string, reqMsg string, ex string) (err error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// BecomeFriends first checks if the users are already in the friends table; if not, it inserts them as friends
 | 
						// BecomeFriends first checks if the users are already in the friends model; if not, it inserts them as friends
 | 
				
			||||||
	BecomeFriends(ctx context.Context, ownerUserID string, friendUserIDs []string, addSource int32) (err error)
 | 
						BecomeFriends(ctx context.Context, ownerUserID string, friendUserIDs []string, addSource int32) (err error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// RefuseFriendRequest refuses a friend request
 | 
						// RefuseFriendRequest refuses a friend request
 | 
				
			||||||
	RefuseFriendRequest(ctx context.Context, friendRequest *relation.FriendRequestModel) (err error)
 | 
						RefuseFriendRequest(ctx context.Context, friendRequest *model.FriendRequest) (err error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// AgreeFriendRequest accepts a friend request
 | 
						// AgreeFriendRequest accepts a friend request
 | 
				
			||||||
	AgreeFriendRequest(ctx context.Context, friendRequest *relation.FriendRequestModel) (err error)
 | 
						AgreeFriendRequest(ctx context.Context, friendRequest *model.FriendRequest) (err error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Delete removes a friend or friends from the owner's friend list
 | 
						// Delete removes a friend or friends from the owner's friend list
 | 
				
			||||||
	Delete(ctx context.Context, ownerUserID string, friendUserIDs []string) (err error)
 | 
						Delete(ctx context.Context, ownerUserID string, friendUserIDs []string) (err error)
 | 
				
			||||||
@ -53,38 +55,38 @@ type FriendDatabase interface {
 | 
				
			|||||||
	UpdateRemark(ctx context.Context, ownerUserID, friendUserID, remark string) (err error)
 | 
						UpdateRemark(ctx context.Context, ownerUserID, friendUserID, remark string) (err error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// PageOwnerFriends retrieves the friend list of ownerUserID with pagination
 | 
						// PageOwnerFriends retrieves the friend list of ownerUserID with pagination
 | 
				
			||||||
	PageOwnerFriends(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendModel, err error)
 | 
						PageOwnerFriends(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, friends []*model.Friend, err error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// PageInWhoseFriends finds the users who have friendUserID in their friend list with pagination
 | 
						// PageInWhoseFriends finds the users who have friendUserID in their friend list with pagination
 | 
				
			||||||
	PageInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendModel, err error)
 | 
						PageInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (total int64, friends []*model.Friend, err error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// PageFriendRequestFromMe retrieves the friend requests sent by the user with pagination
 | 
						// PageFriendRequestFromMe retrieves the friend requests sent by the user with pagination
 | 
				
			||||||
	PageFriendRequestFromMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendRequestModel, err error)
 | 
						PageFriendRequestFromMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*model.FriendRequest, err error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// PageFriendRequestToMe retrieves the friend requests received by the user with pagination
 | 
						// PageFriendRequestToMe retrieves the friend requests received by the user with pagination
 | 
				
			||||||
	PageFriendRequestToMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendRequestModel, err error)
 | 
						PageFriendRequestToMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*model.FriendRequest, err error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// FindFriendsWithError fetches specified friends of a user and returns an error if any do not exist
 | 
						// FindFriendsWithError fetches specified friends of a user and returns an error if any do not exist
 | 
				
			||||||
	FindFriendsWithError(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*relation.FriendModel, err error)
 | 
						FindFriendsWithError(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*model.Friend, err error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// FindFriendUserIDs retrieves the friend IDs of a user
 | 
						// FindFriendUserIDs retrieves the friend IDs of a user
 | 
				
			||||||
	FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error)
 | 
						FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// FindBothFriendRequests finds friend requests sent and received
 | 
						// FindBothFriendRequests finds friend requests sent and received
 | 
				
			||||||
	FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*relation.FriendRequestModel, err error)
 | 
						FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*model.FriendRequest, err error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// UpdateFriends updates fields for friends
 | 
						// UpdateFriends updates fields for friends
 | 
				
			||||||
	UpdateFriends(ctx context.Context, ownerUserID string, friendUserIDs []string, val map[string]any) (err error)
 | 
						UpdateFriends(ctx context.Context, ownerUserID string, friendUserIDs []string, val map[string]any) (err error)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type friendDatabase struct {
 | 
					type friendDatabase struct {
 | 
				
			||||||
	friend        relation.FriendModelInterface
 | 
						friend        database.Friend
 | 
				
			||||||
	friendRequest relation.FriendRequestModelInterface
 | 
						friendRequest database.FriendRequest
 | 
				
			||||||
	tx            tx.Tx
 | 
						tx            tx.Tx
 | 
				
			||||||
	cache         cache.FriendCache
 | 
						cache         cache.FriendCache
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewFriendDatabase(friend relation.FriendModelInterface, friendRequest relation.FriendRequestModelInterface, cache cache.FriendCache, tx tx.Tx) FriendDatabase {
 | 
					func NewFriendDatabase(friend database.Friend, friendRequest database.FriendRequest, cache cache.FriendCache, tx tx.Tx) FriendDatabase {
 | 
				
			||||||
	return &friendDatabase{friend: friend, friendRequest: friendRequest, cache: cache, tx: tx}
 | 
						return &friendDatabase{friend: friend, friendRequest: friendRequest, cache: cache, tx: tx}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -124,10 +126,10 @@ func (f *friendDatabase) AddFriendRequest(ctx context.Context, fromUserID, toUse
 | 
				
			|||||||
			m["ex"] = ex
 | 
								m["ex"] = ex
 | 
				
			||||||
			m["create_time"] = time.Now()
 | 
								m["create_time"] = time.Now()
 | 
				
			||||||
			return f.friendRequest.UpdateByMap(ctx, fromUserID, toUserID, m)
 | 
								return f.friendRequest.UpdateByMap(ctx, fromUserID, toUserID, m)
 | 
				
			||||||
		case relation.IsNotFound(err):
 | 
							case mgo.IsNotFound(err):
 | 
				
			||||||
			return f.friendRequest.Create(
 | 
								return f.friendRequest.Create(
 | 
				
			||||||
				ctx,
 | 
									ctx,
 | 
				
			||||||
				[]*relation.FriendRequestModel{{FromUserID: fromUserID, ToUserID: toUserID, ReqMsg: reqMsg, Ex: ex, CreateTime: time.Now(), HandleTime: time.Unix(0, 0)}},
 | 
									[]*model.FriendRequest{{FromUserID: fromUserID, ToUserID: toUserID, ReqMsg: reqMsg, Ex: ex, CreateTime: time.Now(), HandleTime: time.Unix(0, 0)}},
 | 
				
			||||||
			)
 | 
								)
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
@ -138,7 +140,7 @@ func (f *friendDatabase) AddFriendRequest(ctx context.Context, fromUserID, toUse
 | 
				
			|||||||
// (1) First determine whether it is in the friends list (in or out does not return an error) (2) for not in the friends list can be inserted.
 | 
					// (1) First determine whether it is in the friends list (in or out does not return an error) (2) for not in the friends list can be inserted.
 | 
				
			||||||
func (f *friendDatabase) BecomeFriends(ctx context.Context, ownerUserID string, friendUserIDs []string, addSource int32) (err error) {
 | 
					func (f *friendDatabase) BecomeFriends(ctx context.Context, ownerUserID string, friendUserIDs []string, addSource int32) (err error) {
 | 
				
			||||||
	return f.tx.Transaction(ctx, func(ctx context.Context) error {
 | 
						return f.tx.Transaction(ctx, func(ctx context.Context) error {
 | 
				
			||||||
		cache := f.cache.NewCache()
 | 
							cache := f.cache.CloneFriendCache()
 | 
				
			||||||
		// user find friends
 | 
							// user find friends
 | 
				
			||||||
		fs1, err := f.friend.FindFriends(ctx, ownerUserID, friendUserIDs)
 | 
							fs1, err := f.friend.FindFriends(ctx, ownerUserID, friendUserIDs)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
@ -146,9 +148,9 @@ func (f *friendDatabase) BecomeFriends(ctx context.Context, ownerUserID string,
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		opUserID := mcontext.GetOperationID(ctx)
 | 
							opUserID := mcontext.GetOperationID(ctx)
 | 
				
			||||||
		for _, v := range friendUserIDs {
 | 
							for _, v := range friendUserIDs {
 | 
				
			||||||
			fs1 = append(fs1, &relation.FriendModel{OwnerUserID: ownerUserID, FriendUserID: v, AddSource: addSource, OperatorUserID: opUserID})
 | 
								fs1 = append(fs1, &model.Friend{OwnerUserID: ownerUserID, FriendUserID: v, AddSource: addSource, OperatorUserID: opUserID})
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		fs11 := datautil.DistinctAny(fs1, func(e *relation.FriendModel) string {
 | 
							fs11 := datautil.DistinctAny(fs1, func(e *model.Friend) string {
 | 
				
			||||||
			return e.FriendUserID
 | 
								return e.FriendUserID
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -162,10 +164,10 @@ func (f *friendDatabase) BecomeFriends(ctx context.Context, ownerUserID string,
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		var newFriendIDs []string
 | 
							var newFriendIDs []string
 | 
				
			||||||
		for _, v := range friendUserIDs {
 | 
							for _, v := range friendUserIDs {
 | 
				
			||||||
			fs2 = append(fs2, &relation.FriendModel{OwnerUserID: v, FriendUserID: ownerUserID, AddSource: addSource, OperatorUserID: opUserID})
 | 
								fs2 = append(fs2, &model.Friend{OwnerUserID: v, FriendUserID: ownerUserID, AddSource: addSource, OperatorUserID: opUserID})
 | 
				
			||||||
			newFriendIDs = append(newFriendIDs, v)
 | 
								newFriendIDs = append(newFriendIDs, v)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		fs22 := datautil.DistinctAny(fs2, func(e *relation.FriendModel) string {
 | 
							fs22 := datautil.DistinctAny(fs2, func(e *model.Friend) string {
 | 
				
			||||||
			return e.OwnerUserID
 | 
								return e.OwnerUserID
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
		err = f.friend.Create(ctx, fs22)
 | 
							err = f.friend.Create(ctx, fs22)
 | 
				
			||||||
@ -174,14 +176,14 @@ func (f *friendDatabase) BecomeFriends(ctx context.Context, ownerUserID string,
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		newFriendIDs = append(newFriendIDs, ownerUserID)
 | 
							newFriendIDs = append(newFriendIDs, ownerUserID)
 | 
				
			||||||
		cache = cache.DelFriendIDs(newFriendIDs...)
 | 
							cache = cache.DelFriendIDs(newFriendIDs...)
 | 
				
			||||||
		return cache.ExecDel(ctx)
 | 
							return cache.ChainExecDel(ctx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RefuseFriendRequest rejects a friend request. It first checks for an existing, unprocessed request.
 | 
					// RefuseFriendRequest rejects a friend request. It first checks for an existing, unprocessed request.
 | 
				
			||||||
// If no such request exists, it returns an error. Otherwise, it marks the request as refused.
 | 
					// If no such request exists, it returns an error. Otherwise, it marks the request as refused.
 | 
				
			||||||
func (f *friendDatabase) RefuseFriendRequest(ctx context.Context, friendRequest *relation.FriendRequestModel) error {
 | 
					func (f *friendDatabase) RefuseFriendRequest(ctx context.Context, friendRequest *model.FriendRequest) error {
 | 
				
			||||||
	// Attempt to retrieve the friend request from the database.
 | 
						// Attempt to retrieve the friend request from the database.
 | 
				
			||||||
	fr, err := f.friendRequest.Take(ctx, friendRequest.FromUserID, friendRequest.ToUserID)
 | 
						fr, err := f.friendRequest.Take(ctx, friendRequest.FromUserID, friendRequest.ToUserID)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -210,7 +212,7 @@ func (f *friendDatabase) RefuseFriendRequest(ctx context.Context, friendRequest
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// AgreeFriendRequest accepts a friend request. It first checks for an existing, unprocessed request.
 | 
					// AgreeFriendRequest accepts a friend request. It first checks for an existing, unprocessed request.
 | 
				
			||||||
func (f *friendDatabase) AgreeFriendRequest(ctx context.Context, friendRequest *relation.FriendRequestModel) (err error) {
 | 
					func (f *friendDatabase) AgreeFriendRequest(ctx context.Context, friendRequest *model.FriendRequest) (err error) {
 | 
				
			||||||
	return f.tx.Transaction(ctx, func(ctx context.Context) error {
 | 
						return f.tx.Transaction(ctx, func(ctx context.Context) error {
 | 
				
			||||||
		now := time.Now()
 | 
							now := time.Now()
 | 
				
			||||||
		fr, err := f.friendRequest.Take(ctx, friendRequest.FromUserID, friendRequest.ToUserID)
 | 
							fr, err := f.friendRequest.Take(ctx, friendRequest.FromUserID, friendRequest.ToUserID)
 | 
				
			||||||
@ -237,7 +239,7 @@ func (f *friendDatabase) AgreeFriendRequest(ctx context.Context, friendRequest *
 | 
				
			|||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				return err
 | 
									return err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else if err != nil && (!relation.IsNotFound(err)) {
 | 
							} else if err != nil && (!mgo.IsNotFound(err)) {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -245,14 +247,14 @@ func (f *friendDatabase) AgreeFriendRequest(ctx context.Context, friendRequest *
 | 
				
			|||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		existsMap := datautil.SliceSet(datautil.Slice(exists, func(friend *relation.FriendModel) [2]string {
 | 
							existsMap := datautil.SliceSet(datautil.Slice(exists, func(friend *model.Friend) [2]string {
 | 
				
			||||||
			return [...]string{friend.OwnerUserID, friend.FriendUserID} // My - Friend
 | 
								return [...]string{friend.OwnerUserID, friend.FriendUserID} // My - Friend
 | 
				
			||||||
		}))
 | 
							}))
 | 
				
			||||||
		var adds []*relation.FriendModel
 | 
							var adds []*model.Friend
 | 
				
			||||||
		if _, ok := existsMap[[...]string{friendRequest.ToUserID, friendRequest.FromUserID}]; !ok { // My - Friend
 | 
							if _, ok := existsMap[[...]string{friendRequest.ToUserID, friendRequest.FromUserID}]; !ok { // My - Friend
 | 
				
			||||||
			adds = append(
 | 
								adds = append(
 | 
				
			||||||
				adds,
 | 
									adds,
 | 
				
			||||||
				&relation.FriendModel{
 | 
									&model.Friend{
 | 
				
			||||||
					OwnerUserID:    friendRequest.ToUserID,
 | 
										OwnerUserID:    friendRequest.ToUserID,
 | 
				
			||||||
					FriendUserID:   friendRequest.FromUserID,
 | 
										FriendUserID:   friendRequest.FromUserID,
 | 
				
			||||||
					AddSource:      int32(constant.BecomeFriendByApply),
 | 
										AddSource:      int32(constant.BecomeFriendByApply),
 | 
				
			||||||
@ -263,7 +265,7 @@ func (f *friendDatabase) AgreeFriendRequest(ctx context.Context, friendRequest *
 | 
				
			|||||||
		if _, ok := existsMap[[...]string{friendRequest.FromUserID, friendRequest.ToUserID}]; !ok { // My - Friend
 | 
							if _, ok := existsMap[[...]string{friendRequest.FromUserID, friendRequest.ToUserID}]; !ok { // My - Friend
 | 
				
			||||||
			adds = append(
 | 
								adds = append(
 | 
				
			||||||
				adds,
 | 
									adds,
 | 
				
			||||||
				&relation.FriendModel{
 | 
									&model.Friend{
 | 
				
			||||||
					OwnerUserID:    friendRequest.FromUserID,
 | 
										OwnerUserID:    friendRequest.FromUserID,
 | 
				
			||||||
					FriendUserID:   friendRequest.ToUserID,
 | 
										FriendUserID:   friendRequest.ToUserID,
 | 
				
			||||||
					AddSource:      int32(constant.BecomeFriendByApply),
 | 
										AddSource:      int32(constant.BecomeFriendByApply),
 | 
				
			||||||
@ -276,7 +278,7 @@ func (f *friendDatabase) AgreeFriendRequest(ctx context.Context, friendRequest *
 | 
				
			|||||||
				return err
 | 
									return err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return f.cache.DelFriendIDs(friendRequest.ToUserID, friendRequest.FromUserID).ExecDel(ctx)
 | 
							return f.cache.DelFriendIDs(friendRequest.ToUserID, friendRequest.FromUserID).ChainExecDel(ctx)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -285,7 +287,7 @@ func (f *friendDatabase) Delete(ctx context.Context, ownerUserID string, friendU
 | 
				
			|||||||
	if err := f.friend.Delete(ctx, ownerUserID, friendUserIDs); err != nil {
 | 
						if err := f.friend.Delete(ctx, ownerUserID, friendUserIDs); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return f.cache.DelFriendIDs(append(friendUserIDs, ownerUserID)...).ExecDel(ctx)
 | 
						return f.cache.DelFriendIDs(append(friendUserIDs, ownerUserID)...).ChainExecDel(ctx)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UpdateRemark updates the remark for a friend. Zero value for remark is also supported.
 | 
					// UpdateRemark updates the remark for a friend. Zero value for remark is also supported.
 | 
				
			||||||
@ -293,31 +295,31 @@ func (f *friendDatabase) UpdateRemark(ctx context.Context, ownerUserID, friendUs
 | 
				
			|||||||
	if err := f.friend.UpdateRemark(ctx, ownerUserID, friendUserID, remark); err != nil {
 | 
						if err := f.friend.UpdateRemark(ctx, ownerUserID, friendUserID, remark); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return f.cache.DelFriend(ownerUserID, friendUserID).ExecDel(ctx)
 | 
						return f.cache.DelFriend(ownerUserID, friendUserID).ChainExecDel(ctx)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// PageOwnerFriends retrieves the list of friends for the ownerUserID. It does not return an error if the result is empty.
 | 
					// PageOwnerFriends retrieves the list of friends for the ownerUserID. It does not return an error if the result is empty.
 | 
				
			||||||
func (f *friendDatabase) PageOwnerFriends(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendModel, err error) {
 | 
					func (f *friendDatabase) PageOwnerFriends(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, friends []*model.Friend, err error) {
 | 
				
			||||||
	return f.friend.FindOwnerFriends(ctx, ownerUserID, pagination)
 | 
						return f.friend.FindOwnerFriends(ctx, ownerUserID, pagination)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// PageInWhoseFriends identifies in whose friend lists the friendUserID appears.
 | 
					// PageInWhoseFriends identifies in whose friend lists the friendUserID appears.
 | 
				
			||||||
func (f *friendDatabase) PageInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendModel, err error) {
 | 
					func (f *friendDatabase) PageInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (total int64, friends []*model.Friend, err error) {
 | 
				
			||||||
	return f.friend.FindInWhoseFriends(ctx, friendUserID, pagination)
 | 
						return f.friend.FindInWhoseFriends(ctx, friendUserID, pagination)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// PageFriendRequestFromMe retrieves friend requests sent by me. It does not return an error if the result is empty.
 | 
					// PageFriendRequestFromMe retrieves friend requests sent by me. It does not return an error if the result is empty.
 | 
				
			||||||
func (f *friendDatabase) PageFriendRequestFromMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendRequestModel, err error) {
 | 
					func (f *friendDatabase) PageFriendRequestFromMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*model.FriendRequest, err error) {
 | 
				
			||||||
	return f.friendRequest.FindFromUserID(ctx, userID, pagination)
 | 
						return f.friendRequest.FindFromUserID(ctx, userID, pagination)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// PageFriendRequestToMe retrieves friend requests received by me. It does not return an error if the result is empty.
 | 
					// PageFriendRequestToMe retrieves friend requests received by me. It does not return an error if the result is empty.
 | 
				
			||||||
func (f *friendDatabase) PageFriendRequestToMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendRequestModel, err error) {
 | 
					func (f *friendDatabase) PageFriendRequestToMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*model.FriendRequest, err error) {
 | 
				
			||||||
	return f.friendRequest.FindToUserID(ctx, userID, pagination)
 | 
						return f.friendRequest.FindToUserID(ctx, userID, pagination)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// FindFriendsWithError retrieves specified friends' information for ownerUserID. Returns an error if any friend does not exist.
 | 
					// FindFriendsWithError retrieves specified friends' information for ownerUserID. Returns an error if any friend does not exist.
 | 
				
			||||||
func (f *friendDatabase) FindFriendsWithError(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*relation.FriendModel, err error) {
 | 
					func (f *friendDatabase) FindFriendsWithError(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*model.Friend, err error) {
 | 
				
			||||||
	friends, err = f.friend.FindFriends(ctx, ownerUserID, friendUserIDs)
 | 
						friends, err = f.friend.FindFriends(ctx, ownerUserID, friendUserIDs)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
@ -332,7 +334,7 @@ func (f *friendDatabase) FindFriendUserIDs(ctx context.Context, ownerUserID stri
 | 
				
			|||||||
	return f.cache.GetFriendIDs(ctx, ownerUserID)
 | 
						return f.cache.GetFriendIDs(ctx, ownerUserID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *friendDatabase) FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*relation.FriendRequestModel, err error) {
 | 
					func (f *friendDatabase) FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*model.FriendRequest, err error) {
 | 
				
			||||||
	return f.friendRequest.FindBothFriendRequests(ctx, fromUserID, toUserID)
 | 
						return f.friendRequest.FindBothFriendRequests(ctx, fromUserID, toUserID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
func (f *friendDatabase) UpdateFriends(ctx context.Context, ownerUserID string, friendUserIDs []string, val map[string]any) (err error) {
 | 
					func (f *friendDatabase) UpdateFriends(ctx context.Context, ownerUserID string, friendUserIDs []string, val map[string]any) (err error) {
 | 
				
			||||||
@ -342,5 +344,5 @@ func (f *friendDatabase) UpdateFriends(ctx context.Context, ownerUserID string,
 | 
				
			|||||||
	if err := f.friend.UpdateFriends(ctx, ownerUserID, friendUserIDs, val); err != nil {
 | 
						if err := f.friend.UpdateFriends(ctx, ownerUserID, friendUserIDs, val); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return f.cache.DelFriends(ownerUserID, friendUserIDs).ExecDel(ctx)
 | 
						return f.cache.DelFriends(ownerUserID, friendUserIDs).ChainExecDel(ctx)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -17,11 +17,13 @@ package controller
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
				
			||||||
 | 
						redis2 "github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/common"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/dtm-labs/rockscache"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
 | 
					 | 
				
			||||||
	relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/protocol/constant"
 | 
						"github.com/openimsdk/protocol/constant"
 | 
				
			||||||
	"github.com/openimsdk/tools/db/pagination"
 | 
						"github.com/openimsdk/tools/db/pagination"
 | 
				
			||||||
	"github.com/openimsdk/tools/db/tx"
 | 
						"github.com/openimsdk/tools/db/tx"
 | 
				
			||||||
@ -31,32 +33,32 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
type GroupDatabase interface {
 | 
					type GroupDatabase interface {
 | 
				
			||||||
	// CreateGroup creates new groups along with their members.
 | 
						// CreateGroup creates new groups along with their members.
 | 
				
			||||||
	CreateGroup(ctx context.Context, groups []*relationtb.GroupModel, groupMembers []*relationtb.GroupMemberModel) error
 | 
						CreateGroup(ctx context.Context, groups []*model.Group, groupMembers []*model.GroupMember) error
 | 
				
			||||||
	// TakeGroup retrieves a single group by its ID.
 | 
						// TakeGroup retrieves a single group by its ID.
 | 
				
			||||||
	TakeGroup(ctx context.Context, groupID string) (group *relationtb.GroupModel, err error)
 | 
						TakeGroup(ctx context.Context, groupID string) (group *model.Group, err error)
 | 
				
			||||||
	// FindGroup retrieves multiple groups by their IDs.
 | 
						// FindGroup retrieves multiple groups by their IDs.
 | 
				
			||||||
	FindGroup(ctx context.Context, groupIDs []string) (groups []*relationtb.GroupModel, err error)
 | 
						FindGroup(ctx context.Context, groupIDs []string) (groups []*model.Group, err error)
 | 
				
			||||||
	// SearchGroup searches for groups based on a keyword and pagination settings, returns total count and groups.
 | 
						// SearchGroup searches for groups based on a keyword and pagination settings, returns total count and groups.
 | 
				
			||||||
	SearchGroup(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*relationtb.GroupModel, error)
 | 
						SearchGroup(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*model.Group, error)
 | 
				
			||||||
	// UpdateGroup updates the properties of a group identified by its ID.
 | 
						// UpdateGroup updates the properties of a group identified by its ID.
 | 
				
			||||||
	UpdateGroup(ctx context.Context, groupID string, data map[string]any) error
 | 
						UpdateGroup(ctx context.Context, groupID string, data map[string]any) error
 | 
				
			||||||
	// DismissGroup disbands a group and optionally removes its members based on the deleteMember flag.
 | 
						// DismissGroup disbands a group and optionally removes its members based on the deleteMember flag.
 | 
				
			||||||
	DismissGroup(ctx context.Context, groupID string, deleteMember bool) error
 | 
						DismissGroup(ctx context.Context, groupID string, deleteMember bool) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TakeGroupMember retrieves a specific group member by group ID and user ID.
 | 
						// TakeGroupMember retrieves a specific group member by group ID and user ID.
 | 
				
			||||||
	TakeGroupMember(ctx context.Context, groupID string, userID string) (groupMember *relationtb.GroupMemberModel, err error)
 | 
						TakeGroupMember(ctx context.Context, groupID string, userID string) (groupMember *model.GroupMember, err error)
 | 
				
			||||||
	// TakeGroupOwner retrieves the owner of a group by group ID.
 | 
						// TakeGroupOwner retrieves the owner of a group by group ID.
 | 
				
			||||||
	TakeGroupOwner(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error)
 | 
						TakeGroupOwner(ctx context.Context, groupID string) (*model.GroupMember, error)
 | 
				
			||||||
	// FindGroupMembers retrieves members of a group filtered by user IDs.
 | 
						// FindGroupMembers retrieves members of a group filtered by user IDs.
 | 
				
			||||||
	FindGroupMembers(ctx context.Context, groupID string, userIDs []string) (groupMembers []*relationtb.GroupMemberModel, err error)
 | 
						FindGroupMembers(ctx context.Context, groupID string, userIDs []string) (groupMembers []*model.GroupMember, err error)
 | 
				
			||||||
	// FindGroupMemberUser retrieves groups that a user is a member of, filtered by group IDs.
 | 
						// FindGroupMemberUser retrieves groups that a user is a member of, filtered by group IDs.
 | 
				
			||||||
	FindGroupMemberUser(ctx context.Context, groupIDs []string, userID string) (groupMembers []*relationtb.GroupMemberModel, err error)
 | 
						FindGroupMemberUser(ctx context.Context, groupIDs []string, userID string) (groupMembers []*model.GroupMember, err error)
 | 
				
			||||||
	// FindGroupMemberRoleLevels retrieves group members filtered by their role levels within a group.
 | 
						// FindGroupMemberRoleLevels retrieves group members filtered by their role levels within a group.
 | 
				
			||||||
	FindGroupMemberRoleLevels(ctx context.Context, groupID string, roleLevels []int32) (groupMembers []*relationtb.GroupMemberModel, err error)
 | 
						FindGroupMemberRoleLevels(ctx context.Context, groupID string, roleLevels []int32) (groupMembers []*model.GroupMember, err error)
 | 
				
			||||||
	// FindGroupMemberAll retrieves all members of a group.
 | 
						// FindGroupMemberAll retrieves all members of a group.
 | 
				
			||||||
	FindGroupMemberAll(ctx context.Context, groupID string) (groupMembers []*relationtb.GroupMemberModel, err error)
 | 
						FindGroupMemberAll(ctx context.Context, groupID string) (groupMembers []*model.GroupMember, err error)
 | 
				
			||||||
	// FindGroupsOwner retrieves the owners for multiple groups.
 | 
						// FindGroupsOwner retrieves the owners for multiple groups.
 | 
				
			||||||
	FindGroupsOwner(ctx context.Context, groupIDs []string) ([]*relationtb.GroupMemberModel, error)
 | 
						FindGroupsOwner(ctx context.Context, groupIDs []string) ([]*model.GroupMember, error)
 | 
				
			||||||
	// FindGroupMemberUserID retrieves the user IDs of all members in a group.
 | 
						// FindGroupMemberUserID retrieves the user IDs of all members in a group.
 | 
				
			||||||
	FindGroupMemberUserID(ctx context.Context, groupID string) ([]string, error)
 | 
						FindGroupMemberUserID(ctx context.Context, groupID string) ([]string, error)
 | 
				
			||||||
	// FindGroupMemberNum retrieves the number of members in a group.
 | 
						// FindGroupMemberNum retrieves the number of members in a group.
 | 
				
			||||||
@ -64,22 +66,22 @@ type GroupDatabase interface {
 | 
				
			|||||||
	// FindUserManagedGroupID retrieves group IDs managed by a user.
 | 
						// FindUserManagedGroupID retrieves group IDs managed by a user.
 | 
				
			||||||
	FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error)
 | 
						FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error)
 | 
				
			||||||
	// PageGroupRequest paginates through group requests for specified groups.
 | 
						// PageGroupRequest paginates through group requests for specified groups.
 | 
				
			||||||
	PageGroupRequest(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (int64, []*relationtb.GroupRequestModel, error)
 | 
						PageGroupRequest(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (int64, []*model.GroupRequest, error)
 | 
				
			||||||
	// GetGroupRoleLevelMemberIDs retrieves user IDs of group members with a specific role level.
 | 
						// GetGroupRoleLevelMemberIDs retrieves user IDs of group members with a specific role level.
 | 
				
			||||||
	GetGroupRoleLevelMemberIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error)
 | 
						GetGroupRoleLevelMemberIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// PageGetJoinGroup paginates through groups that a user has joined.
 | 
						// PageGetJoinGroup paginates through groups that a user has joined.
 | 
				
			||||||
	PageGetJoinGroup(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*relationtb.GroupMemberModel, err error)
 | 
						PageGetJoinGroup(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*model.GroupMember, err error)
 | 
				
			||||||
	// PageGetGroupMember paginates through members of a group.
 | 
						// PageGetGroupMember paginates through members of a group.
 | 
				
			||||||
	PageGetGroupMember(ctx context.Context, groupID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*relationtb.GroupMemberModel, err error)
 | 
						PageGetGroupMember(ctx context.Context, groupID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*model.GroupMember, err error)
 | 
				
			||||||
	// SearchGroupMember searches for group members based on a keyword, group ID, and pagination settings.
 | 
						// SearchGroupMember searches for group members based on a keyword, group ID, and pagination settings.
 | 
				
			||||||
	SearchGroupMember(ctx context.Context, keyword string, groupID string, pagination pagination.Pagination) (int64, []*relationtb.GroupMemberModel, error)
 | 
						SearchGroupMember(ctx context.Context, keyword string, groupID string, pagination pagination.Pagination) (int64, []*model.GroupMember, error)
 | 
				
			||||||
	// HandlerGroupRequest processes a group join request with a specified result.
 | 
						// HandlerGroupRequest processes a group join request with a specified result.
 | 
				
			||||||
	HandlerGroupRequest(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32, member *relationtb.GroupMemberModel) error
 | 
						HandlerGroupRequest(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32, member *model.GroupMember) error
 | 
				
			||||||
	// DeleteGroupMember removes specified users from a group.
 | 
						// DeleteGroupMember removes specified users from a group.
 | 
				
			||||||
	DeleteGroupMember(ctx context.Context, groupID string, userIDs []string) error
 | 
						DeleteGroupMember(ctx context.Context, groupID string, userIDs []string) error
 | 
				
			||||||
	// MapGroupMemberUserID maps group IDs to their members' simplified user IDs.
 | 
						// MapGroupMemberUserID maps group IDs to their members' simplified user IDs.
 | 
				
			||||||
	MapGroupMemberUserID(ctx context.Context, groupIDs []string) (map[string]*relationtb.GroupSimpleUserID, error)
 | 
						MapGroupMemberUserID(ctx context.Context, groupIDs []string) (map[string]*common.GroupSimpleUserID, error)
 | 
				
			||||||
	// MapGroupMemberNum maps group IDs to their member count.
 | 
						// MapGroupMemberNum maps group IDs to their member count.
 | 
				
			||||||
	MapGroupMemberNum(ctx context.Context, groupIDs []string) (map[string]uint32, error)
 | 
						MapGroupMemberNum(ctx context.Context, groupIDs []string) (map[string]uint32, error)
 | 
				
			||||||
	// TransferGroupOwner transfers the ownership of a group to another user.
 | 
						// TransferGroupOwner transfers the ownership of a group to another user.
 | 
				
			||||||
@ -87,16 +89,16 @@ type GroupDatabase interface {
 | 
				
			|||||||
	// UpdateGroupMember updates properties of a group member.
 | 
						// UpdateGroupMember updates properties of a group member.
 | 
				
			||||||
	UpdateGroupMember(ctx context.Context, groupID string, userID string, data map[string]any) error
 | 
						UpdateGroupMember(ctx context.Context, groupID string, userID string, data map[string]any) error
 | 
				
			||||||
	// UpdateGroupMembers batch updates properties of group members.
 | 
						// UpdateGroupMembers batch updates properties of group members.
 | 
				
			||||||
	UpdateGroupMembers(ctx context.Context, data []*relationtb.BatchUpdateGroupMember) error
 | 
						UpdateGroupMembers(ctx context.Context, data []*common.BatchUpdateGroupMember) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// CreateGroupRequest creates new group join requests.
 | 
						// CreateGroupRequest creates new group join requests.
 | 
				
			||||||
	CreateGroupRequest(ctx context.Context, requests []*relationtb.GroupRequestModel) error
 | 
						CreateGroupRequest(ctx context.Context, requests []*model.GroupRequest) error
 | 
				
			||||||
	// TakeGroupRequest retrieves a specific group join request.
 | 
						// TakeGroupRequest retrieves a specific group join request.
 | 
				
			||||||
	TakeGroupRequest(ctx context.Context, groupID string, userID string) (*relationtb.GroupRequestModel, error)
 | 
						TakeGroupRequest(ctx context.Context, groupID string, userID string) (*model.GroupRequest, error)
 | 
				
			||||||
	// FindGroupRequests retrieves multiple group join requests.
 | 
						// FindGroupRequests retrieves multiple group join requests.
 | 
				
			||||||
	FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*relationtb.GroupRequestModel, error)
 | 
						FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*model.GroupRequest, error)
 | 
				
			||||||
	// PageGroupRequestUser paginates through group join requests made by a user.
 | 
						// PageGroupRequestUser paginates through group join requests made by a user.
 | 
				
			||||||
	PageGroupRequestUser(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*relationtb.GroupRequestModel, error)
 | 
						PageGroupRequestUser(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*model.GroupRequest, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// CountTotal counts the total number of groups as of a certain date.
 | 
						// CountTotal counts the total number of groups as of a certain date.
 | 
				
			||||||
	CountTotal(ctx context.Context, before *time.Time) (count int64, err error)
 | 
						CountTotal(ctx context.Context, before *time.Time) (count int64, err error)
 | 
				
			||||||
@ -109,49 +111,46 @@ type GroupDatabase interface {
 | 
				
			|||||||
func NewGroupDatabase(
 | 
					func NewGroupDatabase(
 | 
				
			||||||
	rdb redis.UniversalClient,
 | 
						rdb redis.UniversalClient,
 | 
				
			||||||
	localCache *config.LocalCache,
 | 
						localCache *config.LocalCache,
 | 
				
			||||||
	groupDB relationtb.GroupModelInterface,
 | 
						groupDB database.Group,
 | 
				
			||||||
	groupMemberDB relationtb.GroupMemberModelInterface,
 | 
						groupMemberDB database.GroupMember,
 | 
				
			||||||
	groupRequestDB relationtb.GroupRequestModelInterface,
 | 
						groupRequestDB database.GroupRequest,
 | 
				
			||||||
	ctxTx tx.Tx,
 | 
						ctxTx tx.Tx,
 | 
				
			||||||
	groupHash cache.GroupHash,
 | 
						groupHash cache.GroupHash,
 | 
				
			||||||
) GroupDatabase {
 | 
					) GroupDatabase {
 | 
				
			||||||
	rcOptions := rockscache.NewDefaultOptions()
 | 
					 | 
				
			||||||
	rcOptions.StrongConsistency = true
 | 
					 | 
				
			||||||
	rcOptions.RandomExpireAdjustment = 0.2
 | 
					 | 
				
			||||||
	return &groupDatabase{
 | 
						return &groupDatabase{
 | 
				
			||||||
		groupDB:        groupDB,
 | 
							groupDB:        groupDB,
 | 
				
			||||||
		groupMemberDB:  groupMemberDB,
 | 
							groupMemberDB:  groupMemberDB,
 | 
				
			||||||
		groupRequestDB: groupRequestDB,
 | 
							groupRequestDB: groupRequestDB,
 | 
				
			||||||
		ctxTx:          ctxTx,
 | 
							ctxTx:          ctxTx,
 | 
				
			||||||
		cache:          cache.NewGroupCacheRedis(rdb, localCache, groupDB, groupMemberDB, groupRequestDB, groupHash, rcOptions),
 | 
							cache:          redis2.NewGroupCacheRedis(rdb, localCache, groupDB, groupMemberDB, groupRequestDB, groupHash, redis2.GetRocksCacheOptions()),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type groupDatabase struct {
 | 
					type groupDatabase struct {
 | 
				
			||||||
	groupDB        relationtb.GroupModelInterface
 | 
						groupDB        database.Group
 | 
				
			||||||
	groupMemberDB  relationtb.GroupMemberModelInterface
 | 
						groupMemberDB  database.GroupMember
 | 
				
			||||||
	groupRequestDB relationtb.GroupRequestModelInterface
 | 
						groupRequestDB database.GroupRequest
 | 
				
			||||||
	ctxTx          tx.Tx
 | 
						ctxTx          tx.Tx
 | 
				
			||||||
	cache          cache.GroupCache
 | 
						cache          cache.GroupCache
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *groupDatabase) FindGroupMembers(ctx context.Context, groupID string, userIDs []string) ([]*relationtb.GroupMemberModel, error) {
 | 
					func (g *groupDatabase) FindGroupMembers(ctx context.Context, groupID string, userIDs []string) ([]*model.GroupMember, error) {
 | 
				
			||||||
	return g.cache.GetGroupMembersInfo(ctx, groupID, userIDs)
 | 
						return g.cache.GetGroupMembersInfo(ctx, groupID, userIDs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *groupDatabase) FindGroupMemberUser(ctx context.Context, groupIDs []string, userID string) ([]*relationtb.GroupMemberModel, error) {
 | 
					func (g *groupDatabase) FindGroupMemberUser(ctx context.Context, groupIDs []string, userID string) ([]*model.GroupMember, error) {
 | 
				
			||||||
	return g.cache.FindGroupMemberUser(ctx, groupIDs, userID)
 | 
						return g.cache.FindGroupMemberUser(ctx, groupIDs, userID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *groupDatabase) FindGroupMemberRoleLevels(ctx context.Context, groupID string, roleLevels []int32) ([]*relationtb.GroupMemberModel, error) {
 | 
					func (g *groupDatabase) FindGroupMemberRoleLevels(ctx context.Context, groupID string, roleLevels []int32) ([]*model.GroupMember, error) {
 | 
				
			||||||
	return g.cache.GetGroupRolesLevelMemberInfo(ctx, groupID, roleLevels)
 | 
						return g.cache.GetGroupRolesLevelMemberInfo(ctx, groupID, roleLevels)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *groupDatabase) FindGroupMemberAll(ctx context.Context, groupID string) ([]*relationtb.GroupMemberModel, error) {
 | 
					func (g *groupDatabase) FindGroupMemberAll(ctx context.Context, groupID string) ([]*model.GroupMember, error) {
 | 
				
			||||||
	return g.cache.GetAllGroupMembersInfo(ctx, groupID)
 | 
						return g.cache.GetAllGroupMembersInfo(ctx, groupID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *groupDatabase) FindGroupsOwner(ctx context.Context, groupIDs []string) ([]*relationtb.GroupMemberModel, error) {
 | 
					func (g *groupDatabase) FindGroupsOwner(ctx context.Context, groupIDs []string) ([]*model.GroupMember, error) {
 | 
				
			||||||
	return g.cache.GetGroupsOwner(ctx, groupIDs)
 | 
						return g.cache.GetGroupsOwner(ctx, groupIDs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -159,12 +158,12 @@ func (g *groupDatabase) GetGroupRoleLevelMemberIDs(ctx context.Context, groupID
 | 
				
			|||||||
	return g.cache.GetGroupRoleLevelMemberIDs(ctx, groupID, roleLevel)
 | 
						return g.cache.GetGroupRoleLevelMemberIDs(ctx, groupID, roleLevel)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *groupDatabase) CreateGroup(ctx context.Context, groups []*relationtb.GroupModel, groupMembers []*relationtb.GroupMemberModel) error {
 | 
					func (g *groupDatabase) CreateGroup(ctx context.Context, groups []*model.Group, groupMembers []*model.GroupMember) error {
 | 
				
			||||||
	if len(groups)+len(groupMembers) == 0 {
 | 
						if len(groups)+len(groupMembers) == 0 {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
 | 
						return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
 | 
				
			||||||
		c := g.cache.NewCache()
 | 
							c := g.cache.CloneGroupCache()
 | 
				
			||||||
		if len(groups) > 0 {
 | 
							if len(groups) > 0 {
 | 
				
			||||||
			if err := g.groupDB.Create(ctx, groups); err != nil {
 | 
								if err := g.groupDB.Create(ctx, groups); err != nil {
 | 
				
			||||||
				return err
 | 
									return err
 | 
				
			||||||
@ -191,7 +190,7 @@ func (g *groupDatabase) CreateGroup(ctx context.Context, groups []*relationtb.Gr
 | 
				
			|||||||
					DelGroupAllRoleLevel(groupMember.GroupID)
 | 
										DelGroupAllRoleLevel(groupMember.GroupID)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return c.ExecDel(ctx, true)
 | 
							return c.ChainExecDel(ctx)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -207,15 +206,15 @@ func (g *groupDatabase) FindGroupMemberNum(ctx context.Context, groupID string)
 | 
				
			|||||||
	return uint32(num), nil
 | 
						return uint32(num), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *groupDatabase) TakeGroup(ctx context.Context, groupID string) (*relationtb.GroupModel, error) {
 | 
					func (g *groupDatabase) TakeGroup(ctx context.Context, groupID string) (*model.Group, error) {
 | 
				
			||||||
	return g.cache.GetGroupInfo(ctx, groupID)
 | 
						return g.cache.GetGroupInfo(ctx, groupID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *groupDatabase) FindGroup(ctx context.Context, groupIDs []string) ([]*relationtb.GroupModel, error) {
 | 
					func (g *groupDatabase) FindGroup(ctx context.Context, groupIDs []string) ([]*model.Group, error) {
 | 
				
			||||||
	return g.cache.GetGroupsInfo(ctx, groupIDs)
 | 
						return g.cache.GetGroupsInfo(ctx, groupIDs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *groupDatabase) SearchGroup(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*relationtb.GroupModel, error) {
 | 
					func (g *groupDatabase) SearchGroup(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*model.Group, error) {
 | 
				
			||||||
	return g.groupDB.Search(ctx, keyword, pagination)
 | 
						return g.groupDB.Search(ctx, keyword, pagination)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -223,12 +222,12 @@ func (g *groupDatabase) UpdateGroup(ctx context.Context, groupID string, data ma
 | 
				
			|||||||
	if err := g.groupDB.UpdateMap(ctx, groupID, data); err != nil {
 | 
						if err := g.groupDB.UpdateMap(ctx, groupID, data); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return g.cache.DelGroupsInfo(groupID).ExecDel(ctx)
 | 
						return g.cache.DelGroupsInfo(groupID).ChainExecDel(ctx)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *groupDatabase) DismissGroup(ctx context.Context, groupID string, deleteMember bool) error {
 | 
					func (g *groupDatabase) DismissGroup(ctx context.Context, groupID string, deleteMember bool) error {
 | 
				
			||||||
	return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
 | 
						return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
 | 
				
			||||||
		c := g.cache.NewCache()
 | 
							c := g.cache.CloneGroupCache()
 | 
				
			||||||
		if err := g.groupDB.UpdateStatus(ctx, groupID, constant.GroupStatusDismissed); err != nil {
 | 
							if err := g.groupDB.UpdateStatus(ctx, groupID, constant.GroupStatusDismissed); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -247,15 +246,15 @@ func (g *groupDatabase) DismissGroup(ctx context.Context, groupID string, delete
 | 
				
			|||||||
				DelGroupAllRoleLevel(groupID).
 | 
									DelGroupAllRoleLevel(groupID).
 | 
				
			||||||
				DelGroupMembersInfo(groupID, userIDs...)
 | 
									DelGroupMembersInfo(groupID, userIDs...)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return c.DelGroupsInfo(groupID).ExecDel(ctx)
 | 
							return c.DelGroupsInfo(groupID).ChainExecDel(ctx)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *groupDatabase) TakeGroupMember(ctx context.Context, groupID string, userID string) (*relationtb.GroupMemberModel, error) {
 | 
					func (g *groupDatabase) TakeGroupMember(ctx context.Context, groupID string, userID string) (*model.GroupMember, error) {
 | 
				
			||||||
	return g.cache.GetGroupMemberInfo(ctx, groupID, userID)
 | 
						return g.cache.GetGroupMemberInfo(ctx, groupID, userID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *groupDatabase) TakeGroupOwner(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error) {
 | 
					func (g *groupDatabase) TakeGroupOwner(ctx context.Context, groupID string) (*model.GroupMember, error) {
 | 
				
			||||||
	return g.cache.GetGroupOwner(ctx, groupID)
 | 
						return g.cache.GetGroupOwner(ctx, groupID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -263,11 +262,11 @@ func (g *groupDatabase) FindUserManagedGroupID(ctx context.Context, userID strin
 | 
				
			|||||||
	return g.groupMemberDB.FindUserManagedGroupID(ctx, userID)
 | 
						return g.groupMemberDB.FindUserManagedGroupID(ctx, userID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *groupDatabase) PageGroupRequest(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (int64, []*relationtb.GroupRequestModel, error) {
 | 
					func (g *groupDatabase) PageGroupRequest(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (int64, []*model.GroupRequest, error) {
 | 
				
			||||||
	return g.groupRequestDB.PageGroup(ctx, groupIDs, pagination)
 | 
						return g.groupRequestDB.PageGroup(ctx, groupIDs, pagination)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *groupDatabase) PageGetJoinGroup(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*relationtb.GroupMemberModel, err error) {
 | 
					func (g *groupDatabase) PageGetJoinGroup(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*model.GroupMember, err error) {
 | 
				
			||||||
	groupIDs, err := g.cache.GetJoinedGroupIDs(ctx, userID)
 | 
						groupIDs, err := g.cache.GetJoinedGroupIDs(ctx, userID)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return 0, nil, err
 | 
							return 0, nil, err
 | 
				
			||||||
@ -282,7 +281,7 @@ func (g *groupDatabase) PageGetJoinGroup(ctx context.Context, userID string, pag
 | 
				
			|||||||
	return int64(len(groupIDs)), totalGroupMembers, nil
 | 
						return int64(len(groupIDs)), totalGroupMembers, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *groupDatabase) PageGetGroupMember(ctx context.Context, groupID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*relationtb.GroupMemberModel, err error) {
 | 
					func (g *groupDatabase) PageGetGroupMember(ctx context.Context, groupID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*model.GroupMember, err error) {
 | 
				
			||||||
	groupMemberIDs, err := g.cache.GetGroupMemberIDs(ctx, groupID)
 | 
						groupMemberIDs, err := g.cache.GetGroupMemberIDs(ctx, groupID)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return 0, nil, err
 | 
							return 0, nil, err
 | 
				
			||||||
@ -298,26 +297,27 @@ func (g *groupDatabase) PageGetGroupMember(ctx context.Context, groupID string,
 | 
				
			|||||||
	return int64(len(groupMemberIDs)), members, nil
 | 
						return int64(len(groupMemberIDs)), members, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *groupDatabase) SearchGroupMember(ctx context.Context, keyword string, groupID string, pagination pagination.Pagination) (int64, []*relationtb.GroupMemberModel, error) {
 | 
					func (g *groupDatabase) SearchGroupMember(ctx context.Context, keyword string, groupID string, pagination pagination.Pagination) (int64, []*model.GroupMember, error) {
 | 
				
			||||||
	return g.groupMemberDB.SearchMember(ctx, keyword, groupID, pagination)
 | 
						return g.groupMemberDB.SearchMember(ctx, keyword, groupID, pagination)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *groupDatabase) HandlerGroupRequest(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32, member *relationtb.GroupMemberModel) error {
 | 
					func (g *groupDatabase) HandlerGroupRequest(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32, member *model.GroupMember) error {
 | 
				
			||||||
	return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
 | 
						return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
 | 
				
			||||||
		if err := g.groupRequestDB.UpdateHandler(ctx, groupID, userID, handledMsg, handleResult); err != nil {
 | 
							if err := g.groupRequestDB.UpdateHandler(ctx, groupID, userID, handledMsg, handleResult); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if member != nil {
 | 
							if member != nil {
 | 
				
			||||||
			if err := g.groupMemberDB.Create(ctx, []*relationtb.GroupMemberModel{member}); err != nil {
 | 
								c := g.cache.CloneGroupCache()
 | 
				
			||||||
 | 
								if err := g.groupMemberDB.Create(ctx, []*model.GroupMember{member}); err != nil {
 | 
				
			||||||
				return err
 | 
									return err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			c := g.cache.DelGroupMembersHash(groupID).
 | 
								c = c.DelGroupMembersHash(groupID).
 | 
				
			||||||
				DelGroupMembersInfo(groupID, member.UserID).
 | 
									DelGroupMembersInfo(groupID, member.UserID).
 | 
				
			||||||
				DelGroupMemberIDs(groupID).
 | 
									DelGroupMemberIDs(groupID).
 | 
				
			||||||
				DelGroupsMemberNum(groupID).
 | 
									DelGroupsMemberNum(groupID).
 | 
				
			||||||
				DelJoinedGroupID(member.UserID).
 | 
									DelJoinedGroupID(member.UserID).
 | 
				
			||||||
				DelGroupRoleLevel(groupID, []int32{member.RoleLevel})
 | 
									DelGroupRoleLevel(groupID, []int32{member.RoleLevel})
 | 
				
			||||||
			if err := c.ExecDel(ctx); err != nil {
 | 
								if err := c.ChainExecDel(ctx); err != nil {
 | 
				
			||||||
				return err
 | 
									return err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -329,16 +329,17 @@ func (g *groupDatabase) DeleteGroupMember(ctx context.Context, groupID string, u
 | 
				
			|||||||
	if err := g.groupMemberDB.Delete(ctx, groupID, userIDs); err != nil {
 | 
						if err := g.groupMemberDB.Delete(ctx, groupID, userIDs); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return g.cache.DelGroupMembersHash(groupID).
 | 
						c := g.cache.CloneGroupCache()
 | 
				
			||||||
 | 
						return c.DelGroupMembersHash(groupID).
 | 
				
			||||||
		DelGroupMemberIDs(groupID).
 | 
							DelGroupMemberIDs(groupID).
 | 
				
			||||||
		DelGroupsMemberNum(groupID).
 | 
							DelGroupsMemberNum(groupID).
 | 
				
			||||||
		DelJoinedGroupID(userIDs...).
 | 
							DelJoinedGroupID(userIDs...).
 | 
				
			||||||
		DelGroupMembersInfo(groupID, userIDs...).
 | 
							DelGroupMembersInfo(groupID, userIDs...).
 | 
				
			||||||
		DelGroupAllRoleLevel(groupID).
 | 
							DelGroupAllRoleLevel(groupID).
 | 
				
			||||||
		ExecDel(ctx)
 | 
							ChainExecDel(ctx)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *groupDatabase) MapGroupMemberUserID(ctx context.Context, groupIDs []string) (map[string]*relationtb.GroupSimpleUserID, error) {
 | 
					func (g *groupDatabase) MapGroupMemberUserID(ctx context.Context, groupIDs []string) (map[string]*common.GroupSimpleUserID, error) {
 | 
				
			||||||
	return g.cache.GetGroupMemberHashMap(ctx, groupIDs)
 | 
						return g.cache.GetGroupMemberHashMap(ctx, groupIDs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -362,9 +363,10 @@ func (g *groupDatabase) TransferGroupOwner(ctx context.Context, groupID string,
 | 
				
			|||||||
		if err := g.groupMemberDB.UpdateRoleLevel(ctx, groupID, newOwnerUserID, constant.GroupOwner); err != nil {
 | 
							if err := g.groupMemberDB.UpdateRoleLevel(ctx, groupID, newOwnerUserID, constant.GroupOwner); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return g.cache.DelGroupMembersInfo(groupID, oldOwnerUserID, newOwnerUserID).
 | 
							c := g.cache.CloneGroupCache()
 | 
				
			||||||
 | 
							return c.DelGroupMembersInfo(groupID, oldOwnerUserID, newOwnerUserID).
 | 
				
			||||||
			DelGroupAllRoleLevel(groupID).
 | 
								DelGroupAllRoleLevel(groupID).
 | 
				
			||||||
			DelGroupMembersHash(groupID).ExecDel(ctx)
 | 
								DelGroupMembersHash(groupID).ChainExecDel(ctx)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -372,16 +374,17 @@ func (g *groupDatabase) UpdateGroupMember(ctx context.Context, groupID string, u
 | 
				
			|||||||
	if err := g.groupMemberDB.Update(ctx, groupID, userID, data); err != nil {
 | 
						if err := g.groupMemberDB.Update(ctx, groupID, userID, data); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	c := g.cache.DelGroupMembersInfo(groupID, userID)
 | 
						c := g.cache.CloneGroupCache()
 | 
				
			||||||
 | 
						c = c.DelGroupMembersInfo(groupID, userID)
 | 
				
			||||||
	if g.groupMemberDB.IsUpdateRoleLevel(data) {
 | 
						if g.groupMemberDB.IsUpdateRoleLevel(data) {
 | 
				
			||||||
		c = c.DelGroupAllRoleLevel(groupID)
 | 
							c = c.DelGroupAllRoleLevel(groupID)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return c.ExecDel(ctx)
 | 
						return c.ChainExecDel(ctx)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *groupDatabase) UpdateGroupMembers(ctx context.Context, data []*relationtb.BatchUpdateGroupMember) error {
 | 
					func (g *groupDatabase) UpdateGroupMembers(ctx context.Context, data []*common.BatchUpdateGroupMember) error {
 | 
				
			||||||
	return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
 | 
						return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
 | 
				
			||||||
		c := g.cache.NewCache()
 | 
							c := g.cache.CloneGroupCache()
 | 
				
			||||||
		for _, item := range data {
 | 
							for _, item := range data {
 | 
				
			||||||
			if err := g.groupMemberDB.Update(ctx, item.GroupID, item.UserID, item.Map); err != nil {
 | 
								if err := g.groupMemberDB.Update(ctx, item.GroupID, item.UserID, item.Map); err != nil {
 | 
				
			||||||
				return err
 | 
									return err
 | 
				
			||||||
@ -391,11 +394,11 @@ func (g *groupDatabase) UpdateGroupMembers(ctx context.Context, data []*relation
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			c = c.DelGroupMembersInfo(item.GroupID, item.UserID).DelGroupMembersHash(item.GroupID)
 | 
								c = c.DelGroupMembersInfo(item.GroupID, item.UserID).DelGroupMembersHash(item.GroupID)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return c.ExecDel(ctx, true)
 | 
							return c.ChainExecDel(ctx)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *groupDatabase) CreateGroupRequest(ctx context.Context, requests []*relationtb.GroupRequestModel) error {
 | 
					func (g *groupDatabase) CreateGroupRequest(ctx context.Context, requests []*model.GroupRequest) error {
 | 
				
			||||||
	return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
 | 
						return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
 | 
				
			||||||
		for _, request := range requests {
 | 
							for _, request := range requests {
 | 
				
			||||||
			if err := g.groupRequestDB.Delete(ctx, request.GroupID, request.UserID); err != nil {
 | 
								if err := g.groupRequestDB.Delete(ctx, request.GroupID, request.UserID); err != nil {
 | 
				
			||||||
@ -410,11 +413,11 @@ func (g *groupDatabase) TakeGroupRequest(
 | 
				
			|||||||
	ctx context.Context,
 | 
						ctx context.Context,
 | 
				
			||||||
	groupID string,
 | 
						groupID string,
 | 
				
			||||||
	userID string,
 | 
						userID string,
 | 
				
			||||||
) (*relationtb.GroupRequestModel, error) {
 | 
					) (*model.GroupRequest, error) {
 | 
				
			||||||
	return g.groupRequestDB.Take(ctx, groupID, userID)
 | 
						return g.groupRequestDB.Take(ctx, groupID, userID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *groupDatabase) PageGroupRequestUser(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*relationtb.GroupRequestModel, error) {
 | 
					func (g *groupDatabase) PageGroupRequestUser(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*model.GroupRequest, error) {
 | 
				
			||||||
	return g.groupRequestDB.Page(ctx, userID, pagination)
 | 
						return g.groupRequestDB.Page(ctx, userID, pagination)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -426,7 +429,7 @@ func (g *groupDatabase) CountRangeEverydayTotal(ctx context.Context, start time.
 | 
				
			|||||||
	return g.groupDB.CountRangeEverydayTotal(ctx, start, end)
 | 
						return g.groupDB.CountRangeEverydayTotal(ctx, start, end)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *groupDatabase) FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*relationtb.GroupRequestModel, error) {
 | 
					func (g *groupDatabase) FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*model.GroupRequest, error) {
 | 
				
			||||||
	return g.groupRequestDB.FindGroupRequests(ctx, groupID, userIDs)
 | 
						return g.groupRequestDB.FindGroupRequests(ctx, groupID, userIDs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -434,9 +437,9 @@ func (g *groupDatabase) DeleteGroupMemberHash(ctx context.Context, groupIDs []st
 | 
				
			|||||||
	if len(groupIDs) == 0 {
 | 
						if len(groupIDs) == 0 {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	c := g.cache.NewCache()
 | 
						c := g.cache.CloneGroupCache()
 | 
				
			||||||
	for _, groupID := range groupIDs {
 | 
						for _, groupID := range groupIDs {
 | 
				
			||||||
		c = c.DelGroupMembersHash(groupID)
 | 
							c = c.DelGroupMembersHash(groupID)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return c.ExecDel(ctx)
 | 
						return c.ChainExecDel(ctx)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -18,14 +18,15 @@ import (
 | 
				
			|||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/config"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
 | 
				
			||||||
	"github.com/openimsdk/protocol/constant"
 | 
						"github.com/openimsdk/protocol/constant"
 | 
				
			||||||
	pbmsg "github.com/openimsdk/protocol/msg"
 | 
						pbmsg "github.com/openimsdk/protocol/msg"
 | 
				
			||||||
	"github.com/openimsdk/protocol/sdkws"
 | 
						"github.com/openimsdk/protocol/sdkws"
 | 
				
			||||||
@ -48,7 +49,7 @@ type CommonMsgDatabase interface {
 | 
				
			|||||||
	// BatchInsertChat2DB inserts a batch of messages into the database for a specific conversation.
 | 
						// BatchInsertChat2DB inserts a batch of messages into the database for a specific conversation.
 | 
				
			||||||
	BatchInsertChat2DB(ctx context.Context, conversationID string, msgs []*sdkws.MsgData, currentMaxSeq int64) error
 | 
						BatchInsertChat2DB(ctx context.Context, conversationID string, msgs []*sdkws.MsgData, currentMaxSeq int64) error
 | 
				
			||||||
	// RevokeMsg revokes a message in a conversation.
 | 
						// RevokeMsg revokes a message in a conversation.
 | 
				
			||||||
	RevokeMsg(ctx context.Context, conversationID string, seq int64, revoke *relation.RevokeModel) error
 | 
						RevokeMsg(ctx context.Context, conversationID string, seq int64, revoke *model.RevokeModel) error
 | 
				
			||||||
	// MarkSingleChatMsgsAsRead marks messages as read for a single chat by sequence numbers.
 | 
						// MarkSingleChatMsgsAsRead marks messages as read for a single chat by sequence numbers.
 | 
				
			||||||
	MarkSingleChatMsgsAsRead(ctx context.Context, userID string, conversationID string, seqs []int64) error
 | 
						MarkSingleChatMsgsAsRead(ctx context.Context, userID string, conversationID string, seqs []int64) error
 | 
				
			||||||
	// DeleteMessagesFromCache deletes message caches from Redis by sequence numbers.
 | 
						// DeleteMessagesFromCache deletes message caches from Redis by sequence numbers.
 | 
				
			||||||
@ -101,16 +102,16 @@ type CommonMsgDatabase interface {
 | 
				
			|||||||
	MsgToPushMQ(ctx context.Context, key, conversarionID string, msg2mq *sdkws.MsgData) (int32, int64, error)
 | 
						MsgToPushMQ(ctx context.Context, key, conversarionID string, msg2mq *sdkws.MsgData) (int32, int64, error)
 | 
				
			||||||
	MsgToMongoMQ(ctx context.Context, key, conversarionID string, msgs []*sdkws.MsgData, lastSeq int64) error
 | 
						MsgToMongoMQ(ctx context.Context, key, conversarionID string, msgs []*sdkws.MsgData, lastSeq int64) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	RangeUserSendCount(ctx context.Context, start time.Time, end time.Time, group bool, ase bool, pageNumber int32, showNumber int32) (msgCount int64, userCount int64, users []*relation.UserCount, dateCount map[string]int64, err error)
 | 
						RangeUserSendCount(ctx context.Context, start time.Time, end time.Time, group bool, ase bool, pageNumber int32, showNumber int32) (msgCount int64, userCount int64, users []*model.UserCount, dateCount map[string]int64, err error)
 | 
				
			||||||
	RangeGroupSendCount(ctx context.Context, start time.Time, end time.Time, ase bool, pageNumber int32, showNumber int32) (msgCount int64, userCount int64, groups []*relation.GroupCount, dateCount map[string]int64, err error)
 | 
						RangeGroupSendCount(ctx context.Context, start time.Time, end time.Time, ase bool, pageNumber int32, showNumber int32) (msgCount int64, userCount int64, groups []*model.GroupCount, dateCount map[string]int64, err error)
 | 
				
			||||||
	ConvertMsgsDocLen(ctx context.Context, conversationIDs []string)
 | 
						ConvertMsgsDocLen(ctx context.Context, conversationIDs []string)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// clear msg
 | 
						// clear msg
 | 
				
			||||||
	GetBeforeMsg(ctx context.Context, ts int64, limit int) ([]*relation.MsgDocModel, error)
 | 
						GetBeforeMsg(ctx context.Context, ts int64, limit int) ([]*model.MsgDocModel, error)
 | 
				
			||||||
	DeleteDocMsgBefore(ctx context.Context, ts int64, doc *relation.MsgDocModel) ([]int, error)
 | 
						DeleteDocMsgBefore(ctx context.Context, ts int64, doc *model.MsgDocModel) ([]int, error)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewCommonMsgDatabase(msgDocModel relation.MsgDocModelInterface, msg cache.MsgCache, seq cache.SeqCache, kafkaConf *config.Kafka) (CommonMsgDatabase, error) {
 | 
					func NewCommonMsgDatabase(msgDocModel database.Msg, msg cache.MsgCache, seq cache.SeqCache, kafkaConf *config.Kafka) (CommonMsgDatabase, error) {
 | 
				
			||||||
	conf, err := kafka.BuildProducerConfig(*kafkaConf.Build())
 | 
						conf, err := kafka.BuildProducerConfig(*kafkaConf.Build())
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
@ -138,7 +139,7 @@ func NewCommonMsgDatabase(msgDocModel relation.MsgDocModelInterface, msg cache.M
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//func InitCommonMsgDatabase(rdb redis.UniversalClient, database *mongo.Database, config *tools.CronTaskConfig) (CommonMsgDatabase, error) {
 | 
					//func InitCommonMsgDatabase(rdb redis.UniversalClient, database *mongo.Database, config *tools.CronTaskConfig) (CommonMsgDatabase, error) {
 | 
				
			||||||
//	msgDocModel, err := mgo.NewMsgMongo(database)
 | 
					//	msgDocModel, err := database.NewMsgMongo(database)
 | 
				
			||||||
//	if err != nil {
 | 
					//	if err != nil {
 | 
				
			||||||
//		return nil, err
 | 
					//		return nil, err
 | 
				
			||||||
//	}
 | 
					//	}
 | 
				
			||||||
@ -149,8 +150,8 @@ func NewCommonMsgDatabase(msgDocModel relation.MsgDocModelInterface, msg cache.M
 | 
				
			|||||||
//}
 | 
					//}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type commonMsgDatabase struct {
 | 
					type commonMsgDatabase struct {
 | 
				
			||||||
	msgDocDatabase   relation.MsgDocModelInterface
 | 
						msgDocDatabase   database.Msg
 | 
				
			||||||
	msgTable         relation.MsgDocModel
 | 
						msgTable         model.MsgDocModel
 | 
				
			||||||
	msg              cache.MsgCache
 | 
						msg              cache.MsgCache
 | 
				
			||||||
	seq              cache.SeqCache
 | 
						seq              cache.SeqCache
 | 
				
			||||||
	producer         *kafka.Producer
 | 
						producer         *kafka.Producer
 | 
				
			||||||
@ -199,13 +200,13 @@ func (db *commonMsgDatabase) BatchInsertBlock(ctx context.Context, conversationI
 | 
				
			|||||||
		var ok bool
 | 
							var ok bool
 | 
				
			||||||
		switch key {
 | 
							switch key {
 | 
				
			||||||
		case updateKeyMsg:
 | 
							case updateKeyMsg:
 | 
				
			||||||
			var msg *relation.MsgDataModel
 | 
								var msg *model.MsgDataModel
 | 
				
			||||||
			msg, ok = field.(*relation.MsgDataModel)
 | 
								msg, ok = field.(*model.MsgDataModel)
 | 
				
			||||||
			if msg != nil && msg.Seq != firstSeq+int64(i) {
 | 
								if msg != nil && msg.Seq != firstSeq+int64(i) {
 | 
				
			||||||
				return errs.ErrInternalServer.WrapMsg("seq is invalid")
 | 
									return errs.ErrInternalServer.WrapMsg("seq is invalid")
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		case updateKeyRevoke:
 | 
							case updateKeyRevoke:
 | 
				
			||||||
			_, ok = field.(*relation.RevokeModel)
 | 
								_, ok = field.(*model.RevokeModel)
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			return errs.ErrInternalServer.WrapMsg("key is invalid")
 | 
								return errs.ErrInternalServer.WrapMsg("key is invalid")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -245,9 +246,9 @@ func (db *commonMsgDatabase) BatchInsertBlock(ctx context.Context, conversationI
 | 
				
			|||||||
				continue // The current data has been updated, skip the current data
 | 
									continue // The current data has been updated, skip the current data
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		doc := relation.MsgDocModel{
 | 
							doc := model.MsgDocModel{
 | 
				
			||||||
			DocID: db.msgTable.GetDocID(conversationID, seq),
 | 
								DocID: db.msgTable.GetDocID(conversationID, seq),
 | 
				
			||||||
			Msg:   make([]*relation.MsgInfoModel, num),
 | 
								Msg:   make([]*model.MsgInfoModel, num),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		var insert int // Inserted data number
 | 
							var insert int // Inserted data number
 | 
				
			||||||
		for j := i; j < len(fields); j++ {
 | 
							for j := i; j < len(fields); j++ {
 | 
				
			||||||
@ -258,21 +259,21 @@ func (db *commonMsgDatabase) BatchInsertBlock(ctx context.Context, conversationI
 | 
				
			|||||||
			insert++
 | 
								insert++
 | 
				
			||||||
			switch key {
 | 
								switch key {
 | 
				
			||||||
			case updateKeyMsg:
 | 
								case updateKeyMsg:
 | 
				
			||||||
				doc.Msg[db.msgTable.GetMsgIndex(seq)] = &relation.MsgInfoModel{
 | 
									doc.Msg[db.msgTable.GetMsgIndex(seq)] = &model.MsgInfoModel{
 | 
				
			||||||
					Msg: fields[j].(*relation.MsgDataModel),
 | 
										Msg: fields[j].(*model.MsgDataModel),
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			case updateKeyRevoke:
 | 
								case updateKeyRevoke:
 | 
				
			||||||
				doc.Msg[db.msgTable.GetMsgIndex(seq)] = &relation.MsgInfoModel{
 | 
									doc.Msg[db.msgTable.GetMsgIndex(seq)] = &model.MsgInfoModel{
 | 
				
			||||||
					Revoke: fields[j].(*relation.RevokeModel),
 | 
										Revoke: fields[j].(*model.RevokeModel),
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		for i, model := range doc.Msg {
 | 
							for i, msgInfo := range doc.Msg {
 | 
				
			||||||
			if model == nil {
 | 
								if msgInfo == nil {
 | 
				
			||||||
				model = &relation.MsgInfoModel{}
 | 
									msgInfo = &model.MsgInfoModel{}
 | 
				
			||||||
				doc.Msg[i] = model
 | 
									doc.Msg[i] = msgInfo
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if model.DelList == nil {
 | 
								if msgInfo.DelList == nil {
 | 
				
			||||||
				doc.Msg[i].DelList = []string{}
 | 
									doc.Msg[i].DelList = []string{}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -299,9 +300,9 @@ func (db *commonMsgDatabase) BatchInsertChat2DB(ctx context.Context, conversatio
 | 
				
			|||||||
		if msg == nil {
 | 
							if msg == nil {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		var offlinePushModel *relation.OfflinePushModel
 | 
							var offlinePushModel *model.OfflinePushModel
 | 
				
			||||||
		if msg.OfflinePushInfo != nil {
 | 
							if msg.OfflinePushInfo != nil {
 | 
				
			||||||
			offlinePushModel = &relation.OfflinePushModel{
 | 
								offlinePushModel = &model.OfflinePushModel{
 | 
				
			||||||
				Title:         msg.OfflinePushInfo.Title,
 | 
									Title:         msg.OfflinePushInfo.Title,
 | 
				
			||||||
				Desc:          msg.OfflinePushInfo.Desc,
 | 
									Desc:          msg.OfflinePushInfo.Desc,
 | 
				
			||||||
				Ex:            msg.OfflinePushInfo.Ex,
 | 
									Ex:            msg.OfflinePushInfo.Ex,
 | 
				
			||||||
@ -309,7 +310,7 @@ func (db *commonMsgDatabase) BatchInsertChat2DB(ctx context.Context, conversatio
 | 
				
			|||||||
				IOSBadgeCount: msg.OfflinePushInfo.IOSBadgeCount,
 | 
									IOSBadgeCount: msg.OfflinePushInfo.IOSBadgeCount,
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		msgs[i] = &relation.MsgDataModel{
 | 
							msgs[i] = &model.MsgDataModel{
 | 
				
			||||||
			SendID:           msg.SendID,
 | 
								SendID:           msg.SendID,
 | 
				
			||||||
			RecvID:           msg.RecvID,
 | 
								RecvID:           msg.RecvID,
 | 
				
			||||||
			GroupID:          msg.GroupID,
 | 
								GroupID:          msg.GroupID,
 | 
				
			||||||
@ -336,7 +337,7 @@ func (db *commonMsgDatabase) BatchInsertChat2DB(ctx context.Context, conversatio
 | 
				
			|||||||
	return db.BatchInsertBlock(ctx, conversationID, msgs, updateKeyMsg, msgList[0].Seq)
 | 
						return db.BatchInsertBlock(ctx, conversationID, msgs, updateKeyMsg, msgList[0].Seq)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (db *commonMsgDatabase) RevokeMsg(ctx context.Context, conversationID string, seq int64, revoke *relation.RevokeModel) error {
 | 
					func (db *commonMsgDatabase) RevokeMsg(ctx context.Context, conversationID string, seq int64, revoke *model.RevokeModel) error {
 | 
				
			||||||
	return db.BatchInsertBlock(ctx, conversationID, []any{revoke}, updateKeyRevoke, seq)
 | 
						return db.BatchInsertBlock(ctx, conversationID, []any{revoke}, updateKeyRevoke, seq)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -366,7 +367,7 @@ func (db *commonMsgDatabase) DelUserDeleteMsgsList(ctx context.Context, conversa
 | 
				
			|||||||
func (db *commonMsgDatabase) BatchInsertChat2Cache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) (seq int64, isNew bool, err error) {
 | 
					func (db *commonMsgDatabase) BatchInsertChat2Cache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) (seq int64, isNew bool, err error) {
 | 
				
			||||||
	currentMaxSeq, err := db.seq.GetMaxSeq(ctx, conversationID)
 | 
						currentMaxSeq, err := db.seq.GetMaxSeq(ctx, conversationID)
 | 
				
			||||||
	if err != nil && errs.Unwrap(err) != redis.Nil {
 | 
						if err != nil && errs.Unwrap(err) != redis.Nil {
 | 
				
			||||||
		log.ZError(ctx, "db.seq.GetMaxSeq", err)
 | 
							log.ZError(ctx, "storage.seq.GetMaxSeq", err)
 | 
				
			||||||
		return 0, false, err
 | 
							return 0, false, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	lenList := len(msgs)
 | 
						lenList := len(msgs)
 | 
				
			||||||
@ -397,7 +398,7 @@ func (db *commonMsgDatabase) BatchInsertChat2Cache(ctx context.Context, conversa
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	err = db.seq.SetMaxSeq(ctx, conversationID, currentMaxSeq)
 | 
						err = db.seq.SetMaxSeq(ctx, conversationID, currentMaxSeq)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.ZError(ctx, "db.seq.SetMaxSeq error", err, "conversationID", conversationID)
 | 
							log.ZError(ctx, "storage.seq.SetMaxSeq error", err, "conversationID", conversationID)
 | 
				
			||||||
		prommetrics.SeqSetFailedCounter.Inc()
 | 
							prommetrics.SeqSetFailedCounter.Inc()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -423,7 +424,7 @@ func (db *commonMsgDatabase) getMsgBySeqs(ctx context.Context, userID, conversat
 | 
				
			|||||||
	return totalMsgs, nil
 | 
						return totalMsgs, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (db *commonMsgDatabase) handlerDBMsg(ctx context.Context, cache map[int64][]*relation.MsgInfoModel, userID, conversationID string, msg *relation.MsgInfoModel) {
 | 
					func (db *commonMsgDatabase) handlerDBMsg(ctx context.Context, cache map[int64][]*model.MsgInfoModel, userID, conversationID string, msg *model.MsgInfoModel) {
 | 
				
			||||||
	if msg.IsRead {
 | 
						if msg.IsRead {
 | 
				
			||||||
		msg.Msg.IsRead = true
 | 
							msg.Msg.IsRead = true
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -445,7 +446,7 @@ func (db *commonMsgDatabase) handlerDBMsg(ctx context.Context, cache map[int64][
 | 
				
			|||||||
	if quoteMsg.QuoteMessage == nil || quoteMsg.QuoteMessage.ContentType == constant.MsgRevokeNotification {
 | 
						if quoteMsg.QuoteMessage == nil || quoteMsg.QuoteMessage.ContentType == constant.MsgRevokeNotification {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	var msgs []*relation.MsgInfoModel
 | 
						var msgs []*model.MsgInfoModel
 | 
				
			||||||
	if v, ok := cache[quoteMsg.QuoteMessage.Seq]; ok {
 | 
						if v, ok := cache[quoteMsg.QuoteMessage.Seq]; ok {
 | 
				
			||||||
		msgs = v
 | 
							msgs = v
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
@ -479,12 +480,12 @@ func (db *commonMsgDatabase) handlerDBMsg(ctx context.Context, cache map[int64][
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (db *commonMsgDatabase) findMsgInfoBySeq(ctx context.Context, userID, docID string, conversationID string, seqs []int64) (totalMsgs []*relation.MsgInfoModel, err error) {
 | 
					func (db *commonMsgDatabase) findMsgInfoBySeq(ctx context.Context, userID, docID string, conversationID string, seqs []int64) (totalMsgs []*model.MsgInfoModel, err error) {
 | 
				
			||||||
	msgs, err := db.msgDocDatabase.GetMsgBySeqIndexIn1Doc(ctx, userID, docID, seqs)
 | 
						msgs, err := db.msgDocDatabase.GetMsgBySeqIndexIn1Doc(ctx, userID, docID, seqs)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	tempCache := make(map[int64][]*relation.MsgInfoModel)
 | 
						tempCache := make(map[int64][]*model.MsgInfoModel)
 | 
				
			||||||
	for _, msg := range msgs {
 | 
						for _, msg := range msgs {
 | 
				
			||||||
		db.handlerDBMsg(ctx, tempCache, userID, conversationID, msg)
 | 
							db.handlerDBMsg(ctx, tempCache, userID, conversationID, msg)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -636,7 +637,7 @@ func (db *commonMsgDatabase) GetMsgBySeqsRange(ctx context.Context, userID strin
 | 
				
			|||||||
	if len(failedSeqs) != 0 {
 | 
						if len(failedSeqs) != 0 {
 | 
				
			||||||
		log.ZDebug(ctx, "msgs not exist in redis", "seqs", failedSeqs)
 | 
							log.ZDebug(ctx, "msgs not exist in redis", "seqs", failedSeqs)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// get from cache or db
 | 
						// get from cache or storage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(failedSeqs) > 0 {
 | 
						if len(failedSeqs) > 0 {
 | 
				
			||||||
		mongoMsgs, err := db.getMsgBySeqsRange(ctx, userID, conversationID, failedSeqs, begin, end)
 | 
							mongoMsgs, err := db.getMsgBySeqsRange(ctx, userID, conversationID, failedSeqs, begin, end)
 | 
				
			||||||
@ -678,7 +679,7 @@ func (db *commonMsgDatabase) GetMsgBySeqs(ctx context.Context, userID string, co
 | 
				
			|||||||
			log.ZError(ctx, "get message from redis exception", err, "failedSeqs", failedSeqs, "conversationID", conversationID)
 | 
								log.ZError(ctx, "get message from redis exception", err, "failedSeqs", failedSeqs, "conversationID", conversationID)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	log.ZDebug(ctx, "db.seq.GetMessagesBySeq", "userID", userID, "conversationID", conversationID, "seqs",
 | 
						log.ZDebug(ctx, "storage.seq.GetMessagesBySeq", "userID", userID, "conversationID", conversationID, "seqs",
 | 
				
			||||||
		seqs, "len(successMsgs)", len(successMsgs), "failedSeqs", failedSeqs)
 | 
							seqs, "len(successMsgs)", len(successMsgs), "failedSeqs", failedSeqs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(failedSeqs) > 0 {
 | 
						if len(failedSeqs) > 0 {
 | 
				
			||||||
@ -720,7 +721,7 @@ func (db *commonMsgDatabase) UserMsgsDestruct(ctx context.Context, userID string
 | 
				
			|||||||
		msgDocModel, err := db.msgDocDatabase.GetMsgDocModelByIndex(ctx, conversationID, index, 1)
 | 
							msgDocModel, err := db.msgDocDatabase.GetMsgDocModelByIndex(ctx, conversationID, index, 1)
 | 
				
			||||||
		if err != nil || msgDocModel.DocID == "" {
 | 
							if err != nil || msgDocModel.DocID == "" {
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				if err == relation.ErrMsgListNotExist {
 | 
									if err == model.ErrMsgListNotExist {
 | 
				
			||||||
					log.ZDebug(ctx, "not doc find", "conversationID", conversationID, "userID", userID, "index", index)
 | 
										log.ZDebug(ctx, "not doc find", "conversationID", conversationID, "userID", userID, "index", index)
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					log.ZError(ctx, "deleteMsgRecursion GetUserMsgListByIndex failed", err, "conversationID", conversationID, "index", index)
 | 
										log.ZError(ctx, "deleteMsgRecursion GetUserMsgListByIndex failed", err, "conversationID", conversationID, "index", index)
 | 
				
			||||||
@ -787,7 +788,7 @@ func (db *commonMsgDatabase) deleteMsgRecursion(ctx context.Context, conversatio
 | 
				
			|||||||
	msgDocModel, err := db.msgDocDatabase.GetMsgDocModelByIndex(ctx, conversationID, index, 1)
 | 
						msgDocModel, err := db.msgDocDatabase.GetMsgDocModelByIndex(ctx, conversationID, index, 1)
 | 
				
			||||||
	if err != nil || msgDocModel.DocID == "" {
 | 
						if err != nil || msgDocModel.DocID == "" {
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			if err == relation.ErrMsgListNotExist {
 | 
								if err == model.ErrMsgListNotExist {
 | 
				
			||||||
				log.ZDebug(ctx, "deleteMsgRecursion ErrMsgListNotExist", "conversationID", conversationID, "index:", index)
 | 
									log.ZDebug(ctx, "deleteMsgRecursion ErrMsgListNotExist", "conversationID", conversationID, "index:", index)
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				log.ZError(ctx, "deleteMsgRecursion GetUserMsgListByIndex failed", err, "conversationID", conversationID, "index", index)
 | 
									log.ZError(ctx, "deleteMsgRecursion GetUserMsgListByIndex failed", err, "conversationID", conversationID, "index", index)
 | 
				
			||||||
@ -1005,7 +1006,7 @@ func (db *commonMsgDatabase) RangeUserSendCount(
 | 
				
			|||||||
	ase bool,
 | 
						ase bool,
 | 
				
			||||||
	pageNumber int32,
 | 
						pageNumber int32,
 | 
				
			||||||
	showNumber int32,
 | 
						showNumber int32,
 | 
				
			||||||
) (msgCount int64, userCount int64, users []*relation.UserCount, dateCount map[string]int64, err error) {
 | 
					) (msgCount int64, userCount int64, users []*model.UserCount, dateCount map[string]int64, err error) {
 | 
				
			||||||
	return db.msgDocDatabase.RangeUserSendCount(ctx, start, end, group, ase, pageNumber, showNumber)
 | 
						return db.msgDocDatabase.RangeUserSendCount(ctx, start, end, group, ase, pageNumber, showNumber)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1016,7 +1017,7 @@ func (db *commonMsgDatabase) RangeGroupSendCount(
 | 
				
			|||||||
	ase bool,
 | 
						ase bool,
 | 
				
			||||||
	pageNumber int32,
 | 
						pageNumber int32,
 | 
				
			||||||
	showNumber int32,
 | 
						showNumber int32,
 | 
				
			||||||
) (msgCount int64, userCount int64, groups []*relation.GroupCount, dateCount map[string]int64, err error) {
 | 
					) (msgCount int64, userCount int64, groups []*model.GroupCount, dateCount map[string]int64, err error) {
 | 
				
			||||||
	return db.msgDocDatabase.RangeGroupSendCount(ctx, start, end, ase, pageNumber, showNumber)
 | 
						return db.msgDocDatabase.RangeGroupSendCount(ctx, start, end, ase, pageNumber, showNumber)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1054,11 +1055,11 @@ func (db *commonMsgDatabase) ConvertMsgsDocLen(ctx context.Context, conversation
 | 
				
			|||||||
	db.msgDocDatabase.ConvertMsgsDocLen(ctx, conversationIDs)
 | 
						db.msgDocDatabase.ConvertMsgsDocLen(ctx, conversationIDs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (db *commonMsgDatabase) GetBeforeMsg(ctx context.Context, ts int64, limit int) ([]*relation.MsgDocModel, error) {
 | 
					func (db *commonMsgDatabase) GetBeforeMsg(ctx context.Context, ts int64, limit int) ([]*model.MsgDocModel, error) {
 | 
				
			||||||
	return db.msgDocDatabase.GetBeforeMsg(ctx, ts, limit)
 | 
						return db.msgDocDatabase.GetBeforeMsg(ctx, ts, limit)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (db *commonMsgDatabase) DeleteDocMsgBefore(ctx context.Context, ts int64, doc *relation.MsgDocModel) ([]int, error) {
 | 
					func (db *commonMsgDatabase) DeleteDocMsgBefore(ctx context.Context, ts int64, doc *model.MsgDocModel) ([]int, error) {
 | 
				
			||||||
	var notNull int
 | 
						var notNull int
 | 
				
			||||||
	index := make([]int, 0, len(doc.Msg))
 | 
						index := make([]int, 0, len(doc.Msg))
 | 
				
			||||||
	for i, message := range doc.Msg {
 | 
						for i, message := range doc.Msg {
 | 
				
			||||||
@ -1084,14 +1085,14 @@ func (db *commonMsgDatabase) DeleteDocMsgBefore(ctx context.Context, ts int64, d
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//func (db *commonMsgDatabase) ClearMsg(ctx context.Context, ts int64) (err error) {
 | 
					//func (storage *commonMsgDatabase) ClearMsg(ctx context.Context, ts int64) (err error) {
 | 
				
			||||||
//	var (
 | 
					//	var (
 | 
				
			||||||
//		docNum int
 | 
					//		docNum int
 | 
				
			||||||
//		msgNum int
 | 
					//		msgNum int
 | 
				
			||||||
//		start  = time.Now()
 | 
					//		start  = time.Now()
 | 
				
			||||||
//	)
 | 
					//	)
 | 
				
			||||||
//	for {
 | 
					//	for {
 | 
				
			||||||
//		msgs, err := db.msgDocDatabase.GetBeforeMsg(ctx, ts, 100)
 | 
					//		msgs, err := storage.msgDocDatabase.GetBeforeMsg(ctx, ts, 100)
 | 
				
			||||||
//		if err != nil {
 | 
					//		if err != nil {
 | 
				
			||||||
//			return err
 | 
					//			return err
 | 
				
			||||||
//		}
 | 
					//		}
 | 
				
			||||||
@ -1099,7 +1100,7 @@ func (db *commonMsgDatabase) DeleteDocMsgBefore(ctx context.Context, ts int64, d
 | 
				
			|||||||
//			return nil
 | 
					//			return nil
 | 
				
			||||||
//		}
 | 
					//		}
 | 
				
			||||||
//		for _, msg := range msgs {
 | 
					//		for _, msg := range msgs {
 | 
				
			||||||
//			num, err := db.deleteOneMsg(ctx, ts, msg)
 | 
					//			num, err := storage.deleteOneMsg(ctx, ts, msg)
 | 
				
			||||||
//			if err != nil {
 | 
					//			if err != nil {
 | 
				
			||||||
//				return err
 | 
					//				return err
 | 
				
			||||||
//			}
 | 
					//			}
 | 
				
			||||||
@ -17,7 +17,7 @@ package controller
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type PushDatabase interface {
 | 
					type PushDatabase interface {
 | 
				
			||||||
@ -16,11 +16,13 @@ package controller
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						redis2 "github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache/redis"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/tools/s3"
 | 
						"github.com/openimsdk/tools/s3"
 | 
				
			||||||
	"github.com/openimsdk/tools/s3/cont"
 | 
						"github.com/openimsdk/tools/s3/cont"
 | 
				
			||||||
	"github.com/redis/go-redis/v9"
 | 
						"github.com/redis/go-redis/v9"
 | 
				
			||||||
@ -33,15 +35,15 @@ type S3Database interface {
 | 
				
			|||||||
	InitiateMultipartUpload(ctx context.Context, hash string, size int64, expire time.Duration, maxParts int) (*cont.InitiateUploadResult, error)
 | 
						InitiateMultipartUpload(ctx context.Context, hash string, size int64, expire time.Duration, maxParts int) (*cont.InitiateUploadResult, error)
 | 
				
			||||||
	CompleteMultipartUpload(ctx context.Context, uploadID string, parts []string) (*cont.UploadResult, error)
 | 
						CompleteMultipartUpload(ctx context.Context, uploadID string, parts []string) (*cont.UploadResult, error)
 | 
				
			||||||
	AccessURL(ctx context.Context, name string, expire time.Duration, opt *s3.AccessURLOption) (time.Time, string, error)
 | 
						AccessURL(ctx context.Context, name string, expire time.Duration, opt *s3.AccessURLOption) (time.Time, string, error)
 | 
				
			||||||
	SetObject(ctx context.Context, info *relation.ObjectModel) error
 | 
						SetObject(ctx context.Context, info *model.Object) error
 | 
				
			||||||
	StatObject(ctx context.Context, name string) (*s3.ObjectInfo, error)
 | 
						StatObject(ctx context.Context, name string) (*s3.ObjectInfo, error)
 | 
				
			||||||
	FormData(ctx context.Context, name string, size int64, contentType string, duration time.Duration) (*s3.FormData, error)
 | 
						FormData(ctx context.Context, name string, size int64, contentType string, duration time.Duration) (*s3.FormData, error)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewS3Database(rdb redis.UniversalClient, s3 s3.Interface, obj relation.ObjectInfoModelInterface) S3Database {
 | 
					func NewS3Database(rdb redis.UniversalClient, s3 s3.Interface, obj database.ObjectInfo) S3Database {
 | 
				
			||||||
	return &s3Database{
 | 
						return &s3Database{
 | 
				
			||||||
		s3:    cont.New(cache.NewS3Cache(rdb, s3), s3),
 | 
							s3:    cont.New(redis2.NewS3Cache(rdb, s3), s3),
 | 
				
			||||||
		cache: cache.NewObjectCacheRedis(rdb, obj),
 | 
							cache: redis2.NewObjectCacheRedis(rdb, obj),
 | 
				
			||||||
		db:    obj,
 | 
							db:    obj,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -49,7 +51,7 @@ func NewS3Database(rdb redis.UniversalClient, s3 s3.Interface, obj relation.Obje
 | 
				
			|||||||
type s3Database struct {
 | 
					type s3Database struct {
 | 
				
			||||||
	s3    *cont.Controller
 | 
						s3    *cont.Controller
 | 
				
			||||||
	cache cache.ObjectCache
 | 
						cache cache.ObjectCache
 | 
				
			||||||
	db    relation.ObjectInfoModelInterface
 | 
						db    database.ObjectInfo
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *s3Database) PartSize(ctx context.Context, size int64) (int64, error) {
 | 
					func (s *s3Database) PartSize(ctx context.Context, size int64) (int64, error) {
 | 
				
			||||||
@ -72,12 +74,12 @@ func (s *s3Database) CompleteMultipartUpload(ctx context.Context, uploadID strin
 | 
				
			|||||||
	return s.s3.CompleteUpload(ctx, uploadID, parts)
 | 
						return s.s3.CompleteUpload(ctx, uploadID, parts)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *s3Database) SetObject(ctx context.Context, info *relation.ObjectModel) error {
 | 
					func (s *s3Database) SetObject(ctx context.Context, info *model.Object) error {
 | 
				
			||||||
	info.Engine = s.s3.Engine()
 | 
						info.Engine = s.s3.Engine()
 | 
				
			||||||
	if err := s.db.SetObject(ctx, info); err != nil {
 | 
						if err := s.db.SetObject(ctx, info); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return s.cache.DelObjectName(info.Engine, info.Name).ExecDel(ctx)
 | 
						return s.cache.DelObjectName(info.Engine, info.Name).ChainExecDel(ctx)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *s3Database) AccessURL(ctx context.Context, name string, expire time.Duration, opt *s3.AccessURLOption) (time.Time, string, error) {
 | 
					func (s *s3Database) AccessURL(ctx context.Context, name string, expire time.Duration, opt *s3.AccessURLOption) (time.Time, string, error) {
 | 
				
			||||||
@ -16,10 +16,11 @@ package controller
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/tools/db/pagination"
 | 
						"github.com/openimsdk/tools/db/pagination"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -27,15 +28,15 @@ type ThirdDatabase interface {
 | 
				
			|||||||
	FcmUpdateToken(ctx context.Context, account string, platformID int, fcmToken string, expireTime int64) error
 | 
						FcmUpdateToken(ctx context.Context, account string, platformID int, fcmToken string, expireTime int64) error
 | 
				
			||||||
	SetAppBadge(ctx context.Context, userID string, value int) error
 | 
						SetAppBadge(ctx context.Context, userID string, value int) error
 | 
				
			||||||
	// about log for debug
 | 
						// about log for debug
 | 
				
			||||||
	UploadLogs(ctx context.Context, logs []*relation.LogModel) error
 | 
						UploadLogs(ctx context.Context, logs []*model.Log) error
 | 
				
			||||||
	DeleteLogs(ctx context.Context, logID []string, userID string) error
 | 
						DeleteLogs(ctx context.Context, logID []string, userID string) error
 | 
				
			||||||
	SearchLogs(ctx context.Context, keyword string, start time.Time, end time.Time, pagination pagination.Pagination) (int64, []*relation.LogModel, error)
 | 
						SearchLogs(ctx context.Context, keyword string, start time.Time, end time.Time, pagination pagination.Pagination) (int64, []*model.Log, error)
 | 
				
			||||||
	GetLogs(ctx context.Context, LogIDs []string, userID string) ([]*relation.LogModel, error)
 | 
						GetLogs(ctx context.Context, LogIDs []string, userID string) ([]*model.Log, error)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type thirdDatabase struct {
 | 
					type thirdDatabase struct {
 | 
				
			||||||
	cache cache.ThirdCache
 | 
						cache cache.ThirdCache
 | 
				
			||||||
	logdb relation.LogInterface
 | 
						logdb database.Log
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DeleteLogs implements ThirdDatabase.
 | 
					// DeleteLogs implements ThirdDatabase.
 | 
				
			||||||
@ -44,21 +45,21 @@ func (t *thirdDatabase) DeleteLogs(ctx context.Context, logID []string, userID s
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetLogs implements ThirdDatabase.
 | 
					// GetLogs implements ThirdDatabase.
 | 
				
			||||||
func (t *thirdDatabase) GetLogs(ctx context.Context, LogIDs []string, userID string) ([]*relation.LogModel, error) {
 | 
					func (t *thirdDatabase) GetLogs(ctx context.Context, LogIDs []string, userID string) ([]*model.Log, error) {
 | 
				
			||||||
	return t.logdb.Get(ctx, LogIDs, userID)
 | 
						return t.logdb.Get(ctx, LogIDs, userID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SearchLogs implements ThirdDatabase.
 | 
					// SearchLogs implements ThirdDatabase.
 | 
				
			||||||
func (t *thirdDatabase) SearchLogs(ctx context.Context, keyword string, start time.Time, end time.Time, pagination pagination.Pagination) (int64, []*relation.LogModel, error) {
 | 
					func (t *thirdDatabase) SearchLogs(ctx context.Context, keyword string, start time.Time, end time.Time, pagination pagination.Pagination) (int64, []*model.Log, error) {
 | 
				
			||||||
	return t.logdb.Search(ctx, keyword, start, end, pagination)
 | 
						return t.logdb.Search(ctx, keyword, start, end, pagination)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UploadLogs implements ThirdDatabase.
 | 
					// UploadLogs implements ThirdDatabase.
 | 
				
			||||||
func (t *thirdDatabase) UploadLogs(ctx context.Context, logs []*relation.LogModel) error {
 | 
					func (t *thirdDatabase) UploadLogs(ctx context.Context, logs []*model.Log) error {
 | 
				
			||||||
	return t.logdb.Create(ctx, logs)
 | 
						return t.logdb.Create(ctx, logs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewThirdDatabase(cache cache.ThirdCache, logdb relation.LogInterface) ThirdDatabase {
 | 
					func NewThirdDatabase(cache cache.ThirdCache, logdb database.Log) ThirdDatabase {
 | 
				
			||||||
	return &thirdDatabase{cache: cache, logdb: logdb}
 | 
						return &thirdDatabase{cache: cache, logdb: logdb}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -16,6 +16,8 @@ package controller
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"github.com/openimsdk/tools/db/pagination"
 | 
						"github.com/openimsdk/tools/db/pagination"
 | 
				
			||||||
	"github.com/openimsdk/tools/db/tx"
 | 
						"github.com/openimsdk/tools/db/tx"
 | 
				
			||||||
	"github.com/openimsdk/tools/utils/datautil"
 | 
						"github.com/openimsdk/tools/utils/datautil"
 | 
				
			||||||
@ -24,37 +26,36 @@ import (
 | 
				
			|||||||
	"github.com/openimsdk/protocol/user"
 | 
						"github.com/openimsdk/protocol/user"
 | 
				
			||||||
	"github.com/openimsdk/tools/errs"
 | 
						"github.com/openimsdk/tools/errs"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type UserDatabase interface {
 | 
					type UserDatabase interface {
 | 
				
			||||||
	// FindWithError Get the information of the specified user. If the userID is not found, it will also return an error
 | 
						// FindWithError Get the information of the specified user. If the userID is not found, it will also return an error
 | 
				
			||||||
	FindWithError(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error)
 | 
						FindWithError(ctx context.Context, userIDs []string) (users []*model.User, err error)
 | 
				
			||||||
	// Find Get the information of the specified user If the userID is not found, no error will be returned
 | 
						// Find Get the information of the specified user If the userID is not found, no error will be returned
 | 
				
			||||||
	Find(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error)
 | 
						Find(ctx context.Context, userIDs []string) (users []*model.User, err error)
 | 
				
			||||||
	// Find userInfo By Nickname
 | 
						// Find userInfo By Nickname
 | 
				
			||||||
	FindByNickname(ctx context.Context, nickname string) (users []*relation.UserModel, err error)
 | 
						FindByNickname(ctx context.Context, nickname string) (users []*model.User, err error)
 | 
				
			||||||
	// Find notificationAccounts
 | 
						// Find notificationAccounts
 | 
				
			||||||
	FindNotification(ctx context.Context, level int64) (users []*relation.UserModel, err error)
 | 
						FindNotification(ctx context.Context, level int64) (users []*model.User, err error)
 | 
				
			||||||
	// Create Insert multiple external guarantees that the userID is not repeated and does not exist in the db
 | 
						// Create Insert multiple external guarantees that the userID is not repeated and does not exist in the storage
 | 
				
			||||||
	Create(ctx context.Context, users []*relation.UserModel) (err error)
 | 
						Create(ctx context.Context, users []*model.User) (err error)
 | 
				
			||||||
	// UpdateByMap update (zero value) external guarantee userID exists
 | 
						// UpdateByMap update (zero value) external guarantee userID exists
 | 
				
			||||||
	UpdateByMap(ctx context.Context, userID string, args map[string]any) (err error)
 | 
						UpdateByMap(ctx context.Context, userID string, args map[string]any) (err error)
 | 
				
			||||||
	// FindUser
 | 
						// FindUser
 | 
				
			||||||
	PageFindUser(ctx context.Context, level1 int64, level2 int64, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error)
 | 
						PageFindUser(ctx context.Context, level1 int64, level2 int64, pagination pagination.Pagination) (count int64, users []*model.User, err error)
 | 
				
			||||||
	// FindUser with keyword
 | 
						// FindUser with keyword
 | 
				
			||||||
	PageFindUserWithKeyword(ctx context.Context, level1 int64, level2 int64, userID string, nickName string, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error)
 | 
						PageFindUserWithKeyword(ctx context.Context, level1 int64, level2 int64, userID string, nickName string, pagination pagination.Pagination) (count int64, users []*model.User, err error)
 | 
				
			||||||
	// Page If not found, no error is returned
 | 
						// Page If not found, no error is returned
 | 
				
			||||||
	Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error)
 | 
						Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*model.User, err error)
 | 
				
			||||||
	// IsExist true as long as one exists
 | 
						// IsExist true as long as one exists
 | 
				
			||||||
	IsExist(ctx context.Context, userIDs []string) (exist bool, err error)
 | 
						IsExist(ctx context.Context, userIDs []string) (exist bool, err error)
 | 
				
			||||||
	// GetAllUserID Get all user IDs
 | 
						// GetAllUserID Get all user IDs
 | 
				
			||||||
	GetAllUserID(ctx context.Context, pagination pagination.Pagination) (int64, []string, error)
 | 
						GetAllUserID(ctx context.Context, pagination pagination.Pagination) (int64, []string, error)
 | 
				
			||||||
	// Get user by userID
 | 
						// Get user by userID
 | 
				
			||||||
	GetUserByID(ctx context.Context, userID string) (user *relation.UserModel, err error)
 | 
						GetUserByID(ctx context.Context, userID string) (user *model.User, err error)
 | 
				
			||||||
	// InitOnce Inside the function, first query whether it exists in the db, if it exists, do nothing; if it does not exist, insert it
 | 
						// InitOnce Inside the function, first query whether it exists in the storage, if it exists, do nothing; if it does not exist, insert it
 | 
				
			||||||
	InitOnce(ctx context.Context, users []*relation.UserModel) (err error)
 | 
						InitOnce(ctx context.Context, users []*model.User) (err error)
 | 
				
			||||||
	// CountTotal Get the total number of users
 | 
						// CountTotal Get the total number of users
 | 
				
			||||||
	CountTotal(ctx context.Context, before *time.Time) (int64, error)
 | 
						CountTotal(ctx context.Context, before *time.Time) (int64, error)
 | 
				
			||||||
	// CountRangeEverydayTotal Get the user increment in the range
 | 
						// CountRangeEverydayTotal Get the user increment in the range
 | 
				
			||||||
@ -82,18 +83,18 @@ type UserDatabase interface {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
type userDatabase struct {
 | 
					type userDatabase struct {
 | 
				
			||||||
	tx      tx.Tx
 | 
						tx      tx.Tx
 | 
				
			||||||
	userDB  relation.UserModelInterface
 | 
						userDB  database.User
 | 
				
			||||||
	cache   cache.UserCache
 | 
						cache   cache.UserCache
 | 
				
			||||||
	mongoDB relation.SubscribeUserModelInterface
 | 
						mongoDB database.SubscribeUser
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewUserDatabase(userDB relation.UserModelInterface, cache cache.UserCache, tx tx.Tx, mongoDB relation.SubscribeUserModelInterface) UserDatabase {
 | 
					func NewUserDatabase(userDB database.User, cache cache.UserCache, tx tx.Tx, mongoDB database.SubscribeUser) UserDatabase {
 | 
				
			||||||
	return &userDatabase{userDB: userDB, cache: cache, tx: tx, mongoDB: mongoDB}
 | 
						return &userDatabase{userDB: userDB, cache: cache, tx: tx, mongoDB: mongoDB}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (u *userDatabase) InitOnce(ctx context.Context, users []*relation.UserModel) error {
 | 
					func (u *userDatabase) InitOnce(ctx context.Context, users []*model.User) error {
 | 
				
			||||||
	// Extract user IDs from the given user models.
 | 
						// Extract user IDs from the given user models.
 | 
				
			||||||
	userIDs := datautil.Slice(users, func(e *relation.UserModel) string {
 | 
						userIDs := datautil.Slice(users, func(e *model.User) string {
 | 
				
			||||||
		return e.UserID
 | 
							return e.UserID
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -104,7 +105,7 @@ func (u *userDatabase) InitOnce(ctx context.Context, users []*relation.UserModel
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Determine which users are missing from the database.
 | 
						// Determine which users are missing from the database.
 | 
				
			||||||
	missingUsers := datautil.SliceAnySub(users, existingUsers, func(e *relation.UserModel) string {
 | 
						missingUsers := datautil.SliceAnySub(users, existingUsers, func(e *model.User) string {
 | 
				
			||||||
		return e.UserID
 | 
							return e.UserID
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -119,7 +120,7 @@ func (u *userDatabase) InitOnce(ctx context.Context, users []*relation.UserModel
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// FindWithError Get the information of the specified user and return an error if the userID is not found.
 | 
					// FindWithError Get the information of the specified user and return an error if the userID is not found.
 | 
				
			||||||
func (u *userDatabase) FindWithError(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error) {
 | 
					func (u *userDatabase) FindWithError(ctx context.Context, userIDs []string) (users []*model.User, err error) {
 | 
				
			||||||
	users, err = u.cache.GetUsersInfo(ctx, userIDs)
 | 
						users, err = u.cache.GetUsersInfo(ctx, userIDs)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
@ -131,27 +132,27 @@ func (u *userDatabase) FindWithError(ctx context.Context, userIDs []string) (use
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Find Get the information of the specified user. If the userID is not found, no error will be returned.
 | 
					// Find Get the information of the specified user. If the userID is not found, no error will be returned.
 | 
				
			||||||
func (u *userDatabase) Find(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error) {
 | 
					func (u *userDatabase) Find(ctx context.Context, userIDs []string) (users []*model.User, err error) {
 | 
				
			||||||
	return u.cache.GetUsersInfo(ctx, userIDs)
 | 
						return u.cache.GetUsersInfo(ctx, userIDs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (u *userDatabase) FindByNickname(ctx context.Context, nickname string) (users []*relation.UserModel, err error) {
 | 
					func (u *userDatabase) FindByNickname(ctx context.Context, nickname string) (users []*model.User, err error) {
 | 
				
			||||||
	return u.userDB.TakeByNickname(ctx, nickname)
 | 
						return u.userDB.TakeByNickname(ctx, nickname)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (u *userDatabase) FindNotification(ctx context.Context, level int64) (users []*relation.UserModel, err error) {
 | 
					func (u *userDatabase) FindNotification(ctx context.Context, level int64) (users []*model.User, err error) {
 | 
				
			||||||
	return u.userDB.TakeNotification(ctx, level)
 | 
						return u.userDB.TakeNotification(ctx, level)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Create Insert multiple external guarantees that the userID is not repeated and does not exist in the db.
 | 
					// Create Insert multiple external guarantees that the userID is not repeated and does not exist in the storage.
 | 
				
			||||||
func (u *userDatabase) Create(ctx context.Context, users []*relation.UserModel) (err error) {
 | 
					func (u *userDatabase) Create(ctx context.Context, users []*model.User) (err error) {
 | 
				
			||||||
	return u.tx.Transaction(ctx, func(ctx context.Context) error {
 | 
						return u.tx.Transaction(ctx, func(ctx context.Context) error {
 | 
				
			||||||
		if err = u.userDB.Create(ctx, users); err != nil {
 | 
							if err = u.userDB.Create(ctx, users); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return u.cache.DelUsersInfo(datautil.Slice(users, func(e *relation.UserModel) string {
 | 
							return u.cache.DelUsersInfo(datautil.Slice(users, func(e *model.User) string {
 | 
				
			||||||
			return e.UserID
 | 
								return e.UserID
 | 
				
			||||||
		})...).ExecDel(ctx)
 | 
							})...).ChainExecDel(ctx)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -161,20 +162,20 @@ func (u *userDatabase) UpdateByMap(ctx context.Context, userID string, args map[
 | 
				
			|||||||
		if err := u.userDB.UpdateByMap(ctx, userID, args); err != nil {
 | 
							if err := u.userDB.UpdateByMap(ctx, userID, args); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return u.cache.DelUsersInfo(userID).ExecDel(ctx)
 | 
							return u.cache.DelUsersInfo(userID).ChainExecDel(ctx)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Page Gets, returns no error if not found.
 | 
					// Page Gets, returns no error if not found.
 | 
				
			||||||
func (u *userDatabase) Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
 | 
					func (u *userDatabase) Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*model.User, err error) {
 | 
				
			||||||
	return u.userDB.Page(ctx, pagination)
 | 
						return u.userDB.Page(ctx, pagination)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (u *userDatabase) PageFindUser(ctx context.Context, level1 int64, level2 int64, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
 | 
					func (u *userDatabase) PageFindUser(ctx context.Context, level1 int64, level2 int64, pagination pagination.Pagination) (count int64, users []*model.User, err error) {
 | 
				
			||||||
	return u.userDB.PageFindUser(ctx, level1, level2, pagination)
 | 
						return u.userDB.PageFindUser(ctx, level1, level2, pagination)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (u *userDatabase) PageFindUserWithKeyword(ctx context.Context, level1 int64, level2 int64, userID, nickName string, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
 | 
					func (u *userDatabase) PageFindUserWithKeyword(ctx context.Context, level1 int64, level2 int64, userID, nickName string, pagination pagination.Pagination) (count int64, users []*model.User, err error) {
 | 
				
			||||||
	return u.userDB.PageFindUserWithKeyword(ctx, level1, level2, userID, nickName, pagination)
 | 
						return u.userDB.PageFindUserWithKeyword(ctx, level1, level2, userID, nickName, pagination)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -195,7 +196,7 @@ func (u *userDatabase) GetAllUserID(ctx context.Context, pagination pagination.P
 | 
				
			|||||||
	return u.userDB.GetAllUserID(ctx, pagination)
 | 
						return u.userDB.GetAllUserID(ctx, pagination)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (u *userDatabase) GetUserByID(ctx context.Context, userID string) (user *relation.UserModel, err error) {
 | 
					func (u *userDatabase) GetUserByID(ctx context.Context, userID string) (user *model.User, err error) {
 | 
				
			||||||
	return u.userDB.Take(ctx, userID)
 | 
						return u.userDB.Take(ctx, userID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -12,32 +12,20 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package relation
 | 
					package database
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"time"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/openimsdk/tools/db/pagination"
 | 
						"github.com/openimsdk/tools/db/pagination"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type BlackModel struct {
 | 
					type Black interface {
 | 
				
			||||||
	OwnerUserID    string    `bson:"owner_user_id"`
 | 
						Create(ctx context.Context, blacks []*model.Black) (err error)
 | 
				
			||||||
	BlockUserID    string    `bson:"block_user_id"`
 | 
						Delete(ctx context.Context, blacks []*model.Black) (err error)
 | 
				
			||||||
	CreateTime     time.Time `bson:"create_time"`
 | 
						Find(ctx context.Context, blacks []*model.Black) (blackList []*model.Black, err error)
 | 
				
			||||||
	AddSource      int32     `bson:"add_source"`
 | 
						Take(ctx context.Context, ownerUserID, blockUserID string) (black *model.Black, err error)
 | 
				
			||||||
	OperatorUserID string    `bson:"operator_user_id"`
 | 
						FindOwnerBlacks(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, blacks []*model.Black, err error)
 | 
				
			||||||
	Ex             string    `bson:"ex"`
 | 
						FindOwnerBlackInfos(ctx context.Context, ownerUserID string, userIDs []string) (blacks []*model.Black, err error)
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type BlackModelInterface interface {
 | 
					 | 
				
			||||||
	Create(ctx context.Context, blacks []*BlackModel) (err error)
 | 
					 | 
				
			||||||
	Delete(ctx context.Context, blacks []*BlackModel) (err error)
 | 
					 | 
				
			||||||
	// UpdateByMap(ctx context.Context, ownerUserID, blockUserID string, args map[string]any) (err error)
 | 
					 | 
				
			||||||
	// Update(ctx context.Context, blacks []*BlackModel) (err error)
 | 
					 | 
				
			||||||
	Find(ctx context.Context, blacks []*BlackModel) (blackList []*BlackModel, err error)
 | 
					 | 
				
			||||||
	Take(ctx context.Context, ownerUserID, blockUserID string) (black *BlackModel, err error)
 | 
					 | 
				
			||||||
	FindOwnerBlacks(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, blacks []*BlackModel, err error)
 | 
					 | 
				
			||||||
	FindOwnerBlackInfos(ctx context.Context, ownerUserID string, userIDs []string) (blacks []*BlackModel, err error)
 | 
					 | 
				
			||||||
	FindBlackUserIDs(ctx context.Context, ownerUserID string) (blackUserIDs []string, err error)
 | 
						FindBlackUserIDs(ctx context.Context, ownerUserID string) (blackUserIDs []string, err error)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -12,53 +12,31 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package relation
 | 
					package database
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"time"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/openimsdk/tools/db/pagination"
 | 
						"github.com/openimsdk/tools/db/pagination"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type ConversationModel struct {
 | 
					type Conversation interface {
 | 
				
			||||||
	OwnerUserID           string    `bson:"owner_user_id"`
 | 
						Create(ctx context.Context, conversations []*model.Conversation) (err error)
 | 
				
			||||||
	ConversationID        string    `bson:"conversation_id"`
 | 
					 | 
				
			||||||
	ConversationType      int32     `bson:"conversation_type"`
 | 
					 | 
				
			||||||
	UserID                string    `bson:"user_id"`
 | 
					 | 
				
			||||||
	GroupID               string    `bson:"group_id"`
 | 
					 | 
				
			||||||
	RecvMsgOpt            int32     `bson:"recv_msg_opt"`
 | 
					 | 
				
			||||||
	IsPinned              bool      `bson:"is_pinned"`
 | 
					 | 
				
			||||||
	IsPrivateChat         bool      `bson:"is_private_chat"`
 | 
					 | 
				
			||||||
	BurnDuration          int32     `bson:"burn_duration"`
 | 
					 | 
				
			||||||
	GroupAtType           int32     `bson:"group_at_type"`
 | 
					 | 
				
			||||||
	AttachedInfo          string    `bson:"attached_info"`
 | 
					 | 
				
			||||||
	Ex                    string    `bson:"ex"`
 | 
					 | 
				
			||||||
	MaxSeq                int64     `bson:"max_seq"`
 | 
					 | 
				
			||||||
	MinSeq                int64     `bson:"min_seq"`
 | 
					 | 
				
			||||||
	CreateTime            time.Time `bson:"create_time"`
 | 
					 | 
				
			||||||
	IsMsgDestruct         bool      `bson:"is_msg_destruct"`
 | 
					 | 
				
			||||||
	MsgDestructTime       int64     `bson:"msg_destruct_time"`
 | 
					 | 
				
			||||||
	LatestMsgDestructTime time.Time `bson:"latest_msg_destruct_time"`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type ConversationModelInterface interface {
 | 
					 | 
				
			||||||
	Create(ctx context.Context, conversations []*ConversationModel) (err error)
 | 
					 | 
				
			||||||
	Delete(ctx context.Context, groupIDs []string) (err error)
 | 
						Delete(ctx context.Context, groupIDs []string) (err error)
 | 
				
			||||||
	UpdateByMap(ctx context.Context, userIDs []string, conversationID string, args map[string]any) (rows int64, err error)
 | 
						UpdateByMap(ctx context.Context, userIDs []string, conversationID string, args map[string]any) (rows int64, err error)
 | 
				
			||||||
	Update(ctx context.Context, conversation *ConversationModel) (err error)
 | 
						Update(ctx context.Context, conversation *model.Conversation) (err error)
 | 
				
			||||||
	Find(ctx context.Context, ownerUserID string, conversationIDs []string) (conversations []*ConversationModel, err error)
 | 
						Find(ctx context.Context, ownerUserID string, conversationIDs []string) (conversations []*model.Conversation, err error)
 | 
				
			||||||
	FindUserID(ctx context.Context, userIDs []string, conversationIDs []string) ([]string, error)
 | 
						FindUserID(ctx context.Context, userIDs []string, conversationIDs []string) ([]string, error)
 | 
				
			||||||
	FindUserIDAllConversationID(ctx context.Context, userID string) ([]string, error)
 | 
						FindUserIDAllConversationID(ctx context.Context, userID string) ([]string, error)
 | 
				
			||||||
	Take(ctx context.Context, userID, conversationID string) (conversation *ConversationModel, err error)
 | 
						Take(ctx context.Context, userID, conversationID string) (conversation *model.Conversation, err error)
 | 
				
			||||||
	FindConversationID(ctx context.Context, userID string, conversationIDs []string) (existConversationID []string, err error)
 | 
						FindConversationID(ctx context.Context, userID string, conversationIDs []string) (existConversationID []string, err error)
 | 
				
			||||||
	FindUserIDAllConversations(ctx context.Context, userID string) (conversations []*ConversationModel, err error)
 | 
						FindUserIDAllConversations(ctx context.Context, userID string) (conversations []*model.Conversation, err error)
 | 
				
			||||||
	FindRecvMsgUserIDs(ctx context.Context, conversationID string, recvOpts []int) ([]string, error)
 | 
						FindRecvMsgUserIDs(ctx context.Context, conversationID string, recvOpts []int) ([]string, error)
 | 
				
			||||||
	GetUserRecvMsgOpt(ctx context.Context, ownerUserID, conversationID string) (opt int, err error)
 | 
						GetUserRecvMsgOpt(ctx context.Context, ownerUserID, conversationID string) (opt int, err error)
 | 
				
			||||||
	GetAllConversationIDs(ctx context.Context) ([]string, error)
 | 
						GetAllConversationIDs(ctx context.Context) ([]string, error)
 | 
				
			||||||
	GetAllConversationIDsNumber(ctx context.Context) (int64, error)
 | 
						GetAllConversationIDsNumber(ctx context.Context) (int64, error)
 | 
				
			||||||
	PageConversationIDs(ctx context.Context, pagination pagination.Pagination) (conversationIDs []string, err error)
 | 
						PageConversationIDs(ctx context.Context, pagination pagination.Pagination) (conversationIDs []string, err error)
 | 
				
			||||||
	GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*ConversationModel, error)
 | 
						GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*model.Conversation, error)
 | 
				
			||||||
	GetConversationIDsNeedDestruct(ctx context.Context) ([]*ConversationModel, error)
 | 
						GetConversationIDsNeedDestruct(ctx context.Context) ([]*model.Conversation, error)
 | 
				
			||||||
	GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error)
 | 
						GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										15
									
								
								pkg/common/storage/database/doc.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								pkg/common/storage/database/doc.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					// Copyright © 2024 OpenIM. All rights reserved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package database // import "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model/relation"
 | 
				
			||||||
@ -12,31 +12,18 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package relation
 | 
					package database
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"time"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/openimsdk/tools/db/pagination"
 | 
						"github.com/openimsdk/tools/db/pagination"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// FriendModel represents the data structure for a friend relationship in MongoDB.
 | 
					// Friend defines the operations for managing friends in MongoDB.
 | 
				
			||||||
type FriendModel struct {
 | 
					type Friend interface {
 | 
				
			||||||
	OwnerUserID    string    `bson:"owner_user_id"`
 | 
					 | 
				
			||||||
	FriendUserID   string    `bson:"friend_user_id"`
 | 
					 | 
				
			||||||
	Remark         string    `bson:"remark"`
 | 
					 | 
				
			||||||
	CreateTime     time.Time `bson:"create_time"`
 | 
					 | 
				
			||||||
	AddSource      int32     `bson:"add_source"`
 | 
					 | 
				
			||||||
	OperatorUserID string    `bson:"operator_user_id"`
 | 
					 | 
				
			||||||
	Ex             string    `bson:"ex"`
 | 
					 | 
				
			||||||
	IsPinned       bool      `bson:"is_pinned"`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// FriendModelInterface defines the operations for managing friends in MongoDB.
 | 
					 | 
				
			||||||
type FriendModelInterface interface {
 | 
					 | 
				
			||||||
	// Create inserts multiple friend records.
 | 
						// Create inserts multiple friend records.
 | 
				
			||||||
	Create(ctx context.Context, friends []*FriendModel) (err error)
 | 
						Create(ctx context.Context, friends []*model.Friend) (err error)
 | 
				
			||||||
	// Delete removes specified friends of the owner user.
 | 
						// Delete removes specified friends of the owner user.
 | 
				
			||||||
	Delete(ctx context.Context, ownerUserID string, friendUserIDs []string) (err error)
 | 
						Delete(ctx context.Context, ownerUserID string, friendUserIDs []string) (err error)
 | 
				
			||||||
	// UpdateByMap updates specific fields of a friend document using a map.
 | 
						// UpdateByMap updates specific fields of a friend document using a map.
 | 
				
			||||||
@ -44,17 +31,17 @@ type FriendModelInterface interface {
 | 
				
			|||||||
	// UpdateRemark modify remarks.
 | 
						// UpdateRemark modify remarks.
 | 
				
			||||||
	UpdateRemark(ctx context.Context, ownerUserID, friendUserID, remark string) (err error)
 | 
						UpdateRemark(ctx context.Context, ownerUserID, friendUserID, remark string) (err error)
 | 
				
			||||||
	// Take retrieves a single friend document. Returns an error if not found.
 | 
						// Take retrieves a single friend document. Returns an error if not found.
 | 
				
			||||||
	Take(ctx context.Context, ownerUserID, friendUserID string) (friend *FriendModel, err error)
 | 
						Take(ctx context.Context, ownerUserID, friendUserID string) (friend *model.Friend, err error)
 | 
				
			||||||
	// FindUserState finds the friendship status between two users.
 | 
						// FindUserState finds the friendship status between two users.
 | 
				
			||||||
	FindUserState(ctx context.Context, userID1, userID2 string) (friends []*FriendModel, err error)
 | 
						FindUserState(ctx context.Context, userID1, userID2 string) (friends []*model.Friend, err error)
 | 
				
			||||||
	// FindFriends retrieves a list of friends for a given owner. Missing friends do not cause an error.
 | 
						// FindFriends retrieves a list of friends for a given owner. Missing friends do not cause an error.
 | 
				
			||||||
	FindFriends(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*FriendModel, err error)
 | 
						FindFriends(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*model.Friend, err error)
 | 
				
			||||||
	// FindReversalFriends finds users who have added the specified user as a friend.
 | 
						// FindReversalFriends finds users who have added the specified user as a friend.
 | 
				
			||||||
	FindReversalFriends(ctx context.Context, friendUserID string, ownerUserIDs []string) (friends []*FriendModel, err error)
 | 
						FindReversalFriends(ctx context.Context, friendUserID string, ownerUserIDs []string) (friends []*model.Friend, err error)
 | 
				
			||||||
	// FindOwnerFriends retrieves a paginated list of friends for a given owner.
 | 
						// FindOwnerFriends retrieves a paginated list of friends for a given owner.
 | 
				
			||||||
	FindOwnerFriends(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, friends []*FriendModel, err error)
 | 
						FindOwnerFriends(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, friends []*model.Friend, err error)
 | 
				
			||||||
	// FindInWhoseFriends finds users who have added the specified user as a friend, with pagination.
 | 
						// FindInWhoseFriends finds users who have added the specified user as a friend, with pagination.
 | 
				
			||||||
	FindInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (total int64, friends []*FriendModel, err error)
 | 
						FindInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (total int64, friends []*model.Friend, err error)
 | 
				
			||||||
	// FindFriendUserIDs retrieves a list of friend user IDs for a given owner.
 | 
						// FindFriendUserIDs retrieves a list of friend user IDs for a given owner.
 | 
				
			||||||
	FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error)
 | 
						FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error)
 | 
				
			||||||
	// UpdateFriends update friends' fields
 | 
						// UpdateFriends update friends' fields
 | 
				
			||||||
@ -12,42 +12,29 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package relation
 | 
					package database
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"time"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/openimsdk/tools/db/pagination"
 | 
						"github.com/openimsdk/tools/db/pagination"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type FriendRequestModel struct {
 | 
					type FriendRequest interface {
 | 
				
			||||||
	FromUserID    string    `bson:"from_user_id"`
 | 
					 | 
				
			||||||
	ToUserID      string    `bson:"to_user_id"`
 | 
					 | 
				
			||||||
	HandleResult  int32     `bson:"handle_result"`
 | 
					 | 
				
			||||||
	ReqMsg        string    `bson:"req_msg"`
 | 
					 | 
				
			||||||
	CreateTime    time.Time `bson:"create_time"`
 | 
					 | 
				
			||||||
	HandlerUserID string    `bson:"handler_user_id"`
 | 
					 | 
				
			||||||
	HandleMsg     string    `bson:"handle_msg"`
 | 
					 | 
				
			||||||
	HandleTime    time.Time `bson:"handle_time"`
 | 
					 | 
				
			||||||
	Ex            string    `bson:"ex"`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type FriendRequestModelInterface interface {
 | 
					 | 
				
			||||||
	// Insert multiple records
 | 
						// Insert multiple records
 | 
				
			||||||
	Create(ctx context.Context, friendRequests []*FriendRequestModel) (err error)
 | 
						Create(ctx context.Context, friendRequests []*model.FriendRequest) (err error)
 | 
				
			||||||
	// Delete record
 | 
						// Delete record
 | 
				
			||||||
	Delete(ctx context.Context, fromUserID, toUserID string) (err error)
 | 
						Delete(ctx context.Context, fromUserID, toUserID string) (err error)
 | 
				
			||||||
	// Update with zero values
 | 
						// Update with zero values
 | 
				
			||||||
	UpdateByMap(ctx context.Context, formUserID string, toUserID string, args map[string]any) (err error)
 | 
						UpdateByMap(ctx context.Context, formUserID string, toUserID string, args map[string]any) (err error)
 | 
				
			||||||
	// Update multiple records (non-zero values)
 | 
						// Update multiple records (non-zero values)
 | 
				
			||||||
	Update(ctx context.Context, friendRequest *FriendRequestModel) (err error)
 | 
						Update(ctx context.Context, friendRequest *model.FriendRequest) (err error)
 | 
				
			||||||
	// Get friend requests sent to a specific user, no error returned if not found
 | 
						// Get friend requests sent to a specific user, no error returned if not found
 | 
				
			||||||
	Find(ctx context.Context, fromUserID, toUserID string) (friendRequest *FriendRequestModel, err error)
 | 
						Find(ctx context.Context, fromUserID, toUserID string) (friendRequest *model.FriendRequest, err error)
 | 
				
			||||||
	Take(ctx context.Context, fromUserID, toUserID string) (friendRequest *FriendRequestModel, err error)
 | 
						Take(ctx context.Context, fromUserID, toUserID string) (friendRequest *model.FriendRequest, err error)
 | 
				
			||||||
	// Get list of friend requests received by toUserID
 | 
						// Get list of friend requests received by toUserID
 | 
				
			||||||
	FindToUserID(ctx context.Context, toUserID string, pagination pagination.Pagination) (total int64, friendRequests []*FriendRequestModel, err error)
 | 
						FindToUserID(ctx context.Context, toUserID string, pagination pagination.Pagination) (total int64, friendRequests []*model.FriendRequest, err error)
 | 
				
			||||||
	// Get list of friend requests sent by fromUserID
 | 
						// Get list of friend requests sent by fromUserID
 | 
				
			||||||
	FindFromUserID(ctx context.Context, fromUserID string, pagination pagination.Pagination) (total int64, friendRequests []*FriendRequestModel, err error)
 | 
						FindFromUserID(ctx context.Context, fromUserID string, pagination pagination.Pagination) (total int64, friendRequests []*model.FriendRequest, err error)
 | 
				
			||||||
	FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*FriendRequestModel, err error)
 | 
						FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*model.FriendRequest, err error)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										35
									
								
								pkg/common/storage/database/group.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								pkg/common/storage/database/group.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					// Copyright © 2023 OpenIM. All rights reserved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package database
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
 | 
						"github.com/openimsdk/tools/db/pagination"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Group interface {
 | 
				
			||||||
 | 
						Create(ctx context.Context, groups []*model.Group) (err error)
 | 
				
			||||||
 | 
						UpdateMap(ctx context.Context, groupID string, args map[string]any) (err error)
 | 
				
			||||||
 | 
						UpdateStatus(ctx context.Context, groupID string, status int32) (err error)
 | 
				
			||||||
 | 
						Find(ctx context.Context, groupIDs []string) (groups []*model.Group, err error)
 | 
				
			||||||
 | 
						Take(ctx context.Context, groupID string) (group *model.Group, err error)
 | 
				
			||||||
 | 
						Search(ctx context.Context, keyword string, pagination pagination.Pagination) (total int64, groups []*model.Group, err error)
 | 
				
			||||||
 | 
						// Get Group total quantity
 | 
				
			||||||
 | 
						CountTotal(ctx context.Context, before *time.Time) (count int64, err error)
 | 
				
			||||||
 | 
						// Get Group total quantity every day
 | 
				
			||||||
 | 
						CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -12,46 +12,26 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package relation
 | 
					package database
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"time"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/openimsdk/tools/db/pagination"
 | 
						"github.com/openimsdk/tools/db/pagination"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type GroupMemberModel struct {
 | 
					type GroupMember interface {
 | 
				
			||||||
	GroupID        string    `bson:"group_id"`
 | 
						Create(ctx context.Context, groupMembers []*model.GroupMember) (err error)
 | 
				
			||||||
	UserID         string    `bson:"user_id"`
 | 
					 | 
				
			||||||
	Nickname       string    `bson:"nickname"`
 | 
					 | 
				
			||||||
	FaceURL        string    `bson:"face_url"`
 | 
					 | 
				
			||||||
	RoleLevel      int32     `bson:"role_level"`
 | 
					 | 
				
			||||||
	JoinTime       time.Time `bson:"join_time"`
 | 
					 | 
				
			||||||
	JoinSource     int32     `bson:"join_source"`
 | 
					 | 
				
			||||||
	InviterUserID  string    `bson:"inviter_user_id"`
 | 
					 | 
				
			||||||
	OperatorUserID string    `bson:"operator_user_id"`
 | 
					 | 
				
			||||||
	MuteEndTime    time.Time `bson:"mute_end_time"`
 | 
					 | 
				
			||||||
	Ex             string    `bson:"ex"`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type GroupMemberModelInterface interface {
 | 
					 | 
				
			||||||
	// NewTx(tx any) GroupMemberModelInterface
 | 
					 | 
				
			||||||
	Create(ctx context.Context, groupMembers []*GroupMemberModel) (err error)
 | 
					 | 
				
			||||||
	Delete(ctx context.Context, groupID string, userIDs []string) (err error)
 | 
						Delete(ctx context.Context, groupID string, userIDs []string) (err error)
 | 
				
			||||||
	// DeleteGroup(ctx context.Context, groupIDs []string) (err error)
 | 
					 | 
				
			||||||
	Update(ctx context.Context, groupID string, userID string, data map[string]any) (err error)
 | 
						Update(ctx context.Context, groupID string, userID string, data map[string]any) (err error)
 | 
				
			||||||
	UpdateRoleLevel(ctx context.Context, groupID string, userID string, roleLevel int32) error
 | 
						UpdateRoleLevel(ctx context.Context, groupID string, userID string, roleLevel int32) error
 | 
				
			||||||
	FindMemberUserID(ctx context.Context, groupID string) (userIDs []string, err error)
 | 
						FindMemberUserID(ctx context.Context, groupID string) (userIDs []string, err error)
 | 
				
			||||||
	Take(ctx context.Context, groupID string, userID string) (groupMember *GroupMemberModel, err error)
 | 
						Take(ctx context.Context, groupID string, userID string) (groupMember *model.GroupMember, err error)
 | 
				
			||||||
	TakeOwner(ctx context.Context, groupID string) (groupMember *GroupMemberModel, err error)
 | 
						TakeOwner(ctx context.Context, groupID string) (groupMember *model.GroupMember, err error)
 | 
				
			||||||
	SearchMember(ctx context.Context, keyword string, groupID string, pagination pagination.Pagination) (total int64, groupList []*GroupMemberModel, err error)
 | 
						SearchMember(ctx context.Context, keyword string, groupID string, pagination pagination.Pagination) (total int64, groupList []*model.GroupMember, err error)
 | 
				
			||||||
	FindRoleLevelUserIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error)
 | 
						FindRoleLevelUserIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error)
 | 
				
			||||||
	// MapGroupMemberNum(ctx context.Context, groupIDs []string) (count map[string]uint32, err error)
 | 
					 | 
				
			||||||
	// FindJoinUserID(ctx context.Context, groupIDs []string) (groupUsers map[string][]string, err error)
 | 
					 | 
				
			||||||
	FindUserJoinedGroupID(ctx context.Context, userID string) (groupIDs []string, err error)
 | 
						FindUserJoinedGroupID(ctx context.Context, userID string) (groupIDs []string, err error)
 | 
				
			||||||
	TakeGroupMemberNum(ctx context.Context, groupID string) (count int64, err error)
 | 
						TakeGroupMemberNum(ctx context.Context, groupID string) (count int64, err error)
 | 
				
			||||||
	// FindUsersJoinedGroupID(ctx context.Context, userIDs []string) (map[string][]string, error)
 | 
					 | 
				
			||||||
	FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error)
 | 
						FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error)
 | 
				
			||||||
	IsUpdateRoleLevel(data map[string]any) bool
 | 
						IsUpdateRoleLevel(data map[string]any) bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -12,35 +12,20 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package relation
 | 
					package database
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"time"
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/openimsdk/tools/db/pagination"
 | 
						"github.com/openimsdk/tools/db/pagination"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type GroupRequestModel struct {
 | 
					type GroupRequest interface {
 | 
				
			||||||
	UserID        string    `bson:"user_id"`
 | 
						Create(ctx context.Context, groupRequests []*model.GroupRequest) (err error)
 | 
				
			||||||
	GroupID       string    `bson:"group_id"`
 | 
					 | 
				
			||||||
	HandleResult  int32     `bson:"handle_result"`
 | 
					 | 
				
			||||||
	ReqMsg        string    `bson:"req_msg"`
 | 
					 | 
				
			||||||
	HandledMsg    string    `bson:"handled_msg"`
 | 
					 | 
				
			||||||
	ReqTime       time.Time `bson:"req_time"`
 | 
					 | 
				
			||||||
	HandleUserID  string    `bson:"handle_user_id"`
 | 
					 | 
				
			||||||
	HandledTime   time.Time `bson:"handled_time"`
 | 
					 | 
				
			||||||
	JoinSource    int32     `bson:"join_source"`
 | 
					 | 
				
			||||||
	InviterUserID string    `bson:"inviter_user_id"`
 | 
					 | 
				
			||||||
	Ex            string    `bson:"ex"`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type GroupRequestModelInterface interface {
 | 
					 | 
				
			||||||
	Create(ctx context.Context, groupRequests []*GroupRequestModel) (err error)
 | 
					 | 
				
			||||||
	Delete(ctx context.Context, groupID string, userID string) (err error)
 | 
						Delete(ctx context.Context, groupID string, userID string) (err error)
 | 
				
			||||||
	UpdateHandler(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32) (err error)
 | 
						UpdateHandler(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32) (err error)
 | 
				
			||||||
	Take(ctx context.Context, groupID string, userID string) (groupRequest *GroupRequestModel, err error)
 | 
						Take(ctx context.Context, groupID string, userID string) (groupRequest *model.GroupRequest, err error)
 | 
				
			||||||
	FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*GroupRequestModel, error)
 | 
						FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*model.GroupRequest, error)
 | 
				
			||||||
	Page(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, groups []*GroupRequestModel, err error)
 | 
						Page(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error)
 | 
				
			||||||
	PageGroup(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (total int64, groups []*GroupRequestModel, err error)
 | 
						PageGroup(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										29
									
								
								pkg/common/storage/database/log.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								pkg/common/storage/database/log.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					// Copyright © 2023 OpenIM. All rights reserved.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package database
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
 | 
						"github.com/openimsdk/tools/db/pagination"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Log interface {
 | 
				
			||||||
 | 
						Create(ctx context.Context, log []*model.Log) error
 | 
				
			||||||
 | 
						Search(ctx context.Context, keyword string, start time.Time, end time.Time, pagination pagination.Pagination) (int64, []*model.Log, error)
 | 
				
			||||||
 | 
						Delete(ctx context.Context, logID []string, userID string) error
 | 
				
			||||||
 | 
						Get(ctx context.Context, logIDs []string, userID string) ([]*model.Log, error)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -16,8 +16,9 @@ package mgo
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/tools/db/mongoutil"
 | 
						"github.com/openimsdk/tools/db/mongoutil"
 | 
				
			||||||
	"github.com/openimsdk/tools/db/pagination"
 | 
						"github.com/openimsdk/tools/db/pagination"
 | 
				
			||||||
	"go.mongodb.org/mongo-driver/bson"
 | 
						"go.mongodb.org/mongo-driver/bson"
 | 
				
			||||||
@ -25,7 +26,7 @@ import (
 | 
				
			|||||||
	"go.mongodb.org/mongo-driver/mongo/options"
 | 
						"go.mongodb.org/mongo-driver/mongo/options"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewBlackMongo(db *mongo.Database) (relation.BlackModelInterface, error) {
 | 
					func NewBlackMongo(db *mongo.Database) (database.Black, error) {
 | 
				
			||||||
	coll := db.Collection("black")
 | 
						coll := db.Collection("black")
 | 
				
			||||||
	_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
 | 
						_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
 | 
				
			||||||
		Keys: bson.D{
 | 
							Keys: bson.D{
 | 
				
			||||||
@ -51,7 +52,7 @@ func (b *BlackMgo) blackFilter(ownerUserID, blockUserID string) bson.M {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (b *BlackMgo) blacksFilter(blacks []*relation.BlackModel) bson.M {
 | 
					func (b *BlackMgo) blacksFilter(blacks []*model.Black) bson.M {
 | 
				
			||||||
	if len(blacks) == 0 {
 | 
						if len(blacks) == 0 {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -62,11 +63,11 @@ func (b *BlackMgo) blacksFilter(blacks []*relation.BlackModel) bson.M {
 | 
				
			|||||||
	return bson.M{"$or": or}
 | 
						return bson.M{"$or": or}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (b *BlackMgo) Create(ctx context.Context, blacks []*relation.BlackModel) (err error) {
 | 
					func (b *BlackMgo) Create(ctx context.Context, blacks []*model.Black) (err error) {
 | 
				
			||||||
	return mongoutil.InsertMany(ctx, b.coll, blacks)
 | 
						return mongoutil.InsertMany(ctx, b.coll, blacks)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (b *BlackMgo) Delete(ctx context.Context, blacks []*relation.BlackModel) (err error) {
 | 
					func (b *BlackMgo) Delete(ctx context.Context, blacks []*model.Black) (err error) {
 | 
				
			||||||
	if len(blacks) == 0 {
 | 
						if len(blacks) == 0 {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -80,23 +81,23 @@ func (b *BlackMgo) UpdateByMap(ctx context.Context, ownerUserID, blockUserID str
 | 
				
			|||||||
	return mongoutil.UpdateOne(ctx, b.coll, b.blackFilter(ownerUserID, blockUserID), bson.M{"$set": args}, false)
 | 
						return mongoutil.UpdateOne(ctx, b.coll, b.blackFilter(ownerUserID, blockUserID), bson.M{"$set": args}, false)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (b *BlackMgo) Find(ctx context.Context, blacks []*relation.BlackModel) (blackList []*relation.BlackModel, err error) {
 | 
					func (b *BlackMgo) Find(ctx context.Context, blacks []*model.Black) (blackList []*model.Black, err error) {
 | 
				
			||||||
	return mongoutil.Find[*relation.BlackModel](ctx, b.coll, b.blacksFilter(blacks))
 | 
						return mongoutil.Find[*model.Black](ctx, b.coll, b.blacksFilter(blacks))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (b *BlackMgo) Take(ctx context.Context, ownerUserID, blockUserID string) (black *relation.BlackModel, err error) {
 | 
					func (b *BlackMgo) Take(ctx context.Context, ownerUserID, blockUserID string) (black *model.Black, err error) {
 | 
				
			||||||
	return mongoutil.FindOne[*relation.BlackModel](ctx, b.coll, b.blackFilter(ownerUserID, blockUserID))
 | 
						return mongoutil.FindOne[*model.Black](ctx, b.coll, b.blackFilter(ownerUserID, blockUserID))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (b *BlackMgo) FindOwnerBlacks(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, blacks []*relation.BlackModel, err error) {
 | 
					func (b *BlackMgo) FindOwnerBlacks(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, blacks []*model.Black, err error) {
 | 
				
			||||||
	return mongoutil.FindPage[*relation.BlackModel](ctx, b.coll, bson.M{"owner_user_id": ownerUserID}, pagination)
 | 
						return mongoutil.FindPage[*model.Black](ctx, b.coll, bson.M{"owner_user_id": ownerUserID}, pagination)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (b *BlackMgo) FindOwnerBlackInfos(ctx context.Context, ownerUserID string, userIDs []string) (blacks []*relation.BlackModel, err error) {
 | 
					func (b *BlackMgo) FindOwnerBlackInfos(ctx context.Context, ownerUserID string, userIDs []string) (blacks []*model.Black, err error) {
 | 
				
			||||||
	if len(userIDs) == 0 {
 | 
						if len(userIDs) == 0 {
 | 
				
			||||||
		return mongoutil.Find[*relation.BlackModel](ctx, b.coll, bson.M{"owner_user_id": ownerUserID})
 | 
							return mongoutil.Find[*model.Black](ctx, b.coll, bson.M{"owner_user_id": ownerUserID})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return mongoutil.Find[*relation.BlackModel](ctx, b.coll, bson.M{"owner_user_id": ownerUserID, "block_user_id": bson.M{"$in": userIDs}})
 | 
						return mongoutil.Find[*model.Black](ctx, b.coll, bson.M{"owner_user_id": ownerUserID, "block_user_id": bson.M{"$in": userIDs}})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (b *BlackMgo) FindBlackUserIDs(ctx context.Context, ownerUserID string) (blackUserIDs []string, err error) {
 | 
					func (b *BlackMgo) FindBlackUserIDs(ctx context.Context, ownerUserID string) (blackUserIDs []string, err error) {
 | 
				
			||||||
@ -16,9 +16,9 @@ package mgo
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
 | 
					 | 
				
			||||||
	"github.com/openimsdk/protocol/constant"
 | 
						"github.com/openimsdk/protocol/constant"
 | 
				
			||||||
	"github.com/openimsdk/tools/db/mongoutil"
 | 
						"github.com/openimsdk/tools/db/mongoutil"
 | 
				
			||||||
	"github.com/openimsdk/tools/db/pagination"
 | 
						"github.com/openimsdk/tools/db/pagination"
 | 
				
			||||||
@ -47,7 +47,7 @@ type ConversationMgo struct {
 | 
				
			|||||||
	coll *mongo.Collection
 | 
						coll *mongo.Collection
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *ConversationMgo) Create(ctx context.Context, conversations []*relation.ConversationModel) (err error) {
 | 
					func (c *ConversationMgo) Create(ctx context.Context, conversations []*model.Conversation) (err error) {
 | 
				
			||||||
	return mongoutil.InsertMany(ctx, c.coll, conversations)
 | 
						return mongoutil.InsertMany(ctx, c.coll, conversations)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -72,12 +72,12 @@ func (c *ConversationMgo) UpdateByMap(ctx context.Context, userIDs []string, con
 | 
				
			|||||||
	return res.ModifiedCount, nil
 | 
						return res.ModifiedCount, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *ConversationMgo) Update(ctx context.Context, conversation *relation.ConversationModel) (err error) {
 | 
					func (c *ConversationMgo) Update(ctx context.Context, conversation *model.Conversation) (err error) {
 | 
				
			||||||
	return mongoutil.UpdateOne(ctx, c.coll, bson.M{"owner_user_id": conversation.OwnerUserID, "conversation_id": conversation.ConversationID}, bson.M{"$set": conversation}, true)
 | 
						return mongoutil.UpdateOne(ctx, c.coll, bson.M{"owner_user_id": conversation.OwnerUserID, "conversation_id": conversation.ConversationID}, bson.M{"$set": conversation}, true)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *ConversationMgo) Find(ctx context.Context, ownerUserID string, conversationIDs []string) (conversations []*relation.ConversationModel, err error) {
 | 
					func (c *ConversationMgo) Find(ctx context.Context, ownerUserID string, conversationIDs []string) (conversations []*model.Conversation, err error) {
 | 
				
			||||||
	return mongoutil.Find[*relation.ConversationModel](ctx, c.coll, bson.M{"owner_user_id": ownerUserID, "conversation_id": bson.M{"$in": conversationIDs}})
 | 
						return mongoutil.Find[*model.Conversation](ctx, c.coll, bson.M{"owner_user_id": ownerUserID, "conversation_id": bson.M{"$in": conversationIDs}})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *ConversationMgo) FindUserID(ctx context.Context, userIDs []string, conversationIDs []string) ([]string, error) {
 | 
					func (c *ConversationMgo) FindUserID(ctx context.Context, userIDs []string, conversationIDs []string) ([]string, error) {
 | 
				
			||||||
@ -92,16 +92,16 @@ func (c *ConversationMgo) FindUserIDAllConversationID(ctx context.Context, userI
 | 
				
			|||||||
	return mongoutil.Find[string](ctx, c.coll, bson.M{"owner_user_id": userID}, options.Find().SetProjection(bson.M{"_id": 0, "conversation_id": 1}))
 | 
						return mongoutil.Find[string](ctx, c.coll, bson.M{"owner_user_id": userID}, options.Find().SetProjection(bson.M{"_id": 0, "conversation_id": 1}))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *ConversationMgo) Take(ctx context.Context, userID, conversationID string) (conversation *relation.ConversationModel, err error) {
 | 
					func (c *ConversationMgo) Take(ctx context.Context, userID, conversationID string) (conversation *model.Conversation, err error) {
 | 
				
			||||||
	return mongoutil.FindOne[*relation.ConversationModel](ctx, c.coll, bson.M{"owner_user_id": userID, "conversation_id": conversationID})
 | 
						return mongoutil.FindOne[*model.Conversation](ctx, c.coll, bson.M{"owner_user_id": userID, "conversation_id": conversationID})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *ConversationMgo) FindConversationID(ctx context.Context, userID string, conversationIDs []string) (existConversationID []string, err error) {
 | 
					func (c *ConversationMgo) FindConversationID(ctx context.Context, userID string, conversationIDs []string) (existConversationID []string, err error) {
 | 
				
			||||||
	return mongoutil.Find[string](ctx, c.coll, bson.M{"owner_user_id": userID, "conversation_id": bson.M{"$in": conversationIDs}}, options.Find().SetProjection(bson.M{"_id": 0, "conversation_id": 1}))
 | 
						return mongoutil.Find[string](ctx, c.coll, bson.M{"owner_user_id": userID, "conversation_id": bson.M{"$in": conversationIDs}}, options.Find().SetProjection(bson.M{"_id": 0, "conversation_id": 1}))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *ConversationMgo) FindUserIDAllConversations(ctx context.Context, userID string) (conversations []*relation.ConversationModel, err error) {
 | 
					func (c *ConversationMgo) FindUserIDAllConversations(ctx context.Context, userID string) (conversations []*model.Conversation, err error) {
 | 
				
			||||||
	return mongoutil.Find[*relation.ConversationModel](ctx, c.coll, bson.M{"owner_user_id": userID})
 | 
						return mongoutil.Find[*model.Conversation](ctx, c.coll, bson.M{"owner_user_id": userID})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *ConversationMgo) FindRecvMsgUserIDs(ctx context.Context, conversationID string, recvOpts []int) ([]string, error) {
 | 
					func (c *ConversationMgo) FindRecvMsgUserIDs(ctx context.Context, conversationID string, recvOpts []int) ([]string, error) {
 | 
				
			||||||
@ -144,13 +144,13 @@ func (c *ConversationMgo) PageConversationIDs(ctx context.Context, pagination pa
 | 
				
			|||||||
	return mongoutil.FindPageOnly[string](ctx, c.coll, bson.M{}, pagination, options.Find().SetProjection(bson.M{"conversation_id": 1}))
 | 
						return mongoutil.FindPageOnly[string](ctx, c.coll, bson.M{}, pagination, options.Find().SetProjection(bson.M{"conversation_id": 1}))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *ConversationMgo) GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*relation.ConversationModel, error) {
 | 
					func (c *ConversationMgo) GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*model.Conversation, error) {
 | 
				
			||||||
	return mongoutil.Find[*relation.ConversationModel](ctx, c.coll, bson.M{"conversation_id": bson.M{"$in": conversationIDs}})
 | 
						return mongoutil.Find[*model.Conversation](ctx, c.coll, bson.M{"conversation_id": bson.M{"$in": conversationIDs}})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *ConversationMgo) GetConversationIDsNeedDestruct(ctx context.Context) ([]*relation.ConversationModel, error) {
 | 
					func (c *ConversationMgo) GetConversationIDsNeedDestruct(ctx context.Context) ([]*model.Conversation, error) {
 | 
				
			||||||
	// "is_msg_destruct = 1 && msg_destruct_time != 0 && (UNIX_TIMESTAMP(NOW()) > (msg_destruct_time + UNIX_TIMESTAMP(latest_msg_destruct_time)) || latest_msg_destruct_time is NULL)"
 | 
						// "is_msg_destruct = 1 && msg_destruct_time != 0 && (UNIX_TIMESTAMP(NOW()) > (msg_destruct_time + UNIX_TIMESTAMP(latest_msg_destruct_time)) || latest_msg_destruct_time is NULL)"
 | 
				
			||||||
	return mongoutil.Find[*relation.ConversationModel](ctx, c.coll, bson.M{
 | 
						return mongoutil.Find[*model.Conversation](ctx, c.coll, bson.M{
 | 
				
			||||||
		"is_msg_destruct":   1,
 | 
							"is_msg_destruct":   1,
 | 
				
			||||||
		"msg_destruct_time": bson.M{"$ne": 0},
 | 
							"msg_destruct_time": bson.M{"$ne": 0},
 | 
				
			||||||
		"$or": []bson.M{
 | 
							"$or": []bson.M{
 | 
				
			||||||
@ -12,4 +12,4 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package mgo // import "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
 | 
					package mgo // import "github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user