From 4c3c4555a35ec8e31ffbf3e96a5dba3bceec09ee Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Thu, 11 Jan 2024 11:18:52 +0800 Subject: [PATCH 01/27] fix: GroupApplicationAcceptedNotification --- pkg/rpcclient/notification/group.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/rpcclient/notification/group.go b/pkg/rpcclient/notification/group.go index cbae7c49b2..f2413143d8 100755 --- a/pkg/rpcclient/notification/group.go +++ b/pkg/rpcclient/notification/group.go @@ -413,7 +413,7 @@ func (g *GroupNotificationSender) GroupApplicationAcceptedNotification(ctx conte if err := g.fillOpUser(ctx, &tips.OpUser, tips.Group.GroupID); err != nil { return err } - for _, userID := range append(userIDs, mcontext.GetOpUserID(ctx)) { + for _, userID := range append(userIDs, req.FromUserID) { err = g.Notification(ctx, mcontext.GetOpUserID(ctx), userID, constant.GroupApplicationAcceptedNotification, tips) if err != nil { log.ZError(ctx, "failed", err) @@ -441,7 +441,7 @@ func (g *GroupNotificationSender) GroupApplicationRejectedNotification(ctx conte if err := g.fillOpUser(ctx, &tips.OpUser, tips.Group.GroupID); err != nil { return err } - for _, userID := range append(userIDs, mcontext.GetOpUserID(ctx)) { + for _, userID := range append(userIDs, req.FromUserID) { err = g.Notification(ctx, mcontext.GetOpUserID(ctx), userID, constant.GroupApplicationRejectedNotification, tips) if err != nil { log.ZError(ctx, "failed", err) From a00d77a7053c3f9999952337490f0493b4865c49 Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Thu, 11 Jan 2024 16:31:24 +0800 Subject: [PATCH 02/27] fix: GroupApplicationAcceptedNotification --- pkg/rpcclient/notification/group.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/pkg/rpcclient/notification/group.go b/pkg/rpcclient/notification/group.go index f2413143d8..8c3719b2c1 100755 --- a/pkg/rpcclient/notification/group.go +++ b/pkg/rpcclient/notification/group.go @@ -409,11 +409,16 @@ func (g *GroupNotificationSender) GroupApplicationAcceptedNotification(ctx conte if err != nil { return err } - tips := &sdkws.GroupApplicationAcceptedTips{Group: group, HandleMsg: req.HandledMsg, ReceiverAs: 1} + tips := &sdkws.GroupApplicationAcceptedTips{Group: group, HandleMsg: req.HandledMsg} if err := g.fillOpUser(ctx, &tips.OpUser, tips.Group.GroupID); err != nil { return err } for _, userID := range append(userIDs, req.FromUserID) { + if userID == req.FromUserID { + tips.ReceiverAs = 0 + } else { + tips.ReceiverAs = 1 + } err = g.Notification(ctx, mcontext.GetOpUserID(ctx), userID, constant.GroupApplicationAcceptedNotification, tips) if err != nil { log.ZError(ctx, "failed", err) @@ -442,6 +447,11 @@ func (g *GroupNotificationSender) GroupApplicationRejectedNotification(ctx conte return err } for _, userID := range append(userIDs, req.FromUserID) { + if userID == req.FromUserID { + tips.ReceiverAs = 0 + } else { + tips.ReceiverAs = 1 + } err = g.Notification(ctx, mcontext.GetOpUserID(ctx), userID, constant.GroupApplicationRejectedNotification, tips) if err != nil { log.ZError(ctx, "failed", err) From 48ff03f854e48fd22819c818586c6385d899a3c1 Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Fri, 12 Jan 2024 11:01:28 +0800 Subject: [PATCH 03/27] fix: NotificationUserInfoUpdate --- internal/rpc/group/group.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/internal/rpc/group/group.go b/internal/rpc/group/group.go index f9b73ad2b3..abc271651f 100644 --- a/internal/rpc/group/group.go +++ b/internal/rpc/group/group.go @@ -109,14 +109,11 @@ type groupServer struct { } func (s *groupServer) NotificationUserInfoUpdate(ctx context.Context, req *pbgroup.NotificationUserInfoUpdateReq) (*pbgroup.NotificationUserInfoUpdateResp, error) { - defer log.ZDebug(ctx, "return") + defer log.ZDebug(ctx, "NotificationUserInfoUpdate return") members, err := s.db.FindGroupMemberUser(ctx, nil, req.UserID) if err != nil { return nil, err } - if err := s.PopulateGroupMember(ctx, members...); err != nil { - return nil, err - } groupIDs := make([]string, 0, len(members)) for _, member := range members { if member.Nickname != "" && member.FaceURL != "" { From 4266fed44f9f8dc9002634cb6cc6860a7d9f7434 Mon Sep 17 00:00:00 2001 From: withchao Date: Mon, 22 Jan 2024 03:13:27 +0000 Subject: [PATCH 04/27] cicd: robot automated Change --- go.mod | 2 +- go.sum | 4 ++-- internal/msggateway/n_ws_server.go | 3 ++- internal/push/push_rpc_server.go | 3 ++- internal/push/push_to_client.go | 3 ++- internal/rpc/conversation/conversaion.go | 3 ++- internal/rpc/msg/as_read.go | 1 + internal/rpc/msg/seq.go | 1 + internal/rpc/third/s3.go | 6 ++++-- internal/rpc/user/callback.go | 1 + internal/rpc/user/user.go | 6 ++++-- pkg/common/convert/friend.go | 1 + pkg/common/db/controller/user.go | 9 ++++++++- pkg/common/db/mgo/friend.go | 1 + pkg/common/db/mgo/user.go | 13 +++++++++++-- pkg/common/db/table/relation/user.go | 3 ++- .../discoveryregister/kubernetes/kubernetes.go | 4 +++- pkg/rpcclient/msg.go | 1 + 18 files changed, 49 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index 4332e389c2..739cf6b8e7 100644 --- a/go.mod +++ b/go.mod @@ -38,6 +38,7 @@ require ( github.com/aliyun/aliyun-oss-go-sdk v2.2.9+incompatible github.com/go-redis/redis v6.15.9+incompatible github.com/redis/go-redis/v9 v9.2.1 + github.com/spf13/pflag v1.0.5 github.com/stathat/consistent v1.0.0 github.com/tencentyun/cos-go-sdk-v5 v0.7.45 go.uber.org/automaxprocs v1.5.3 @@ -116,7 +117,6 @@ require ( github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rs/xid v1.5.0 // indirect github.com/sergi/go-diff v1.0.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect github.com/src-d/gcfg v1.4.0 // indirect github.com/stretchr/objx v0.5.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect diff --git a/go.sum b/go.sum index d32a689cb5..659ff30369 100644 --- a/go.sum +++ b/go.sum @@ -15,11 +15,11 @@ cloud.google.com/go/storage v1.30.1 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/o cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= firebase.google.com/go v3.13.0+incompatible h1:3TdYC3DDi6aHn20qoRkxwGqNgdjtblwVAyRLQwGn/+4= firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIwjt8toICdV5Wh9ptHs= -github.com/AndrewZuo01/protocol v0.0.0-20240112093520-fd9c53e27b94 h1:o86vkek41ZrQqoBGqyKvS0z6N0uJj64mpzK72OkDZVM= -github.com/AndrewZuo01/protocol v0.0.0-20240112093520-fd9c53e27b94/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/IBM/sarama v1.41.3 h1:MWBEJ12vHC8coMjdEXFq/6ftO6DUZnQlFYcxtOJFa7c= github.com/IBM/sarama v1.41.3/go.mod h1:Xxho9HkHd4K/MDUo/T/sOqwtX/17D33++E9Wib6hUdQ= +github.com/OpenIMSDK/protocol v0.0.48 h1:8MIMjyzJRsruYhVv2ZKArFiOveroaofDOb3dlAdgjsw= +github.com/OpenIMSDK/protocol v0.0.48/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y= github.com/OpenIMSDK/tools v0.0.23 h1:xozfrGzhbpNPlDTap5DLVPk+JfgZ/ZyIj4Cuu3/bm9w= github.com/OpenIMSDK/tools v0.0.23/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI= github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM= diff --git a/internal/msggateway/n_ws_server.go b/internal/msggateway/n_ws_server.go index 7e8129105f..01d92b92ac 100644 --- a/internal/msggateway/n_ws_server.go +++ b/internal/msggateway/n_ws_server.go @@ -19,7 +19,6 @@ import ( "encoding/json" "errors" "fmt" - "github.com/OpenIMSDK/tools/apiresp" "net/http" "os" "os/signal" @@ -29,6 +28,8 @@ import ( "syscall" "time" + "github.com/OpenIMSDK/tools/apiresp" + "github.com/go-playground/validator/v10" "github.com/redis/go-redis/v9" "golang.org/x/sync/errgroup" diff --git a/internal/push/push_rpc_server.go b/internal/push/push_rpc_server.go index 9e66f8f739..188ddc0e15 100644 --- a/internal/push/push_rpc_server.go +++ b/internal/push/push_rpc_server.go @@ -16,9 +16,10 @@ package push import ( "context" - "github.com/OpenIMSDK/tools/utils" "sync" + "github.com/OpenIMSDK/tools/utils" + "google.golang.org/grpc" "github.com/OpenIMSDK/protocol/constant" diff --git a/internal/push/push_to_client.go b/internal/push/push_to_client.go index 7cee7b99d3..ca90046058 100644 --- a/internal/push/push_to_client.go +++ b/internal/push/push_to_client.go @@ -18,9 +18,10 @@ import ( "context" "encoding/json" "errors" - "google.golang.org/grpc" "sync" + "google.golang.org/grpc" + "golang.org/x/sync/errgroup" "github.com/OpenIMSDK/protocol/constant" diff --git a/internal/rpc/conversation/conversaion.go b/internal/rpc/conversation/conversaion.go index d0d59547c5..40803089ca 100644 --- a/internal/rpc/conversation/conversaion.go +++ b/internal/rpc/conversation/conversaion.go @@ -17,9 +17,10 @@ package conversation import ( "context" "errors" - "github.com/OpenIMSDK/protocol/sdkws" "sort" + "github.com/OpenIMSDK/protocol/sdkws" + "github.com/OpenIMSDK/tools/tx" "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo" diff --git a/internal/rpc/msg/as_read.go b/internal/rpc/msg/as_read.go index e91e2cf342..cb292421e9 100644 --- a/internal/rpc/msg/as_read.go +++ b/internal/rpc/msg/as_read.go @@ -18,6 +18,7 @@ import ( "context" utils2 "github.com/OpenIMSDK/tools/utils" + cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" "github.com/redis/go-redis/v9" diff --git a/internal/rpc/msg/seq.go b/internal/rpc/msg/seq.go index c12f258b70..dfc2ad0b1b 100644 --- a/internal/rpc/msg/seq.go +++ b/internal/rpc/msg/seq.go @@ -16,6 +16,7 @@ package msg import ( "context" + pbmsg "github.com/OpenIMSDK/protocol/msg" ) diff --git a/internal/rpc/third/s3.go b/internal/rpc/third/s3.go index 2c230f258b..3b501d4add 100644 --- a/internal/rpc/third/s3.go +++ b/internal/rpc/third/s3.go @@ -19,12 +19,14 @@ import ( "encoding/base64" "encoding/hex" "encoding/json" - "github.com/google/uuid" - "github.com/openimsdk/open-im-server/v3/pkg/authverify" "path" "strconv" "time" + "github.com/google/uuid" + + "github.com/openimsdk/open-im-server/v3/pkg/authverify" + "github.com/openimsdk/open-im-server/v3/pkg/common/db/s3" "github.com/OpenIMSDK/protocol/third" diff --git a/internal/rpc/user/callback.go b/internal/rpc/user/callback.go index 092a66a07c..5276946a48 100644 --- a/internal/rpc/user/callback.go +++ b/internal/rpc/user/callback.go @@ -16,6 +16,7 @@ package user import ( "context" + pbuser "github.com/OpenIMSDK/protocol/user" "github.com/OpenIMSDK/tools/utils" diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go index 240bea1533..e09c3299a1 100644 --- a/internal/rpc/user/user.go +++ b/internal/rpc/user/user.go @@ -17,12 +17,14 @@ package user import ( "context" "errors" - "github.com/OpenIMSDK/tools/pagination" - "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" "math/rand" "strings" "time" + "github.com/OpenIMSDK/tools/pagination" + + "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" + "github.com/OpenIMSDK/tools/tx" "github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo" diff --git a/pkg/common/convert/friend.go b/pkg/common/convert/friend.go index 62ce6f95bb..27bd595ad5 100644 --- a/pkg/common/convert/friend.go +++ b/pkg/common/convert/friend.go @@ -17,6 +17,7 @@ package convert import ( "context" "fmt" + "github.com/OpenIMSDK/protocol/sdkws" "github.com/OpenIMSDK/tools/utils" diff --git a/pkg/common/db/controller/user.go b/pkg/common/db/controller/user.go index 1a36510762..78ac5a7010 100644 --- a/pkg/common/db/controller/user.go +++ b/pkg/common/db/controller/user.go @@ -190,7 +190,14 @@ func (u *userDatabase) Page(ctx context.Context, pagination pagination.Paginatio func (u *userDatabase) PageFindUser(ctx context.Context, level1 int64, level2 int64, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) { 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 []*relation.UserModel, err error) { return u.userDB.PageFindUserWithKeyword(ctx, level1, level2, userID, nickName, pagination) } diff --git a/pkg/common/db/mgo/friend.go b/pkg/common/db/mgo/friend.go index b4172d0fbb..851db61572 100644 --- a/pkg/common/db/mgo/friend.go +++ b/pkg/common/db/mgo/friend.go @@ -16,6 +16,7 @@ package mgo import ( "context" + "github.com/OpenIMSDK/tools/mgoutil" "github.com/OpenIMSDK/tools/pagination" "go.mongodb.org/mongo-driver/mongo/options" diff --git a/pkg/common/db/mgo/user.go b/pkg/common/db/mgo/user.go index 7eed326349..34a25ed08e 100644 --- a/pkg/common/db/mgo/user.go +++ b/pkg/common/db/mgo/user.go @@ -16,10 +16,11 @@ package mgo import ( "context" + "time" + "github.com/OpenIMSDK/protocol/user" "github.com/OpenIMSDK/tools/errs" "go.mongodb.org/mongo-driver/bson/primitive" - "time" "github.com/OpenIMSDK/tools/mgoutil" "github.com/OpenIMSDK/tools/pagination" @@ -89,7 +90,15 @@ func (u *UserMgo) PageFindUser(ctx context.Context, level1 int64, level2 int64, return mgoutil.FindPage[*relation.UserModel](ctx, u.coll, query, pagination) } -func (u *UserMgo) PageFindUserWithKeyword(ctx context.Context, level1 int64, level2 int64, userID string, nickName string, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) { + +func (u *UserMgo) PageFindUserWithKeyword( + ctx context.Context, + level1 int64, + level2 int64, + userID string, + nickName string, + pagination pagination.Pagination, +) (count int64, users []*relation.UserModel, err error) { // Initialize the base query with level conditions query := bson.M{ "$and": []bson.M{ diff --git a/pkg/common/db/table/relation/user.go b/pkg/common/db/table/relation/user.go index 4039257f17..dbb2ff4647 100644 --- a/pkg/common/db/table/relation/user.go +++ b/pkg/common/db/table/relation/user.go @@ -16,9 +16,10 @@ package relation import ( "context" - "github.com/OpenIMSDK/protocol/user" "time" + "github.com/OpenIMSDK/protocol/user" + "github.com/OpenIMSDK/tools/pagination" ) diff --git a/pkg/common/discoveryregister/kubernetes/kubernetes.go b/pkg/common/discoveryregister/kubernetes/kubernetes.go index c105180568..06c58d9616 100644 --- a/pkg/common/discoveryregister/kubernetes/kubernetes.go +++ b/pkg/common/discoveryregister/kubernetes/kubernetes.go @@ -18,15 +18,17 @@ import ( "context" "errors" "fmt" - "github.com/stathat/consistent" "os" "strconv" "strings" + "github.com/stathat/consistent" + "google.golang.org/grpc" "github.com/OpenIMSDK/tools/discoveryregistry" "github.com/OpenIMSDK/tools/log" + "github.com/openimsdk/open-im-server/v3/pkg/common/config" ) diff --git a/pkg/rpcclient/msg.go b/pkg/rpcclient/msg.go index abad0075ad..56167d7f44 100644 --- a/pkg/rpcclient/msg.go +++ b/pkg/rpcclient/msg.go @@ -17,6 +17,7 @@ package rpcclient import ( "context" "encoding/json" + "google.golang.org/grpc" "google.golang.org/protobuf/proto" From 7b5279a15b88e519290d7ff01a3a1ffa64e0898c Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Wed, 13 Mar 2024 10:54:44 +0800 Subject: [PATCH 05/27] fix: component --- tools/component/component.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/component/component.go b/tools/component/component.go index 3220f36f73..e1f86e1207 100644 --- a/tools/component/component.go +++ b/tools/component/component.go @@ -99,13 +99,14 @@ func main() { } checks := []checkFunc{ - //{name: "Mysql", function: checkMysql}, {name: "Mongo", function: checkMongo, config: conf}, {name: "Redis", function: checkRedis, config: conf}, - {name: "Minio", function: checkMinio, config: conf}, {name: "Zookeeper", function: checkZookeeper, config: conf}, {name: "Kafka", function: checkKafka, config: conf}, } + if conf.Object.Enable == "minio" { + checks = append(checks, checkFunc{name: "Minio", function: checkMinio, config: conf}) + } for i := 0; i < maxRetry; i++ { if i != 0 { From 34daf1307f48e46be73c2c912a3c9d771a1c7eac Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Wed, 13 Mar 2024 14:37:03 +0800 Subject: [PATCH 06/27] fix: getConversationInfo --- internal/rpc/conversation/conversaion.go | 26 ++++++++++++++++-------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/internal/rpc/conversation/conversaion.go b/internal/rpc/conversation/conversaion.go index 91eec079bd..e78e4a18f0 100644 --- a/internal/rpc/conversation/conversaion.go +++ b/internal/rpc/conversation/conversaion.go @@ -506,19 +506,27 @@ func (c *conversationServer) getConversationInfo( switch chatLog.SessionType { case constant.SingleChatType: if chatLog.SendID == userID { - msgInfo.FaceURL = sendMap[chatLog.RecvID].FaceURL - msgInfo.SenderName = sendMap[chatLog.RecvID].Nickname + if recv, ok := sendMap[chatLog.RecvID]; ok { + msgInfo.FaceURL = recv.FaceURL + msgInfo.SenderName = recv.Nickname + } break } - msgInfo.FaceURL = sendMap[chatLog.SendID].FaceURL - msgInfo.SenderName = sendMap[chatLog.SendID].Nickname + if send, ok := sendMap[chatLog.SendID]; ok { + msgInfo.FaceURL = send.FaceURL + msgInfo.SenderName = send.Nickname + } case constant.GroupChatType, constant.SuperGroupChatType: - msgInfo.GroupName = groupMap[chatLog.GroupID].GroupName - msgInfo.GroupFaceURL = groupMap[chatLog.GroupID].FaceURL - msgInfo.GroupMemberCount = groupMap[chatLog.GroupID].MemberCount msgInfo.GroupID = chatLog.GroupID - msgInfo.GroupType = groupMap[chatLog.GroupID].GroupType - msgInfo.SenderName = sendMap[chatLog.SendID].Nickname + if group, ok := groupMap[chatLog.GroupID]; ok { + msgInfo.GroupName = group.GroupName + msgInfo.GroupFaceURL = group.FaceURL + msgInfo.GroupMemberCount = group.MemberCount + msgInfo.GroupType = group.GroupType + } + if send, ok := sendMap[chatLog.SendID]; ok { + msgInfo.SenderName = send.Nickname + } } pbchatLog.ConversationID = conversationID msgInfo.LatestMsgRecvTime = chatLog.SendTime From dc57d38856bfcfd7ef0e2ff6c9627530e59f5d81 Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Thu, 25 Apr 2024 16:50:24 +0800 Subject: [PATCH 07/27] feat: cron task --- config/openim-crontask.yml | 4 +- go.mod | 9 +- internal/rpc/conversation/conversaion.go | 43 +++++ internal/rpc/msg/clear.go | 77 ++++++++ internal/tools/conversation.go | 149 --------------- internal/tools/cron_task.go | 111 ++++------- internal/tools/cron_task_test.go | 113 ------------ internal/tools/msg.go | 226 ----------------------- internal/tools/msg_doc_convert.go | 46 ----- pkg/authverify/token.go | 1 - pkg/common/config/config.go | 2 - pkg/common/db/controller/msg.go | 75 ++++++++ pkg/common/db/mgo/conversation.go | 11 +- pkg/common/db/mgo/msg.go | 86 +++++++++ pkg/common/db/mgo/msg_del.go | 71 +++++++ pkg/common/db/mgo/msg_test.go | 46 +++++ pkg/common/db/table/relation/msg.go | 6 + pkg/rpcclient/conversation.go | 5 + pkg/rpcclient/msg.go | 5 + 19 files changed, 470 insertions(+), 616 deletions(-) create mode 100644 internal/rpc/msg/clear.go delete mode 100644 internal/tools/conversation.go delete mode 100644 internal/tools/cron_task_test.go delete mode 100644 internal/tools/msg.go delete mode 100644 internal/tools/msg_doc_convert.go create mode 100644 pkg/common/db/mgo/msg_del.go create mode 100644 pkg/common/db/mgo/msg_test.go diff --git a/config/openim-crontask.yml b/config/openim-crontask.yml index 39f730112a..9bbccfd252 100644 --- a/config/openim-crontask.yml +++ b/config/openim-crontask.yml @@ -1,4 +1,2 @@ -chatRecordsClearTime: "0 2 * * 3" -msgDestructTime: "0 2 * * *" +chatRecordsClearTime: "0 2 * * *" retainChatRecords: 365 -enableCronLocker: false diff --git a/go.mod b/go.mod index 891125a899..58354b107d 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module github.com/openimsdk/open-im-server/v3 -go 1.20 +go 1.21.2 + +toolchain go1.21.9 require ( firebase.google.com/go v3.13.0+incompatible @@ -172,3 +174,8 @@ require ( golang.org/x/crypto v0.21.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect ) + + +replace ( + github.com/openimsdk/protocol => /Users/chao/Desktop/withchao/protocol +) \ No newline at end of file diff --git a/internal/rpc/conversation/conversaion.go b/internal/rpc/conversation/conversaion.go index 1bf612923c..96d2a403f6 100644 --- a/internal/rpc/conversation/conversaion.go +++ b/internal/rpc/conversation/conversaion.go @@ -536,3 +536,46 @@ func (c *conversationServer) GetConversationNotReceiveMessageUserIDs(ctx context } return &pbconversation.GetConversationNotReceiveMessageUserIDsResp{UserIDs: userIDs}, nil } + +func (c *conversationServer) UpdateConversation(ctx context.Context, req *pbconversation.UpdateConversationReq) (*pbconversation.UpdateConversationResp, error) { + m := make(map[string]any) + if req.RecvMsgOpt != nil { + m["recv_msg_opt"] = req.RecvMsgOpt.Value + } + if req.AttachedInfo != nil { + m["attached_info"] = req.AttachedInfo.Value + } + if req.Ex != nil { + m["ex"] = req.Ex.Value + } + if req.IsPinned != nil { + m["is_pinned"] = req.IsPinned.Value + } + if req.GroupAtType != nil { + m["group_at_type"] = req.GroupAtType.Value + } + if req.MsgDestructTime != nil { + m["msg_destruct_time"] = req.MsgDestructTime.Value + } + if req.IsMsgDestruct != nil { + m["is_msg_destruct"] = req.IsMsgDestruct.Value + } + if req.BurnDuration != nil { + m["burn_duration"] = req.BurnDuration.Value + } + if req.IsPrivateChat != nil { + m["is_private_chat"] = req.IsPrivateChat.Value + } + if req.MinSeq != nil { + m["min_seq"] = req.MinSeq.Value + } + if req.MaxSeq != nil { + m["max_seq"] = req.MaxSeq.Value + } + if len(m) > 0 { + if err := c.conversationDatabase.UpdateUsersConversationField(ctx, req.UserIDs, req.ConversationID, m); err != nil { + return nil, err + } + } + return &pbconversation.UpdateConversationResp{}, nil +} diff --git a/internal/rpc/msg/clear.go b/internal/rpc/msg/clear.go new file mode 100644 index 0000000000..774eae32cd --- /dev/null +++ b/internal/rpc/msg/clear.go @@ -0,0 +1,77 @@ +package msg + +import ( + "context" + "github.com/openimsdk/open-im-server/v3/pkg/authverify" + "github.com/openimsdk/protocol/conversation" + "github.com/openimsdk/protocol/msg" + "github.com/openimsdk/protocol/wrapperspb" + "github.com/openimsdk/tools/errs" + "github.com/openimsdk/tools/log" + "strings" + "time" +) + +func (m *msgServer) ClearMsg(ctx context.Context, req *msg.ClearMsgReq) (_ *msg.ClearMsgResp, err error) { + if err := authverify.CheckAdmin(ctx, m.config.Share.IMAdminUserID); err != nil { + return nil, err + } + if req.Timestamp > time.Now().UnixMilli() { + return nil, errs.ErrArgs.WrapMsg("request millisecond timestamp error") + } + var ( + docNum int + msgNum int + start = time.Now() + ) + clearMsg := func(ctx context.Context) (bool, error) { + conversationSeqs := make(map[string]struct{}) + defer func() { + req := &conversation.UpdateConversationReq{ + MsgDestructTime: wrapperspb.Int64(time.Now().UnixMilli()), + } + for conversationID := range conversationSeqs { + req.ConversationID = conversationID + if err := m.Conversation.UpdateConversations(ctx, req); err != nil { + log.ZError(ctx, "update conversation max seq failed", err, "conversationID", conversationID, "msgDestructTime", req.MsgDestructTime) + } + } + }() + msgs, err := m.MsgDatabase.GetBeforeMsg(ctx, req.Timestamp, 100) + if err != nil { + return false, err + } + if len(msgs) == 0 { + return false, nil + } + for _, msg := range msgs { + index, err := m.MsgDatabase.DeleteDocMsgBefore(ctx, req.Timestamp, msg) + if err != nil { + return false, err + } + if len(index) == 0 { + return false, errs.ErrInternalServer.WrapMsg("delete doc msg failed") + } + docNum++ + msgNum += len(index) + conversationID := msg.DocID[:strings.LastIndex(msg.DocID, ":")] + if _, ok := conversationSeqs[conversationID]; !ok { + conversationSeqs[conversationID] = struct{}{} + } + } + return true, nil + } + for { + keep, err := clearMsg(ctx) + if err != nil { + log.ZError(ctx, "clear msg failed", err, "docNum", docNum, "msgNum", msgNum, "cost", time.Since(start)) + return nil, err + } + if !keep { + log.ZInfo(ctx, "clear msg success", "docNum", docNum, "msgNum", msgNum, "cost", time.Since(start)) + break + } + log.ZInfo(ctx, "clearing message", "docNum", docNum, "msgNum", msgNum, "cost", time.Since(start)) + } + return &msg.ClearMsgResp{}, nil +} diff --git a/internal/tools/conversation.go b/internal/tools/conversation.go deleted file mode 100644 index 3e2a88ffd6..0000000000 --- a/internal/tools/conversation.go +++ /dev/null @@ -1,149 +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 tools - -import ( - "context" - "math/rand" - "time" - - "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" - "github.com/openimsdk/protocol/sdkws" - "github.com/openimsdk/tools/log" - "github.com/openimsdk/tools/mcontext" - "github.com/openimsdk/tools/utils/idutil" - "github.com/openimsdk/tools/utils/stringutil" -) - -// func (c *MsgTool) ConversationsDestructMsgs() { -// log.ZInfo(context.Background(), "start msg destruct cron task") -// ctx := mcontext.NewCtx(utils.GetSelfFuncName()) -// conversations, err := c.conversationDatabase.GetConversationIDsNeedDestruct(ctx) -// if err != nil { -// log.ZError(ctx, "get conversation id need destruct failed", err) -// return -// } -// log.ZDebug(context.Background(), "nums conversations need destruct", "nums", len(conversations)) -// for _, conversation := range conversations { -// ctx = mcontext.NewCtx(utils.GetSelfFuncName() + "-" + utils.OperationIDGenerator() + "-" + conversation.ConversationID + "-" + conversation.OwnerUserID) -// log.ZDebug( -// ctx, -// "UserMsgsDestruct", -// "conversationID", -// conversation.ConversationID, -// "ownerUserID", -// conversation.OwnerUserID, -// "msgDestructTime", -// conversation.MsgDestructTime, -// "lastMsgDestructTime", -// conversation.LatestMsgDestructTime, -// ) -// now := time.Now() -// seqs, err := c.msgDatabase.UserMsgsDestruct(ctx, conversation.OwnerUserID, conversation.ConversationID, conversation.MsgDestructTime, conversation.LatestMsgDestructTime) -// if err != nil { -// log.ZError(ctx, "user msg destruct failed", err, "conversationID", conversation.ConversationID, "ownerUserID", conversation.OwnerUserID) -// continue -// } -// if len(seqs) > 0 { -// if err := c.conversationDatabase.UpdateUsersConversationField(ctx, []string{conversation.OwnerUserID}, conversation.ConversationID, map[string]interface{}{"latest_msg_destruct_time": now}); err -// != nil { -// log.ZError(ctx, "updateUsersConversationField failed", err, "conversationID", conversation.ConversationID, "ownerUserID", conversation.OwnerUserID) -// continue -// } -// if err := c.msgNotificationSender.UserDeleteMsgsNotification(ctx, conversation.OwnerUserID, conversation.ConversationID, seqs); err != nil { -// log.ZError(ctx, "userDeleteMsgsNotification failed", err, "conversationID", conversation.ConversationID, "ownerUserID", conversation.OwnerUserID) -// } -// } -// } -//} - -func (c *MsgTool) ConversationsDestructMsgs() { - log.ZInfo(context.Background(), "start msg destruct cron task") - ctx := mcontext.NewCtx(stringutil.GetSelfFuncName()) - num, err := c.conversationDatabase.GetAllConversationIDsNumber(ctx) - if err != nil { - log.ZError(ctx, "GetAllConversationIDsNumber failed", err) - return - } - const batchNum = 50 - log.ZDebug(ctx, "GetAllConversationIDsNumber", "num", num) - if num == 0 { - return - } - count := int(num/batchNum + num/batchNum/2) - if count < 1 { - count = 1 - } - maxPage := 1 + num/batchNum - if num%batchNum != 0 { - maxPage++ - } - for i := 0; i < count; i++ { - pageNumber := rand.Int63() % maxPage - pagination := &sdkws.RequestPagination{ - PageNumber: int32(pageNumber), - ShowNumber: batchNum, - } - conversationIDs, err := c.conversationDatabase.PageConversationIDs(ctx, pagination) - if err != nil { - log.ZError(ctx, "PageConversationIDs failed", err, "pageNumber", pageNumber) - continue - } - log.ZError(ctx, "PageConversationIDs failed", err, "pageNumber", pageNumber, "conversationIDsNum", len(conversationIDs), "conversationIDs", conversationIDs) - if len(conversationIDs) == 0 { - continue - } - conversations, err := c.conversationDatabase.GetConversationsByConversationID(ctx, conversationIDs) - if err != nil { - log.ZError(ctx, "GetConversationsByConversationID failed", err, "conversationIDs", conversationIDs) - continue - } - temp := make([]*relation.ConversationModel, 0, len(conversations)) - for i, conversation := range conversations { - if conversation.IsMsgDestruct && conversation.MsgDestructTime != 0 && (time.Now().Unix() > (conversation.MsgDestructTime+conversation.LatestMsgDestructTime.Unix()+8*60*60)) || - conversation.LatestMsgDestructTime.IsZero() { - temp = append(temp, conversations[i]) - } - } - for _, conversation := range temp { - ctx = mcontext.NewCtx(stringutil.GetSelfFuncName() + "-" + idutil.OperationIDGenerator() + "-" + conversation.ConversationID + "-" + conversation.OwnerUserID) - log.ZDebug( - ctx, - "UserMsgsDestruct", - "conversationID", - conversation.ConversationID, - "ownerUserID", - conversation.OwnerUserID, - "msgDestructTime", - conversation.MsgDestructTime, - "lastMsgDestructTime", - conversation.LatestMsgDestructTime, - ) - now := time.Now() - seqs, err := c.msgDatabase.UserMsgsDestruct(ctx, conversation.OwnerUserID, conversation.ConversationID, conversation.MsgDestructTime, conversation.LatestMsgDestructTime) - if err != nil { - log.ZError(ctx, "user msg destruct failed", err, "conversationID", conversation.ConversationID, "ownerUserID", conversation.OwnerUserID) - continue - } - if len(seqs) > 0 { - if err := c.conversationDatabase.UpdateUsersConversationField(ctx, []string{conversation.OwnerUserID}, conversation.ConversationID, map[string]any{"latest_msg_destruct_time": now}); err != nil { - log.ZError(ctx, "updateUsersConversationField failed", err, "conversationID", conversation.ConversationID, "ownerUserID", conversation.OwnerUserID) - continue - } - c.msgNotificationSender.UserDeleteMsgsNotification(ctx, conversation.OwnerUserID, conversation.ConversationID, seqs) - } - } - } -} diff --git a/internal/tools/cron_task.go b/internal/tools/cron_task.go index 82ce95eda9..d52ed65096 100644 --- a/internal/tools/cron_task.go +++ b/internal/tools/cron_task.go @@ -16,8 +16,11 @@ package tools import ( "context" + "fmt" "github.com/openimsdk/open-im-server/v3/pkg/common/config" - "github.com/openimsdk/tools/db/redisutil" + kdisc "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister" + "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" + "github.com/openimsdk/tools/mcontext" "os" "os/signal" "syscall" @@ -25,7 +28,6 @@ import ( "github.com/openimsdk/tools/errs" "github.com/openimsdk/tools/log" - "github.com/redis/go-redis/v9" "github.com/robfig/cron/v3" ) @@ -39,82 +41,43 @@ type CronTaskConfig struct { } func Start(ctx context.Context, config *CronTaskConfig) error { - - log.CInfo(ctx, "CRON-TASK server is initializing", "chatRecordsClearTime", - config.CronTask.ChatRecordsClearTime, "msgDestructTime", config.CronTask.MsgDestructTime) - - msgTool, err := InitMsgTool(ctx, config) - if err != nil { - return err - } - - msgTool.convertTools() - - rdb, err := redisutil.NewRedisClient(ctx, config.RedisConfig.Build()) - if err != nil { - return err - } - - // register cron tasks - var crontab = cron.New() - - _, err = crontab.AddFunc(config.CronTask.ChatRecordsClearTime, - cronWrapFunc(config, rdb, "cron_clear_msg_and_fix_seq", msgTool.AllConversationClearMsgAndFixSeq)) - if err != nil { - return errs.Wrap(err) - } - - _, err = crontab.AddFunc(config.CronTask.MsgDestructTime, - cronWrapFunc(config, rdb, "cron_conversations_destruct_msgs", msgTool.ConversationsDestructMsgs)) - if err != nil { - return errs.WrapMsg(err, "cron_conversations_destruct_msgs") - } - - // start crontab - crontab.Start() - - sigs := make(chan os.Signal, 1) - signal.Notify(sigs, syscall.SIGTERM) - <-sigs - - // stop crontab, Wait for the running task to exit. - cronCtx := crontab.Stop() - - select { - case <-cronCtx.Done(): - // graceful exit - - case <-time.After(15 * time.Second): - // forced exit on timeout + log.CInfo(ctx, "CRON-TASK server is initializing", "chatRecordsClearTime", config.CronTask.ChatRecordsClearTime, "msgDestructTime", config.CronTask.RetainChatRecords) + if config.CronTask.RetainChatRecords < 1 { + return errs.New("msg destruct time must be greater than 1").Wrap() } - - return nil -} - -// netlock redis lock. -func netlock(rdb redis.UniversalClient, key string, ttl time.Duration) bool { - value := "used" - ok, err := rdb.SetNX(context.Background(), key, value, ttl).Result() // nolint + client, err := kdisc.NewDiscoveryRegister(&config.ZookeeperConfig, &config.Share) if err != nil { - // when err is about redis server, return true. - return false + return errs.WrapMsg(err, "failed to register discovery service") } - - return ok -} - -func cronWrapFunc(config *CronTaskConfig, rdb redis.UniversalClient, key string, fn func()) func() { - enableCronLocker := config.CronTask.EnableCronLocker - return func() { - // if don't enable cron-locker, call fn directly. - if !enableCronLocker { - fn() - return + cli := rpcclient.NewMessageRpcClient(client, config.Share.RpcRegisterName.Msg) + ctx, exitBy := context.WithCancelCause(context.Background()) + ctx = mcontext.SetOpUserID(ctx, config.Share.IMAdminUserID[0]) + go func() { + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGTERM) + select { + case <-ctx.Done(): + case s := <-sigs: + exitBy(fmt.Errorf("exit signal %s", s)) } - - // when acquire redis lock, call fn(). - if netlock(rdb, key, 5*time.Second) { - fn() + }() + crontab := cron.New() + clearFunc := func() { + now := time.Now() + deltime := now.Add(-time.Hour * 24 * time.Duration(config.CronTask.RetainChatRecords)) + ctx := mcontext.SetOperationID(ctx, fmt.Sprintf("cron_%d_%d", os.Getpid(), deltime.UnixMilli())) + log.ZInfo(ctx, "clear chat records", "deltime", deltime, "timestamp", deltime.UnixMilli()) + if err := cli.ClearMsg(ctx, deltime.UnixMilli()); err != nil { + log.ZError(ctx, "cron clear chat records failed", err, "deltime", deltime, "cont", time.Since(now)) + return } + log.ZInfo(ctx, "cron clear chat records success", "deltime", deltime, "cont", time.Since(now)) + } + if _, err := crontab.AddFunc(config.CronTask.ChatRecordsClearTime, clearFunc); err != nil { + return errs.Wrap(err) } + log.ZInfo(ctx, "start cron task", "chatRecordsClearTime", config.CronTask.ChatRecordsClearTime) + crontab.Start() + <-ctx.Done() + return context.Cause(ctx) } diff --git a/internal/tools/cron_task_test.go b/internal/tools/cron_task_test.go deleted file mode 100644 index 0bea8a4361..0000000000 --- a/internal/tools/cron_task_test.go +++ /dev/null @@ -1,113 +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 tools - -import ( - "testing" - "time" - - "github.com/redis/go-redis/v9" - "github.com/stretchr/testify/assert" -) - -func TestDisLock(t *testing.T) { - rdb := redis.NewClient(&redis.Options{}) - defer rdb.Close() - - assert.Equal(t, true, netlock(rdb, "cron-1", 1*time.Second)) - - // if exists, get false - assert.Equal(t, false, netlock(rdb, "cron-1", 1*time.Second)) - - time.Sleep(2 * time.Second) - - // wait for key on timeout, get true - assert.Equal(t, true, netlock(rdb, "cron-1", 2*time.Second)) - - // set different key - assert.Equal(t, true, netlock(rdb, "cron-2", 2*time.Second)) -} - -//func TestCronWrapFunc(t *testing.T) { -// rdb := redis.NewClient(&redis.Options{}) -// defer rdb.Close() -// -// once := sync.Once{} -// done := make(chan struct{}, 1) -// cb := func() { -// once.Do(func() { -// close(done) -// }) -// } -// -// start := time.Now() -// key := fmt.Sprintf("cron-%v", rand.Int31()) -// crontab := cron.New(cron.WithSeconds()) -// crontab.AddFunc("*/1 * * * * *", cronWrapFunc(config.NewGlobalConfig(), rdb, key, cb)) -// crontab.Start() -// <-done -// -// dur := time.Since(start) -// assert.LessOrEqual(t, dur.Seconds(), float64(2*time.Second)) -// crontab.Stop() -//} -// -//func TestCronWrapFuncWithNetlock(t *testing.T) { -// conf, err := initCfg() -// if err != nil { -// panic(err) -// } -// conf.EnableCronLocker = true -// rdb := redis.NewClient(&redis.Options{}) -// defer rdb.Close() -// -// done := make(chan string, 10) -// -// crontab := cron.New(cron.WithSeconds()) -// -// key := fmt.Sprintf("cron-%v", rand.Int31()) -// crontab.AddFunc("*/1 * * * * *", cronWrapFunc(conf, rdb, key, func() { -// done <- "host1" -// })) -// crontab.AddFunc("*/1 * * * * *", cronWrapFunc(conf, rdb, key, func() { -// done <- "host2" -// })) -// crontab.Start() -// -// time.Sleep(12 * time.Second) -// // the ttl of netlock is 5s, so expected value is 2. -// assert.Equal(t, len(done), 2) -// -// crontab.Stop() -//} -// -//func initCfg() (*config.GlobalConfig, error) { -// const ( -// defaultCfgPath = "../../../../../config/config.yaml" -// ) -// -// cfgPath := flag.String("c", defaultCfgPath, "Path to the configuration file") -// data, err := os.ReadFile(*cfgPath) -// if err != nil { -// return nil, errs.WrapMsg(err, "ReadFile unmarshal failed") -// } -// -// conf := config.NewGlobalConfig() -// err = yaml.Unmarshal(data, &conf) -// if err != nil { -// return nil, errs.WrapMsg(err, "InitConfig unmarshal failed") -// } -// return conf, nil -//} diff --git a/internal/tools/msg.go b/internal/tools/msg.go deleted file mode 100644 index 42af1efdc2..0000000000 --- a/internal/tools/msg.go +++ /dev/null @@ -1,226 +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 tools - -import ( - "context" - "fmt" - "github.com/openimsdk/open-im-server/v3/internal/rpc/msg" - "math" - "math/rand" - - "github.com/openimsdk/open-im-server/v3/pkg/common/db/controller" - "github.com/openimsdk/open-im-server/v3/pkg/util/conversationutil" - "github.com/openimsdk/protocol/sdkws" - "github.com/openimsdk/tools/errs" - "github.com/openimsdk/tools/log" - "github.com/openimsdk/tools/mcontext" - "github.com/openimsdk/tools/utils/stringutil" - "github.com/redis/go-redis/v9" -) - -type MsgTool struct { - msgDatabase controller.CommonMsgDatabase - conversationDatabase controller.ConversationDatabase - userDatabase controller.UserDatabase - groupDatabase controller.GroupDatabase - msgNotificationSender *msg.MsgNotificationSender - config *CronTaskConfig -} - -func NewMsgTool(msgDatabase controller.CommonMsgDatabase, userDatabase controller.UserDatabase, - groupDatabase controller.GroupDatabase, conversationDatabase controller.ConversationDatabase, - msgNotificationSender *msg.MsgNotificationSender, config *CronTaskConfig, -) *MsgTool { - return &MsgTool{ - msgDatabase: msgDatabase, - userDatabase: userDatabase, - groupDatabase: groupDatabase, - conversationDatabase: conversationDatabase, - msgNotificationSender: msgNotificationSender, - config: config, - } -} - -func InitMsgTool(ctx context.Context, config *CronTaskConfig) (*MsgTool, error) { - ch := make(chan int) - <-ch - //mgocli, err := mongoutil.NewMongoDB(ctx, config.MongodbConfig.Build()) - //if err != nil { - // return nil, err - //} - //rdb, err := redisutil.NewRedisClient(ctx, config.RedisConfig.Build()) - //if err != nil { - // return nil, err - //} - //discov, err := kdisc.NewDiscoveryRegister(&config.ZookeeperConfig, &config.Share) - //if err != nil { - // return nil, err - //} - //discov.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, "round_robin"))) - //userDB, err := mgo.NewUserMongo(mgocli.GetDB()) - //if err != nil { - // return nil, err - //} - ////msgDatabase, err := controller.InitCommonMsgDatabase(rdb, mgocli.GetDB(), config) - //if err != nil { - // return nil, err - //} - //userMongoDB := mgo.NewUserMongoDriver(mgocli.GetDB()) - //userDatabase := controller.NewUserDatabase( - // userDB, - // cache.NewUserCacheRedis(rdb, userDB, cache.GetDefaultOpt()), - // mgocli.GetTx(), - // userMongoDB, - //) - //groupDB, err := mgo.NewGroupMongo(mgocli.GetDB()) - //if err != nil { - // return nil, err - //} - //groupMemberDB, err := mgo.NewGroupMember(mgocli.GetDB()) - //if err != nil { - // return nil, err - //} - //groupRequestDB, err := mgo.NewGroupRequestMgo(mgocli.GetDB()) - //if err != nil { - // return nil, err - //} - //conversationDB, err := mgo.NewConversationMongo(mgocli.GetDB()) - //if err != nil { - // return nil, err - //} - //groupDatabase := controller.NewGroupDatabase(rdb, groupDB, groupMemberDB, groupRequestDB, mgocli.GetTx(), nil) - //conversationDatabase := controller.NewConversationDatabase( - // conversationDB, - // cache.NewConversationRedis(rdb, cache.GetDefaultOpt(), conversationDB), - // mgocli.GetTx(), - //) - //msgRpcClient := rpcclient.NewMessageRpcClient(discov, config.Share.RpcRegisterName.Msg) - //msgNotificationSender := notification.NewMsgNotificationSender(config, rpcclient.WithRpcClient(&msgRpcClient)) - //msgTool := NewMsgTool(msgDatabase, userDatabase, groupDatabase, conversationDatabase, msgNotificationSender, config) - //return msgTool, nil - return nil, nil -} - -// func (c *MsgTool) AllConversationClearMsgAndFixSeq() { -// ctx := mcontext.NewCtx(utils.GetSelfFuncName()) -// log.ZInfo(ctx, "============================ start del cron task ============================") -// conversationIDs, err := c.conversationDatabase.GetAllConversationIDs(ctx) -// if err != nil { -// log.ZError(ctx, "GetAllConversationIDs failed", err) -// return -// } -// for _, conversationID := range conversationIDs { -// conversationIDs = append(conversationIDs, utils.GetNotificationConversationIDByConversationID(conversationID)) -// } -// c.ClearConversationsMsg(ctx, conversationIDs) -// log.ZInfo(ctx, "============================ start del cron finished ============================") -//} - -func (c *MsgTool) AllConversationClearMsgAndFixSeq() { - ctx := mcontext.NewCtx(stringutil.GetSelfFuncName()) - log.ZInfo(ctx, "============================ start del cron task ============================") - num, err := c.conversationDatabase.GetAllConversationIDsNumber(ctx) - if err != nil { - log.ZError(ctx, "GetAllConversationIDsNumber failed", err) - return - } - const batchNum = 50 - log.ZDebug(ctx, "GetAllConversationIDsNumber", "num", num) - if num == 0 { - return - } - count := int(num/batchNum + num/batchNum/2) - if count < 1 { - count = 1 - } - maxPage := 1 + num/batchNum - if num%batchNum != 0 { - maxPage++ - } - for i := 0; i < count; i++ { - pageNumber := rand.Int63() % maxPage - pagination := &sdkws.RequestPagination{ - PageNumber: int32(pageNumber), - ShowNumber: batchNum, - } - conversationIDs, err := c.conversationDatabase.PageConversationIDs(ctx, pagination) - if err != nil { - log.ZError(ctx, "PageConversationIDs failed", err, "pageNumber", pageNumber) - continue - } - log.ZDebug(ctx, "PageConversationIDs failed", "pageNumber", pageNumber, "conversationIDsNum", len(conversationIDs), "conversationIDs", conversationIDs) - if len(conversationIDs) == 0 { - continue - } - c.ClearConversationsMsg(ctx, conversationIDs) - } - log.ZInfo(ctx, "============================ start del cron finished ============================") -} - -func (c *MsgTool) ClearConversationsMsg(ctx context.Context, conversationIDs []string) { - for _, conversationID := range conversationIDs { - if err := c.msgDatabase.DeleteConversationMsgsAndSetMinSeq(ctx, conversationID, int64(c.config.CronTask.RetainChatRecords*24*60*60)); err != nil { - log.ZError(ctx, "DeleteUserSuperGroupMsgsAndSetMinSeq failed", err, "conversationID", - conversationID, "DBRetainChatRecords", c.config.CronTask.RetainChatRecords) - } - if err := c.checkMaxSeq(ctx, conversationID); err != nil { - log.ZError(ctx, "fixSeq failed", err, "conversationID", conversationID) - } - } -} - -func (c *MsgTool) checkMaxSeqWithMongo(ctx context.Context, conversationID string, maxSeqCache int64) error { - minSeqMongo, maxSeqMongo, err := c.msgDatabase.GetMongoMaxAndMinSeq(ctx, conversationID) - if err != nil { - return err - } - if math.Abs(float64(maxSeqMongo-maxSeqCache)) > 10 { - err = fmt.Errorf("cache max seq and mongo max seq is diff > 10, maxSeqMongo:%d,minSeqMongo:%d,maxSeqCache:%d,conversationID:%s", maxSeqMongo, minSeqMongo, maxSeqCache, conversationID) - return errs.Wrap(err) - } - return nil -} - -func (c *MsgTool) checkMaxSeq(ctx context.Context, conversationID string) error { - maxSeq, err := c.msgDatabase.GetMaxSeq(ctx, conversationID) - if err != nil { - if errs.Unwrap(err) == redis.Nil { - return nil - } - return err - } - if err := c.checkMaxSeqWithMongo(ctx, conversationID, maxSeq); err != nil { - return err - } - return nil -} - -func (c *MsgTool) FixAllSeq(ctx context.Context) error { - conversationIDs, err := c.conversationDatabase.GetAllConversationIDs(ctx) - if err != nil { - return err - } - for _, conversationID := range conversationIDs { - conversationIDs = append(conversationIDs, conversationutil.GetNotificationConversationIDByConversationID(conversationID)) - } - for _, conversationID := range conversationIDs { - if err := c.checkMaxSeq(ctx, conversationID); err != nil { - log.ZWarn(ctx, "fixSeq failed", err, "conversationID", conversationID) - } - } - fmt.Println("fix all seq finished") - return nil -} diff --git a/internal/tools/msg_doc_convert.go b/internal/tools/msg_doc_convert.go deleted file mode 100644 index e7625ce215..0000000000 --- a/internal/tools/msg_doc_convert.go +++ /dev/null @@ -1,46 +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 tools - -import ( - "github.com/openimsdk/open-im-server/v3/pkg/msgprocessor" - "github.com/openimsdk/protocol/constant" - "github.com/openimsdk/tools/log" - "github.com/openimsdk/tools/mcontext" -) - -func (c *MsgTool) convertTools() { - ctx := mcontext.NewCtx("convert") - conversationIDs, err := c.conversationDatabase.GetAllConversationIDs(ctx) - if err != nil { - log.ZError(ctx, "get all conversation ids failed", err) - return - } - for _, conversationID := range conversationIDs { - conversationIDs = append(conversationIDs, msgprocessor.GetNotificationConversationIDByConversationID(conversationID)) - } - _, userIDs, err := c.userDatabase.GetAllUserID(ctx, nil) - if err != nil { - log.ZError(ctx, "get all user ids failed", err) - return - } - log.ZDebug(ctx, "all userIDs", "len userIDs", len(userIDs)) - for _, userID := range userIDs { - conversationIDs = append(conversationIDs, msgprocessor.GetConversationIDBySessionType(constant.SingleChatType, userID, userID)) - conversationIDs = append(conversationIDs, msgprocessor.GetNotificationConversationID(constant.SingleChatType, userID, userID)) - } - log.ZDebug(ctx, "all conversationIDs", "len userIDs", len(conversationIDs)) - c.msgDatabase.ConvertMsgsDocLen(ctx, conversationIDs) -} diff --git a/pkg/authverify/token.go b/pkg/authverify/token.go index a96d6de201..f1b377bad7 100644 --- a/pkg/authverify/token.go +++ b/pkg/authverify/token.go @@ -46,7 +46,6 @@ func IsAppManagerUid(ctx context.Context, imAdminUserID []string) bool { } func CheckAdmin(ctx context.Context, imAdminUserID []string) error { - if datautil.Contain(mcontext.GetOpUserID(ctx), imAdminUserID...) { return nil } diff --git a/pkg/common/config/config.go b/pkg/common/config/config.go index df2639cab3..caf31036cd 100644 --- a/pkg/common/config/config.go +++ b/pkg/common/config/config.go @@ -107,9 +107,7 @@ type API struct { type CronTask struct { ChatRecordsClearTime string `mapstructure:"chatRecordsClearTime"` - MsgDestructTime string `mapstructure:"msgDestructTime"` RetainChatRecords int `mapstructure:"retainChatRecords"` - EnableCronLocker bool `yaml:"enableCronLocker"` } type OfflinePushConfig struct { diff --git a/pkg/common/db/controller/msg.go b/pkg/common/db/controller/msg.go index 130e35d20e..c0a013c175 100644 --- a/pkg/common/db/controller/msg.go +++ b/pkg/common/db/controller/msg.go @@ -17,6 +17,8 @@ package controller import ( "context" "encoding/json" + "errors" + "strings" "time" "github.com/openimsdk/open-im-server/v3/pkg/common/config" @@ -102,6 +104,10 @@ type CommonMsgDatabase interface { 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) 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) ConvertMsgsDocLen(ctx context.Context, conversationIDs []string) + + // clear msg + GetBeforeMsg(ctx context.Context, ts int64, limit int) ([]*relation.MsgDocModel, error) + DeleteDocMsgBefore(ctx context.Context, ts int64, doc *relation.MsgDocModel) ([]int, error) } func NewCommonMsgDatabase(msgDocModel relation.MsgDocModelInterface, msg cache.MsgCache, seq cache.SeqCache, kafkaConf *config.Kafka) (CommonMsgDatabase, error) { @@ -1047,3 +1053,72 @@ func (db *commonMsgDatabase) FindOneByDocIDs(ctx context.Context, conversationID func (db *commonMsgDatabase) ConvertMsgsDocLen(ctx context.Context, conversationIDs []string) { db.msgDocDatabase.ConvertMsgsDocLen(ctx, conversationIDs) } + +func (db *commonMsgDatabase) GetBeforeMsg(ctx context.Context, ts int64, limit int) ([]*relation.MsgDocModel, error) { + return db.msgDocDatabase.GetBeforeMsg(ctx, ts, limit) +} + +func (db *commonMsgDatabase) DeleteDocMsgBefore(ctx context.Context, ts int64, doc *relation.MsgDocModel) ([]int, error) { + var notNull int + index := make([]int, 0, len(doc.Msg)) + for i, message := range doc.Msg { + if message.Msg != nil { + notNull++ + if message.Msg.SendTime < ts { + index = append(index, i) + } + } + } + if len(index) == 0 { + return index, nil + } + maxSeq := doc.Msg[index[len(index)-1]].Msg.Seq + conversationID := doc.DocID[:strings.LastIndex(doc.DocID, ":")] + if err := db.setMinSeq(ctx, conversationID, maxSeq+1); err != nil { + return index, err + } + if len(index) == notNull { + return index, db.msgDocDatabase.DeleteDoc(ctx, doc.DocID) + } else { + return index, db.msgDocDatabase.DeleteMsgByIndex(ctx, doc.DocID, index) + } +} + +//func (db *commonMsgDatabase) ClearMsg(ctx context.Context, ts int64) (err error) { +// var ( +// docNum int +// msgNum int +// start = time.Now() +// ) +// for { +// msgs, err := db.msgDocDatabase.GetBeforeMsg(ctx, ts, 100) +// if err != nil { +// return err +// } +// if len(msgs) == 0 { +// return nil +// } +// for _, msg := range msgs { +// num, err := db.deleteOneMsg(ctx, ts, msg) +// if err != nil { +// return err +// } +// docNum++ +// msgNum += num +// } +// } +//} + +func (db *commonMsgDatabase) setMinSeq(ctx context.Context, conversationID string, seq int64) error { + dbSeq, err := db.seq.GetMinSeq(ctx, conversationID) + if err != nil { + if errors.Is(errs.Unwrap(err), redis.Nil) { + return nil + } + return err + } + if dbSeq >= seq { + return nil + } + return db.seq.SetMinSeq(ctx, conversationID, seq) +} diff --git a/pkg/common/db/mgo/conversation.go b/pkg/common/db/mgo/conversation.go index d10bda39b1..5292cb60cf 100644 --- a/pkg/common/db/mgo/conversation.go +++ b/pkg/common/db/mgo/conversation.go @@ -56,7 +56,16 @@ func (c *ConversationMgo) Delete(ctx context.Context, groupIDs []string) (err er } func (c *ConversationMgo) UpdateByMap(ctx context.Context, userIDs []string, conversationID string, args map[string]any) (rows int64, err error) { - res, err := mongoutil.UpdateMany(ctx, c.coll, bson.M{"owner_user_id": bson.M{"$in": userIDs}, "conversation_id": conversationID}, bson.M{"$set": args}) + if len(args) == 0 { + return 0, nil + } + filter := bson.M{ + "conversation_id": conversationID, + } + if len(userIDs) > 0 { + filter["owner_user_id"] = bson.M{"$in": userIDs} + } + res, err := mongoutil.UpdateMany(ctx, c.coll, filter, bson.M{"$set": args}) if err != nil { return 0, err } diff --git a/pkg/common/db/mgo/msg.go b/pkg/common/db/mgo/msg.go index 40ee5e4235..6fe24536bd 100644 --- a/pkg/common/db/mgo/msg.go +++ b/pkg/common/db/mgo/msg.go @@ -896,3 +896,89 @@ func (m *MsgMgo) ConvertMsgsDocLen(ctx context.Context, conversationIDs []string } } } + +func (m *MsgMgo) GetBeforeMsg(ctx context.Context, ts int64, limit int) ([]*relation.MsgDocModel, error) { + return mongoutil.Aggregate[*relation.MsgDocModel](ctx, m.coll, []bson.M{ + { + "$match": bson.M{ + "msgs.msg.send_time": bson.M{ + "$lt": ts, + }, + }, + }, + { + "$project": bson.M{ + "_id": 0, + "doc_id": 1, + "msgs.msg.send_time": 1, + "msgs.msg.seq": 1, + }, + }, + { + "$limit": limit, + }, + }) +} + +func (m *MsgMgo) DeleteMsgByIndex(ctx context.Context, docID string, index []int) error { + if len(index) == 0 { + return nil + } + model := &relation.MsgInfoModel{DelList: []string{}} + set := make(map[string]any) + for i := range index { + set[fmt.Sprintf("msgs.%d", i)] = model + } + return mongoutil.UpdateOne(ctx, m.coll, bson.M{"doc_id": docID}, bson.M{"$set": set}, true) +} + +//func (m *MsgMgo) ClearMsg(ctx context.Context, t time.Time) (int64, error) { +// ts := t.UnixMilli() +// var count int64 +// for { +// msgs, err := m.GetBeforeMsg(ctx, ts, 100) +// if err != nil { +// return count, err +// } +// if len(msgs) == 0 { +// return count, nil +// } +// for _, msg := range msgs { +// num, err := m.deleteOneMsg(ctx, ts, msg) +// count += num +// if err != nil { +// return count, err +// } +// } +// } +//} + +func (m *MsgMgo) DeleteDoc(ctx context.Context, docID string) error { + return mongoutil.DeleteOne(ctx, m.coll, bson.M{"doc_id": docID}) +} + +//func (m *MsgMgo) DeleteDocMsg(ctx context.Context, ts int64, doc *relation.MsgDocModel) (int64, error) { +// var notNull int +// index := make([]int, 0, len(doc.Msg)) +// for i, message := range doc.Msg { +// if message.Msg != nil { +// notNull++ +// if message.Msg.SendTime < ts { +// index = append(index, i) +// } +// } +// } +// if len(index) == 0 { +// return 0, errs.New("no msg to delete").WrapMsg("deleteOneMsg", "docID", doc.DocID) +// } +// if len(index) == notNull { +// if err := m.DeleteDoc(ctx, doc.DocID); err != nil { +// return 0, err +// } +// } else { +// if err := m.setNullMsg(ctx, doc.DocID, index); err != nil { +// return 0, err +// } +// } +// return int64(len(index)), nil +//} diff --git a/pkg/common/db/mgo/msg_del.go b/pkg/common/db/mgo/msg_del.go new file mode 100644 index 0000000000..cee5fa065b --- /dev/null +++ b/pkg/common/db/mgo/msg_del.go @@ -0,0 +1,71 @@ +package mgo + +import ( + "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" + "go.mongodb.org/mongo-driver/mongo" +) + +func NewMsgDelMongo(db *mongo.Database) *MsgDelMgo { + return &MsgDelMgo{coll: db.Collection(new(relation.MsgDocModel).TableName())} +} + +type MsgDelMgo struct { + coll *mongo.Collection + model relation.MsgDocModel +} + +//func (m *MsgDelMgo) getEmptyMsg(ctx context.Context, limit int) ([]string, error) { +// return mongoutil.Aggregate[string](ctx, m.coll, []bson.M{ +// { +// "$match": bson.M{ +// "msgs": bson.M{ +// "$exists": true, +// }, +// }, +// }, +// { +// "$project": bson.M{ +// "_id": 0, +// "doc_id": 1, +// "all_null_msgs": bson.M{ +// "$not": []bson.M{ +// { +// "$anyElementTrue": bson.M{ +// "$map": bson.M{ +// "input": "$msgs", +// "as": "item", +// "in": "$$item.msg", +// }, +// }, +// }, +// }, +// }, +// }, +// }, +// { +// "$project": bson.M{ +// "doc_id": 1, +// }, +// }, +// { +// "$limit": limit, +// }, +// }) +//} +// +//func (m *MsgDelMgo) deleteEmptyMsgs(ctx context.Context) error { +// for { +// docIDs, err := m.getEmptyMsg(ctx, 100) +// if err != nil { +// return err +// } +// if len(docIDs) == 0 { +// return nil +// } +// for _, docID := range docIDs { +// if err := m.deleteEmptyMsg(ctx, docID); err != nil { +// return err +// } +// } +// } +//} diff --git a/pkg/common/db/mgo/msg_test.go b/pkg/common/db/mgo/msg_test.go new file mode 100644 index 0000000000..15026d69c6 --- /dev/null +++ b/pkg/common/db/mgo/msg_test.go @@ -0,0 +1,46 @@ +package mgo + +import ( + "strings" + "testing" +) + +func TestName(t *testing.T) { + //conf := config.Mongo{ + // Address: []string{"localhost:37017"}, + // Username: "openIM", + // Password: "openIM123", + // Database: "demo", + //} + //conf.URI = `mongodb://openIM:openIM123@localhost:37017/demo?maxPoolSize=100&authSource=admin` + //cli, err := mongoutil.NewMongoDB(context.Background(), conf.Build()) + //if err != nil { + // panic(err) + //} + //msg, _ := NewMsgMongo(cli.GetDB()) + //count, err := msg.ClearMsg(context.Background(), time.Now().Add(-time.Hour*24*61)) + //if err != nil { + // t.Log("error", err) + // return + //} + //t.Log("count", count) + + s := `si_5300327160_9129042887:0123` + + t.Log(s[:strings.LastIndex(s, ":")]) + +} + +func TestName2(t *testing.T) { + m := map[string]string{ + "1": "1", + "2": "2", + } + t.Log(m) + clear(m) + t.Log(m) + a := []string{"1", "2"} + t.Log(a) + clear(a) + t.Log(a) +} diff --git a/pkg/common/db/table/relation/msg.go b/pkg/common/db/table/relation/msg.go index 14b8dbb30e..41a6ede974 100644 --- a/pkg/common/db/table/relation/msg.go +++ b/pkg/common/db/table/relation/msg.go @@ -116,6 +116,12 @@ type MsgDocModelInterface interface { RangeUserSendCount(ctx context.Context, start time.Time, end time.Time, group bool, ase bool, pageNumber int32, showNumber int32) (msgCount int64, userCount int64, users []*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 []*GroupCount, dateCount map[string]int64, err error) ConvertMsgsDocLen(ctx context.Context, conversationIDs []string) + + DeleteDoc(ctx context.Context, docID string) error + DeleteMsgByIndex(ctx context.Context, docID string, index []int) error + GetBeforeMsg(ctx context.Context, ts int64, limit int) ([]*MsgDocModel, error) + + //ClearMsg(ctx context.Context, t time.Time) (int64, error) } func (MsgDocModel) TableName() string { diff --git a/pkg/rpcclient/conversation.go b/pkg/rpcclient/conversation.go index 6eb6c94612..e078f432b3 100644 --- a/pkg/rpcclient/conversation.go +++ b/pkg/rpcclient/conversation.go @@ -82,6 +82,11 @@ func (c *ConversationRpcClient) SetConversations(ctx context.Context, userIDs [] return err } +func (c *ConversationRpcClient) UpdateConversations(ctx context.Context, conversation *pbconversation.UpdateConversationReq) error { + _, err := c.Client.UpdateConversation(ctx, conversation) + return err +} + func (c *ConversationRpcClient) GetConversationIDs(ctx context.Context, ownerUserID string) ([]string, error) { resp, err := c.Client.GetConversationIDs(ctx, &pbconversation.GetConversationIDsReq{UserID: ownerUserID}) if err != nil { diff --git a/pkg/rpcclient/msg.go b/pkg/rpcclient/msg.go index 36daf9f66b..f660c74dd7 100644 --- a/pkg/rpcclient/msg.go +++ b/pkg/rpcclient/msg.go @@ -212,6 +212,11 @@ func (m *MessageRpcClient) GetConversationMaxSeq(ctx context.Context, conversati return resp.MaxSeq, nil } +func (m *MessageRpcClient) ClearMsg(ctx context.Context, ts int64) error { + _, err := m.Client.ClearMsg(ctx, &msg.ClearMsgReq{Timestamp: ts}) + return err +} + type NotificationSender struct { contentTypeConf map[int32]config.NotificationConfig sessionTypeConf map[int32]int32 From 2f13149555c1cd10546d778fee17d4a6854bd5ab Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Thu, 25 Apr 2024 17:02:00 +0800 Subject: [PATCH 08/27] feat: cron task --- go.mod | 7 +------ go.sum | 23 +++++++++++++++++++++-- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 58354b107d..6b23243b66 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible // indirect github.com/mitchellh/mapstructure v1.5.0 - github.com/openimsdk/protocol v0.0.64 + github.com/openimsdk/protocol v0.0.65 github.com/openimsdk/tools v0.0.49-alpha.2 github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_golang v1.18.0 @@ -174,8 +174,3 @@ require ( golang.org/x/crypto v0.21.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect ) - - -replace ( - github.com/openimsdk/protocol => /Users/chao/Desktop/withchao/protocol -) \ No newline at end of file diff --git a/go.sum b/go.sum index 5dc0cc524c..aa851c74b8 100644 --- a/go.sum +++ b/go.sum @@ -22,10 +22,13 @@ github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mo github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible h1:8psS8a+wKfiLt1iVDX79F7Y6wUM49Lcha2FMXt4UM8g= github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= @@ -43,6 +46,7 @@ github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5P github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -66,12 +70,15 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= +github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= @@ -90,6 +97,7 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= @@ -137,11 +145,13 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= +github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= @@ -194,6 +204,7 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= +github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kelindar/bitmap v1.5.2 h1:XwX7CTvJtetQZ64zrOkApoZZHBJRkjE23NfqUALA/HE= @@ -209,7 +220,9 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02 github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8= @@ -268,8 +281,8 @@ github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/openimsdk/gomake v0.0.9 h1:ouf25ygN2PMQ68Gfgns/EQRPiLPnp+77SIr68GfE+n4= github.com/openimsdk/gomake v0.0.9/go.mod h1:PndCozNc2IsQIciyn9mvEblYWZwJmAI+06z94EY+csI= -github.com/openimsdk/protocol v0.0.64 h1:OrjSs4CgKN9VLvJvrAsc37O7Ru0E0VllXZQSmG/ab7U= -github.com/openimsdk/protocol v0.0.64/go.mod h1:OZQA9FR55lseYoN2Ql1XAHYKHJGu7OMNkUbuekrKCM8= +github.com/openimsdk/protocol v0.0.65 h1:SPT9qyUsFRTTKSKb/FjpS+xr6sxz/Kbnu+su1bxYagc= +github.com/openimsdk/protocol v0.0.65/go.mod h1:OZQA9FR55lseYoN2Ql1XAHYKHJGu7OMNkUbuekrKCM8= github.com/openimsdk/tools v0.0.49-alpha.2 h1:8IfV6o2ySU7C54sh/MG7ctEp1h3lSNe03OCUDWSk5Ws= github.com/openimsdk/tools v0.0.49-alpha.2/go.mod h1:P4oGP1Pd+d4ctbLD5U/XQTgl8yu8Hd3skx640Fr69ko= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= @@ -282,6 +295,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -298,6 +312,7 @@ github.com/redis/go-redis/v9 v9.4.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0 github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -376,6 +391,7 @@ go.opentelemetry.io/otel v1.23.0/go.mod h1:YCycw9ZeKhcJFrb34iVSkyT0iczq/zYDtZYFu go.opentelemetry.io/otel/metric v1.23.0 h1:pazkx7ss4LFVVYSxYew7L5I6qvLXHA0Ap2pwV+9Cnpo= go.opentelemetry.io/otel/metric v1.23.0/go.mod h1:MqUW2X2a6Q8RN96E2/nqNoT+z9BSms20Jb7Bbp+HiTo= go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= +go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= go.opentelemetry.io/otel/trace v1.23.0 h1:37Ik5Ib7xfYVb4V1UtnT97T1jI+AoIYkJyPkuL4iJgI= go.opentelemetry.io/otel/trace v1.23.0/go.mod h1:GSGTbIClEsuZrGIzoEHqsVfxgn5UkggkflQwDScNUsk= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= @@ -383,6 +399,7 @@ go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8= go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= @@ -489,6 +506,7 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/api v0.165.0 h1:zd5d4JIIIaYYsfVy1HzoXYZ9rWCSBxxAglbczzo7Bgc= google.golang.org/api v0.165.0/go.mod h1:2OatzO7ZDQsoS7IFf3rvsE17/TldiU3F/zxFHeqUB5o= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -526,6 +544,7 @@ google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGm google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= From 2e439508bcb822f878e83b36bb8c39218c9d01e3 Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Thu, 25 Apr 2024 17:09:24 +0800 Subject: [PATCH 09/27] feat: cron task --- pkg/common/cmd/msg_utils.go | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/pkg/common/cmd/msg_utils.go b/pkg/common/cmd/msg_utils.go index fc5eaceae8..a0a9b04101 100644 --- a/pkg/common/cmd/msg_utils.go +++ b/pkg/common/cmd/msg_utils.go @@ -15,16 +15,11 @@ package cmd import ( - "context" - - "github.com/openimsdk/open-im-server/v3/internal/tools" - "github.com/openimsdk/tools/system/program" "github.com/spf13/cobra" ) type MsgUtilsCmd struct { cobra.Command - MsgTool *tools.MsgTool } func (m *MsgUtilsCmd) AddUserIDFlag() { @@ -146,27 +141,7 @@ func NewSeqCmd() *SeqCmd { func (s *SeqCmd) GetSeqCmd() *cobra.Command { s.Command.Run = func(cmdLines *cobra.Command, args []string) { - _, err := tools.InitMsgTool(context.Background(), nil) - if err != nil { - program.ExitWithError(err) - } - userID := s.getUserIDFlag(cmdLines) - superGroupID := s.getSuperGroupIDFlag(cmdLines) - // beginSeq := s.getBeginSeqFlag(cmdLines) - // limit := s.getLimitFlag(cmdLines) - if userID != "" { - // seq, err := msgTool.s(context.Background(), userID) - if err != nil { - panic(err) - } - // println(seq) - } else if superGroupID != "" { - // seq, err := msgTool.GetSuperGroupSeq(context.Background(), superGroupID) - if err != nil { - panic(err) - } - // println(seq) - } + } return &s.Command } From 7a29a853e9e50f87925ff96d6bcbdb4317d47146 Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Fri, 26 Apr 2024 15:32:20 +0800 Subject: [PATCH 10/27] feat: cron task --- internal/tools/cron_task.go | 17 +++++++---- pkg/common/cmd/cron_task.go | 3 -- pkg/common/db/mgo/msg_test.go | 56 ++++++++++++++--------------------- 3 files changed, 33 insertions(+), 43 deletions(-) diff --git a/internal/tools/cron_task.go b/internal/tools/cron_task.go index d52ed65096..7161f55fc1 100644 --- a/internal/tools/cron_task.go +++ b/internal/tools/cron_task.go @@ -19,8 +19,11 @@ import ( "fmt" "github.com/openimsdk/open-im-server/v3/pkg/common/config" kdisc "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister" - "github.com/openimsdk/open-im-server/v3/pkg/rpcclient" + "github.com/openimsdk/protocol/msg" "github.com/openimsdk/tools/mcontext" + "github.com/openimsdk/tools/mw" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" "os" "os/signal" "syscall" @@ -33,11 +36,8 @@ import ( type CronTaskConfig struct { CronTask config.CronTask - RedisConfig config.Redis - MongodbConfig config.Mongo ZookeeperConfig config.ZooKeeper Share config.Share - KafkaConfig config.Kafka } func Start(ctx context.Context, config *CronTaskConfig) error { @@ -49,9 +49,14 @@ func Start(ctx context.Context, config *CronTaskConfig) error { if err != nil { return errs.WrapMsg(err, "failed to register discovery service") } - cli := rpcclient.NewMessageRpcClient(client, config.Share.RpcRegisterName.Msg) + client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials())) ctx, exitBy := context.WithCancelCause(context.Background()) ctx = mcontext.SetOpUserID(ctx, config.Share.IMAdminUserID[0]) + conn, err := client.GetConn(ctx, config.Share.RpcRegisterName.Msg) + if err != nil { + return err + } + cli := msg.NewMsgClient(conn) go func() { sigs := make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGTERM) @@ -67,7 +72,7 @@ func Start(ctx context.Context, config *CronTaskConfig) error { deltime := now.Add(-time.Hour * 24 * time.Duration(config.CronTask.RetainChatRecords)) ctx := mcontext.SetOperationID(ctx, fmt.Sprintf("cron_%d_%d", os.Getpid(), deltime.UnixMilli())) log.ZInfo(ctx, "clear chat records", "deltime", deltime, "timestamp", deltime.UnixMilli()) - if err := cli.ClearMsg(ctx, deltime.UnixMilli()); err != nil { + if _, err := cli.ClearMsg(ctx, &msg.ClearMsgReq{Timestamp: deltime.UnixMilli()}); err != nil { log.ZError(ctx, "cron clear chat records failed", err, "deltime", deltime, "cont", time.Since(now)) return } diff --git a/pkg/common/cmd/cron_task.go b/pkg/common/cmd/cron_task.go index 0e94cf52ce..be26f5af36 100644 --- a/pkg/common/cmd/cron_task.go +++ b/pkg/common/cmd/cron_task.go @@ -34,11 +34,8 @@ func NewCronTaskCmd() *CronTaskCmd { ret := &CronTaskCmd{cronTaskConfig: &cronTaskConfig} ret.configMap = map[string]any{ OpenIMCronTaskCfgFileName: &cronTaskConfig.CronTask, - RedisConfigFileName: &cronTaskConfig.RedisConfig, - MongodbConfigFileName: &cronTaskConfig.MongodbConfig, ZookeeperConfigFileName: &cronTaskConfig.ZookeeperConfig, ShareFileName: &cronTaskConfig.Share, - KafkaConfigFileName: &cronTaskConfig.KafkaConfig, } ret.RootCmd = NewRootCmd(program.GetProcessName(), WithConfigMap(ret.configMap)) ret.ctx = context.WithValue(context.Background(), "version", config.Version) diff --git a/pkg/common/db/mgo/msg_test.go b/pkg/common/db/mgo/msg_test.go index 15026d69c6..0a92b7d4ad 100644 --- a/pkg/common/db/mgo/msg_test.go +++ b/pkg/common/db/mgo/msg_test.go @@ -1,46 +1,34 @@ package mgo import ( - "strings" + "context" + "github.com/openimsdk/protocol/msg" + "github.com/openimsdk/tools/mcontext" + "github.com/openimsdk/tools/mw" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" "testing" + "time" ) func TestName(t *testing.T) { - //conf := config.Mongo{ - // Address: []string{"localhost:37017"}, - // Username: "openIM", - // Password: "openIM123", - // Database: "demo", - //} - //conf.URI = `mongodb://openIM:openIM123@localhost:37017/demo?maxPoolSize=100&authSource=admin` - //cli, err := mongoutil.NewMongoDB(context.Background(), conf.Build()) - //if err != nil { - // panic(err) - //} - //msg, _ := NewMsgMongo(cli.GetDB()) - //count, err := msg.ClearMsg(context.Background(), time.Now().Add(-time.Hour*24*61)) - //if err != nil { - // t.Log("error", err) - // return - //} - //t.Log("count", count) + ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) + defer cancel() + ctx = mcontext.SetOpUserID(ctx, "imAdmin") + ctx = mcontext.SetOperationID(ctx, "test123456") - s := `si_5300327160_9129042887:0123` - - t.Log(s[:strings.LastIndex(s, ":")]) + conn, err := grpc.DialContext(ctx, "172.16.8.48:10130", grpc.WithTransportCredentials(insecure.NewCredentials()), mw.GrpcClient()) + if err != nil { + panic(err) + } + defer conn.Close() + cli := msg.NewMsgClient(conn) + var ts int64 -} + ts = time.Now().UnixMilli() -func TestName2(t *testing.T) { - m := map[string]string{ - "1": "1", - "2": "2", + if _, err := cli.ClearMsg(ctx, &msg.ClearMsgReq{Timestamp: ts}); err != nil { + panic(err) } - t.Log(m) - clear(m) - t.Log(m) - a := []string{"1", "2"} - t.Log(a) - clear(a) - t.Log(a) + t.Log("success!") } From 3920c0673c6acd027cba6a3833d27742aee3f9ba Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Fri, 26 Apr 2024 15:33:03 +0800 Subject: [PATCH 11/27] feat: cron task --- pkg/common/db/mgo/msg_del.go | 71 ----------------------------------- pkg/common/db/mgo/msg_test.go | 34 ----------------- 2 files changed, 105 deletions(-) delete mode 100644 pkg/common/db/mgo/msg_del.go delete mode 100644 pkg/common/db/mgo/msg_test.go diff --git a/pkg/common/db/mgo/msg_del.go b/pkg/common/db/mgo/msg_del.go deleted file mode 100644 index cee5fa065b..0000000000 --- a/pkg/common/db/mgo/msg_del.go +++ /dev/null @@ -1,71 +0,0 @@ -package mgo - -import ( - "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" - "go.mongodb.org/mongo-driver/mongo" -) - -func NewMsgDelMongo(db *mongo.Database) *MsgDelMgo { - return &MsgDelMgo{coll: db.Collection(new(relation.MsgDocModel).TableName())} -} - -type MsgDelMgo struct { - coll *mongo.Collection - model relation.MsgDocModel -} - -//func (m *MsgDelMgo) getEmptyMsg(ctx context.Context, limit int) ([]string, error) { -// return mongoutil.Aggregate[string](ctx, m.coll, []bson.M{ -// { -// "$match": bson.M{ -// "msgs": bson.M{ -// "$exists": true, -// }, -// }, -// }, -// { -// "$project": bson.M{ -// "_id": 0, -// "doc_id": 1, -// "all_null_msgs": bson.M{ -// "$not": []bson.M{ -// { -// "$anyElementTrue": bson.M{ -// "$map": bson.M{ -// "input": "$msgs", -// "as": "item", -// "in": "$$item.msg", -// }, -// }, -// }, -// }, -// }, -// }, -// }, -// { -// "$project": bson.M{ -// "doc_id": 1, -// }, -// }, -// { -// "$limit": limit, -// }, -// }) -//} -// -//func (m *MsgDelMgo) deleteEmptyMsgs(ctx context.Context) error { -// for { -// docIDs, err := m.getEmptyMsg(ctx, 100) -// if err != nil { -// return err -// } -// if len(docIDs) == 0 { -// return nil -// } -// for _, docID := range docIDs { -// if err := m.deleteEmptyMsg(ctx, docID); err != nil { -// return err -// } -// } -// } -//} diff --git a/pkg/common/db/mgo/msg_test.go b/pkg/common/db/mgo/msg_test.go deleted file mode 100644 index 0a92b7d4ad..0000000000 --- a/pkg/common/db/mgo/msg_test.go +++ /dev/null @@ -1,34 +0,0 @@ -package mgo - -import ( - "context" - "github.com/openimsdk/protocol/msg" - "github.com/openimsdk/tools/mcontext" - "github.com/openimsdk/tools/mw" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" - "testing" - "time" -) - -func TestName(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) - defer cancel() - ctx = mcontext.SetOpUserID(ctx, "imAdmin") - ctx = mcontext.SetOperationID(ctx, "test123456") - - conn, err := grpc.DialContext(ctx, "172.16.8.48:10130", grpc.WithTransportCredentials(insecure.NewCredentials()), mw.GrpcClient()) - if err != nil { - panic(err) - } - defer conn.Close() - cli := msg.NewMsgClient(conn) - var ts int64 - - ts = time.Now().UnixMilli() - - if _, err := cli.ClearMsg(ctx, &msg.ClearMsgReq{Timestamp: ts}); err != nil { - panic(err) - } - t.Log("success!") -} From 480ccc70b0512219f98913ac02550f3a77586254 Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Sun, 28 Apr 2024 18:41:36 +0800 Subject: [PATCH 12/27] fix: minio config url recognition error --- pkg/common/config/config.go | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/pkg/common/config/config.go b/pkg/common/config/config.go index caf31036cd..24d04d8ccc 100644 --- a/pkg/common/config/config.go +++ b/pkg/common/config/config.go @@ -15,14 +15,13 @@ package config import ( - "fmt" "github.com/openimsdk/tools/db/mongoutil" "github.com/openimsdk/tools/db/redisutil" "github.com/openimsdk/tools/mq/kafka" "github.com/openimsdk/tools/s3/cos" "github.com/openimsdk/tools/s3/minio" "github.com/openimsdk/tools/s3/oss" - "net" + "strings" "time" ) @@ -473,25 +472,23 @@ func (k *Kafka) Build() *kafka.Config { }, } } + func (m *Minio) Build() *minio.Config { - conf := minio.Config{ + formatEndpoint := func(address string) string { + if strings.HasPrefix(address, "http://") || strings.HasPrefix(address, "https://") { + return address + } + return "http://" + address + } + return &minio.Config{ Bucket: m.Bucket, AccessKeyID: m.AccessKeyID, SecretAccessKey: m.SecretAccessKey, SessionToken: m.SessionToken, PublicRead: m.PublicRead, + Endpoint: formatEndpoint(m.InternalAddress), + SignEndpoint: formatEndpoint(m.ExternalAddress), } - if _, _, err := net.SplitHostPort(m.InternalAddress); err == nil { - conf.Endpoint = fmt.Sprintf("http://%s", m.InternalAddress) - } else { - conf.Endpoint = m.InternalAddress - } - if _, _, err := net.SplitHostPort(m.ExternalAddress); err == nil { - conf.SignEndpoint = fmt.Sprintf("http://%s", m.ExternalAddress) - } else { - conf.SignEndpoint = m.ExternalAddress - } - return &conf } func (c *Cos) Build() *cos.Config { return &cos.Config{ From 8d4737cb677bd55e65c53d59d8318e12e74c9170 Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Wed, 3 Jul 2024 10:30:06 +0800 Subject: [PATCH 13/27] update gomake version --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 245214b932..365933de65 100644 --- a/go.mod +++ b/go.mod @@ -35,7 +35,7 @@ require ( github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/kelindar/bitmap v1.5.2 github.com/likexian/gokit v0.25.13 - github.com/openimsdk/gomake v0.0.13 + github.com/openimsdk/gomake v0.0.14-alpha.5 github.com/redis/go-redis/v9 v9.4.0 github.com/robfig/cron/v3 v3.0.1 github.com/shirou/gopsutil v3.21.11+incompatible diff --git a/go.sum b/go.sum index 664f2366a7..a5a620a144 100644 --- a/go.sum +++ b/go.sum @@ -268,8 +268,8 @@ github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/gomega v1.25.0 h1:Vw7br2PCDYijJHSfBOWhov+8cAnUf8MfMaIOV323l6Y= github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= -github.com/openimsdk/gomake v0.0.13 h1:xLDe/moqgWpRoptHzI4packAWzs4C16b+sVY+txNJp0= -github.com/openimsdk/gomake v0.0.13/go.mod h1:PndCozNc2IsQIciyn9mvEblYWZwJmAI+06z94EY+csI= +github.com/openimsdk/gomake v0.0.14-alpha.5 h1:VY9c5x515lTfmdhhPjMvR3BBRrRquAUCFsz7t7vbv7Y= +github.com/openimsdk/gomake v0.0.14-alpha.5/go.mod h1:PndCozNc2IsQIciyn9mvEblYWZwJmAI+06z94EY+csI= github.com/openimsdk/protocol v0.0.69-alpha.17 h1:pEag4ZdlovE+AyLsw1VYFU/3sk6ayvGdPzgufQfKf9M= github.com/openimsdk/protocol v0.0.69-alpha.17/go.mod h1:OZQA9FR55lseYoN2Ql1XAHYKHJGu7OMNkUbuekrKCM8= github.com/openimsdk/tools v0.0.49-alpha.28 h1:1CfdFxvKzyOIvgNMVMq4ZB2upAJ0evLbbigOhWQzhu8= From 0b4c8020748981da84e2590d5fb877d08227969c Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Wed, 3 Jul 2024 10:45:11 +0800 Subject: [PATCH 14/27] update gomake version --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 3f765805c3..e082dd64c8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -43,7 +43,7 @@ COPY --from=builder $SERVER_DIR/start-config.yml $SERVER_DIR/ COPY --from=builder $SERVER_DIR/go.mod $SERVER_DIR/ COPY --from=builder $SERVER_DIR/go.sum $SERVER_DIR/ -RUN go get github.com/openimsdk/gomake@v0.0.13 +RUN go get github.com/openimsdk/gomake@v0.0.14-alpha.5 # Set the command to run when the container starts ENTRYPOINT ["sh", "-c", "mage start && tail -f /dev/null"] From 2ce8d221898e221d537069e4f06baa90313b622a Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Wed, 17 Jul 2024 20:31:21 +0800 Subject: [PATCH 15/27] fix: seq conversion bug --- tools/seq/internal/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/seq/internal/main.go b/tools/seq/internal/main.go index 5200ad5fef..7f021a90e8 100644 --- a/tools/seq/internal/main.go +++ b/tools/seq/internal/main.go @@ -116,7 +116,7 @@ func Main(conf string, del time.Duration) error { { Prefix: MaxSeq, GetSeq: cSeq.GetMaxSeq, - SetSeq: cSeq.SetMinSeq, + SetSeq: cSeq.SetMaxSeq, }, { Prefix: MinSeq, From d521f0b0311a4c15230d29513a9ccb220841e1f1 Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Wed, 17 Jul 2024 21:43:10 +0800 Subject: [PATCH 16/27] fix: redis pipe exec --- pkg/common/storage/cache/redis/seq_conversation.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/common/storage/cache/redis/seq_conversation.go b/pkg/common/storage/cache/redis/seq_conversation.go index 76cac2b02f..fb8a547dfa 100644 --- a/pkg/common/storage/cache/redis/seq_conversation.go +++ b/pkg/common/storage/cache/redis/seq_conversation.go @@ -63,7 +63,7 @@ func (s *seqConversationCacheRedis) batchGetMaxSeq(ctx context.Context, keys []s for i, key := range keys { result[i] = pipe.HGet(ctx, key, "CURR") } - if _, err := pipe.Exec(ctx); err != nil { + if _, err := pipe.Exec(ctx); err != nil && !errors.Is(err, redis.Nil) { return errs.Wrap(err) } var notFoundKey []string From 882d24b063f924a48e7134d059841aabe82794be Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Mon, 29 Jul 2024 16:28:30 +0800 Subject: [PATCH 17/27] fix: ImportFriends --- pkg/common/storage/controller/friend.go | 61 +++++++++++++++---------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/pkg/common/storage/controller/friend.go b/pkg/common/storage/controller/friend.go index e402f5980b..636371198a 100644 --- a/pkg/common/storage/controller/friend.go +++ b/pkg/common/storage/controller/friend.go @@ -152,42 +152,55 @@ func (f *friendDatabase) BecomeFriends(ctx context.Context, ownerUserID string, return f.tx.Transaction(ctx, func(ctx context.Context) error { cache := f.cache.CloneFriendCache() // user find friends - fs1, err := f.friend.FindFriends(ctx, ownerUserID, friendUserIDs) + myFriends, err := f.friend.FindFriends(ctx, ownerUserID, friendUserIDs) if err != nil { return err } - opUserID := mcontext.GetOperationID(ctx) - for _, v := range friendUserIDs { - fs1 = append(fs1, &model.Friend{OwnerUserID: ownerUserID, FriendUserID: v, AddSource: addSource, OperatorUserID: opUserID}) - } - fs11 := datautil.DistinctAny(fs1, func(e *model.Friend) string { - return e.FriendUserID - }) - - err = f.friend.Create(ctx, fs11) + addOwners, err := f.friend.FindReversalFriends(ctx, ownerUserID, friendUserIDs) if err != nil { return err } - fs2, err := f.friend.FindReversalFriends(ctx, ownerUserID, friendUserIDs) - if err != nil { - return err + opUserID := mcontext.GetOperationID(ctx) + friends := make([]*model.Friend, 0, len(friendUserIDs)*2) + myFriendsSet := datautil.SliceSetAny(myFriends, func(friend *model.Friend) string { + return friend.FriendUserID + }) + addOwnersSet := datautil.SliceSetAny(addOwners, func(friend *model.Friend) string { + return friend.OwnerUserID + }) + newMyFriendIDs := make([]string, 0, len(friendUserIDs)) + newMyOwnerIDs := make([]string, 0, len(friendUserIDs)) + for _, userID := range friendUserIDs { + if ownerUserID == userID { + continue + } + if _, ok := myFriendsSet[userID]; !ok { + myFriendsSet[userID] = struct{}{} + newMyFriendIDs = append(newMyFriendIDs, userID) + friends = append(friends, &model.Friend{OwnerUserID: ownerUserID, FriendUserID: userID, AddSource: addSource, OperatorUserID: opUserID}) + } + if _, ok := addOwnersSet[userID]; !ok { + addOwnersSet[userID] = struct{}{} + newMyOwnerIDs = append(newMyOwnerIDs, userID) + friends = append(friends, &model.Friend{OwnerUserID: userID, FriendUserID: ownerUserID, AddSource: addSource, OperatorUserID: opUserID}) + } } - var newFriendIDs []string - for _, v := range friendUserIDs { - fs2 = append(fs2, &model.Friend{OwnerUserID: v, FriendUserID: ownerUserID, AddSource: addSource, OperatorUserID: opUserID}) - newFriendIDs = append(newFriendIDs, v) + if len(friends) == 0 { + return nil } - fs22 := datautil.DistinctAny(fs2, func(e *model.Friend) string { - return e.OwnerUserID - }) - err = f.friend.Create(ctx, fs22) + err = f.friend.Create(ctx, friends) if err != nil { return err } - newFriendIDs = append(newFriendIDs, ownerUserID) - cache = cache.DelFriendIDs(newFriendIDs...).DelMaxFriendVersion(newFriendIDs...) + if len(newMyFriendIDs) > 0 { + cache = cache.DelFriendIDs(newMyFriendIDs...) + cache = cache.DelFriends(ownerUserID, newMyFriendIDs).DelMaxFriendVersion(newMyFriendIDs...) + } + if len(newMyOwnerIDs) > 0 { + cache = cache.DelFriendIDs(newMyOwnerIDs...) + cache = cache.DelOwner(ownerUserID, newMyOwnerIDs).DelMaxFriendVersion(newMyOwnerIDs...) + } return cache.ChainExecDel(ctx) - }) } From 0f86c4bd559b89f307f0cd4924dfdfdf4941bff4 Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Fri, 16 Aug 2024 15:03:24 +0800 Subject: [PATCH 18/27] =?UTF-8?q?fix:=20A=20large=20number=20of=20logs=20k?= =?UTF-8?q?eysAndValues=20=E2=80=8B=E2=80=8Blength=20is=20not=20even?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/msggateway/ws_server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/msggateway/ws_server.go b/internal/msggateway/ws_server.go index 537b8c5f0a..9b18ade7dc 100644 --- a/internal/msggateway/ws_server.go +++ b/internal/msggateway/ws_server.go @@ -275,7 +275,7 @@ func (ws *WsServer) registerClient(client *Client) { } wg := sync.WaitGroup{} - log.ZDebug(client.ctx, "ws.msgGatewayConfig.Discovery.Enable", ws.msgGatewayConfig.Discovery.Enable) + log.ZDebug(client.ctx, "ws.msgGatewayConfig.Discovery.Enable", "discoveryEnable", ws.msgGatewayConfig.Discovery.Enable) if ws.msgGatewayConfig.Discovery.Enable != "k8s" { wg.Add(1) From 6cf385bb31e6682fccb61b28d8abd381c1d63999 Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Fri, 23 Aug 2024 17:44:58 +0800 Subject: [PATCH 19/27] feat: mark read aggregate write --- go.mod | 5 +- go.sum | 6 +- internal/push/a_test.go | 29 ++++ internal/push/push_handler.go | 136 ++++++++++++++++++ internal/rpc/group/group.go | 5 + internal/rpc/msg/as_read.go | 12 +- pkg/apistruct/msg_test.go | 1 + pkg/common/storage/cache/redis/online_test.go | 43 ++++++ pkg/common/storage/cache/redis/seq_user.go | 10 +- pkg/common/storage/cache/seq_user.go | 2 +- pkg/common/storage/controller/msg.go | 9 +- 11 files changed, 240 insertions(+), 18 deletions(-) create mode 100644 internal/push/a_test.go create mode 100644 pkg/apistruct/msg_test.go create mode 100644 pkg/common/storage/cache/redis/online_test.go diff --git a/go.mod b/go.mod index fba1499fe1..abfb4bab32 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/gorilla/websocket v1.5.1 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/mitchellh/mapstructure v1.5.0 - github.com/openimsdk/protocol v0.0.69 + github.com/openimsdk/protocol v0.0.72-alpha.6 github.com/openimsdk/tools v0.0.49-alpha.55 github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_golang v1.18.0 @@ -41,6 +41,7 @@ require ( github.com/spf13/viper v1.18.2 github.com/stathat/consistent v1.0.0 go.uber.org/automaxprocs v1.5.3 + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 golang.org/x/sync v0.6.0 ) @@ -74,7 +75,6 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/bytedance/sonic v1.9.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/chai2010/webp v1.1.1 // indirect github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect github.com/clbanning/mxj v1.8.4 // indirect github.com/coreos/go-semver v0.3.0 // indirect @@ -170,7 +170,6 @@ require ( go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/arch v0.3.0 // indirect - golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect golang.org/x/image v0.15.0 // indirect golang.org/x/net v0.22.0 // indirect golang.org/x/oauth2 v0.17.0 // indirect diff --git a/go.sum b/go.sum index 1a8e1d76d8..55490ed6a6 100644 --- a/go.sum +++ b/go.sum @@ -71,8 +71,6 @@ github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZX github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chai2010/webp v1.1.1 h1:jTRmEccAJ4MGrhFOrPMpNGIJ/eybIgwKpcACsrTEapk= -github.com/chai2010/webp v1.1.1/go.mod h1:0XVwvZWdjjdxpUEIf7b9g9VkHFnInUSYujwqTLEuldU= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= @@ -321,8 +319,8 @@ github.com/onsi/gomega v1.25.0 h1:Vw7br2PCDYijJHSfBOWhov+8cAnUf8MfMaIOV323l6Y= github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= github.com/openimsdk/gomake v0.0.14-alpha.5 h1:VY9c5x515lTfmdhhPjMvR3BBRrRquAUCFsz7t7vbv7Y= github.com/openimsdk/gomake v0.0.14-alpha.5/go.mod h1:PndCozNc2IsQIciyn9mvEblYWZwJmAI+06z94EY+csI= -github.com/openimsdk/protocol v0.0.69 h1:dVi8meSg8kmUzSH1XQab4MjihqKkkcCAmt1BYXPJuXo= -github.com/openimsdk/protocol v0.0.69/go.mod h1:OZQA9FR55lseYoN2Ql1XAHYKHJGu7OMNkUbuekrKCM8= +github.com/openimsdk/protocol v0.0.72-alpha.6 h1:FzSzXJtSyXYSAewt7vPaQf0DuU8T7QS6ePy68F7bXk8= +github.com/openimsdk/protocol v0.0.72-alpha.6/go.mod h1:OZQA9FR55lseYoN2Ql1XAHYKHJGu7OMNkUbuekrKCM8= github.com/openimsdk/tools v0.0.49-alpha.55 h1:KPgC53oqiwZYssLKljhtXbWXifMlTj2SSQEusj4Uf4k= github.com/openimsdk/tools v0.0.49-alpha.55/go.mod h1:h1cYmfyaVtgFbKmb1Cfsl8XwUOMTt8ubVUQrdGtsUh4= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= diff --git a/internal/push/a_test.go b/internal/push/a_test.go new file mode 100644 index 0000000000..8b2d864071 --- /dev/null +++ b/internal/push/a_test.go @@ -0,0 +1,29 @@ +package push + +import ( + "github.com/openimsdk/protocol/sdkws" + "testing" +) + +func TestName(t *testing.T) { + var c ConsumerHandler + c.readCh = make(chan *sdkws.MarkAsReadTips) + + go c.loopRead() + + go func() { + for i := 0; ; i++ { + seq := int64(i + 1) + if seq%3 == 0 { + seq = 1 + } + c.readCh <- &sdkws.MarkAsReadTips{ + ConversationID: "c100", + MarkAsReadUserID: "u100", + HasReadSeq: seq, + } + } + }() + + select {} +} diff --git a/internal/push/push_handler.go b/internal/push/push_handler.go index 8ecb3dad1a..bac09729d3 100644 --- a/internal/push/push_handler.go +++ b/internal/push/push_handler.go @@ -17,6 +17,7 @@ package push import ( "context" "encoding/json" + "fmt" "github.com/IBM/sarama" "github.com/openimsdk/open-im-server/v3/internal/push/offlinepush" "github.com/openimsdk/open-im-server/v3/internal/push/offlinepush/options" @@ -35,11 +36,17 @@ import ( "github.com/openimsdk/tools/log" "github.com/openimsdk/tools/mcontext" "github.com/openimsdk/tools/mq/kafka" + "github.com/openimsdk/tools/mq/memamq" "github.com/openimsdk/tools/utils/datautil" "github.com/openimsdk/tools/utils/jsonutil" "github.com/openimsdk/tools/utils/timeutil" "github.com/redis/go-redis/v9" "google.golang.org/protobuf/proto" + "math/rand" + "os" + "strconv" + "sync/atomic" + "time" ) type ConsumerHandler struct { @@ -54,6 +61,7 @@ type ConsumerHandler struct { groupRpcClient rpcclient.GroupRpcClient webhookClient *webhook.Client config *Config + readCh chan *sdkws.MarkAsReadTips } func NewConsumerHandler(config *Config, offlinePusher offlinepush.OfflinePusher, rdb redis.UniversalClient, @@ -76,6 +84,8 @@ func NewConsumerHandler(config *Config, offlinePusher offlinepush.OfflinePusher, consumerHandler.webhookClient = webhook.NewWebhookClient(config.WebhooksConfig.URL) consumerHandler.config = config consumerHandler.onlineCache = rpccache.NewOnlineCache(userRpcClient, consumerHandler.groupLocalCache, rdb, nil) + consumerHandler.readCh = make(chan *sdkws.MarkAsReadTips, 1024*8) + go consumerHandler.loopRead() return &consumerHandler, nil } @@ -89,6 +99,7 @@ func (c *ConsumerHandler) handleMs2PsChat(ctx context.Context, msg []byte) { MsgData: msgFromMQ.MsgData, ConversationID: msgFromMQ.ConversationID, } + c.handlerConversationRead(ctx, pbData.MsgData) sec := msgFromMQ.MsgData.SendTime / 1000 nowSec := timeutil.GetCurrentTimestampBySecond() log.ZDebug(ctx, "push msg", "msg", pbData.String(), "sec", sec, "nowSec", nowSec) @@ -118,6 +129,98 @@ func (*ConsumerHandler) Setup(sarama.ConsumerGroupSession) error { return nil } func (*ConsumerHandler) Cleanup(sarama.ConsumerGroupSession) error { return nil } +func (c *ConsumerHandler) loopRead() { + type markKey struct { + ConversationID string + UserID string + } + type markSeq struct { + ReadSeq int64 + MarkSeq int64 + Count int64 + } + type asyncRequest struct { + ConversationID string + UserID string + ReadSeq int64 + } + ctx := context.Background() + ctx = mcontext.WithOpUserIDContext(ctx, c.config.Share.IMAdminUserID[0]) + opIDPrefix := fmt.Sprintf("mark_read_%d_%d_", os.Getpid(), rand.Uint32()) + var incr atomic.Uint64 + maxSeq := make(map[markKey]*markSeq, 1024*8) + queue := memamq.NewMemoryQueue(32, 1024) + defer queue.Stop() + ticker := time.NewTicker(time.Second * 1) + defer ticker.Stop() + for { + select { + case <-ticker.C: + var markSeqs []asyncRequest + for key, seq := range maxSeq { + if seq.MarkSeq >= seq.ReadSeq { + seq.Count++ + if seq.Count > 6 { + delete(maxSeq, key) + } + continue + } + seq.Count = 0 + seq.MarkSeq = seq.ReadSeq + markSeqs = append(markSeqs, asyncRequest{ + ConversationID: key.ConversationID, + UserID: key.UserID, + ReadSeq: seq.ReadSeq, + }) + } + if len(markSeqs) == 0 { + continue + } + go func() { + for i := range markSeqs { + seq := markSeqs[i] + queue.PushCtx(ctx, func() { + ctx = mcontext.SetOperationID(ctx, opIDPrefix+strconv.FormatUint(incr.Add(1), 10)) + _, err := c.msgRpcClient.Client.SetConversationHasReadSeq(ctx, &pbchat.SetConversationHasReadSeqReq{ + ConversationID: seq.ConversationID, + UserID: seq.UserID, + HasReadSeq: seq.ReadSeq, + NoNotification: true, + }) + if err != nil { + log.ZError(ctx, "ConsumerHandler SetConversationHasReadSeq", err, "conversationID", seq.ConversationID, "userID", seq.UserID, "readSeq", seq.ReadSeq) + } + }) + } + }() + + case tips, ok := <-c.readCh: + if !ok { + return + } + if tips.HasReadSeq <= 0 { + continue + } + key := markKey{ + ConversationID: tips.ConversationID, + UserID: tips.MarkAsReadUserID, + } + ms, ok := maxSeq[key] + if ok { + if ms.ReadSeq < tips.HasReadSeq { + ms.ReadSeq = tips.HasReadSeq + } + } else { + ms = &markSeq{ + ReadSeq: tips.HasReadSeq, + MarkSeq: 0, + } + maxSeq[key] = ms + } + } + } +} + func (c *ConsumerHandler) ConsumeClaim(sess sarama.ConsumerGroupSession, claim sarama.ConsumerGroupClaim) error { for msg := range claim.Messages() { ctx := c.pushConsumerGroup.GetContextFromMsg(msg) @@ -215,6 +318,39 @@ func (c *ConsumerHandler) GetConnsAndOnlinePush(ctx context.Context, msg *sdkws. return result, nil } +func (c *ConsumerHandler) handlerConversationRead(ctx context.Context, msg *sdkws.MsgData) { + if msg.ContentType != constant.HasReadReceipt { + return + } + var elem sdkws.NotificationElem + if err := json.Unmarshal(msg.Content, &elem); err != nil { + log.ZError(ctx, "handlerConversationRead Unmarshal NotificationElem msg err", err, "msg", msg) + return + } + var tips sdkws.MarkAsReadTips + if err := json.Unmarshal([]byte(elem.Detail), &tips); err != nil { + log.ZError(ctx, "handlerConversationRead Unmarshal MarkAsReadTips msg err", err, "msg", msg) + return + } + if len(tips.Seqs) > 0 { + for _, seq := range tips.Seqs { + if tips.HasReadSeq < seq { + tips.HasReadSeq = seq + } + } + clear(tips.Seqs) + tips.Seqs = nil + } + if tips.HasReadSeq < 0 { + return + } + select { + case c.readCh <- &tips: + default: + log.ZWarn(ctx, "handlerConversationRead readCh is full", nil, "markAsReadTips", &tips) + } +} + func (c *ConsumerHandler) Push2Group(ctx context.Context, groupID string, msg *sdkws.MsgData) (err error) { log.ZDebug(ctx, "Get group msg from msg_transfer and push msg", "msg", msg.String(), "groupID", groupID) var pushToUserIDs []string diff --git a/internal/rpc/group/group.go b/internal/rpc/group/group.go index aa12c9d0f1..837b57f8de 100644 --- a/internal/rpc/group/group.go +++ b/internal/rpc/group/group.go @@ -66,6 +66,11 @@ type groupServer struct { webhookClient *webhook.Client } +func (s *groupServer) SetGroupInfoEX(ctx context.Context, req *pbgroup.SetGroupInfoEXReq) (*pbgroup.SetGroupInfoEXResp, error) { + //TODO implement me + panic("implement me") +} + type Config struct { RpcConfig config.Group RedisConfig config.Redis diff --git a/internal/rpc/msg/as_read.go b/internal/rpc/msg/as_read.go index bfba4824fe..9a3174e8ef 100644 --- a/internal/rpc/msg/as_read.go +++ b/internal/rpc/msg/as_read.go @@ -80,10 +80,16 @@ func (m *msgServer) SetConversationHasReadSeq(ctx context.Context, req *msg.SetC if req.HasReadSeq > maxSeq { return nil, errs.ErrArgs.WrapMsg("hasReadSeq must not be bigger than maxSeq") } - if err := m.MsgDatabase.SetHasReadSeq(ctx, req.UserID, req.ConversationID, req.HasReadSeq); err != nil { - return nil, err + if req.NoNotification { + if err := m.MsgDatabase.SetHasReadSeqToDB(ctx, req.UserID, req.ConversationID, req.HasReadSeq); err != nil { + return nil, err + } + } else { + if err := m.MsgDatabase.SetHasReadSeq(ctx, req.UserID, req.ConversationID, req.HasReadSeq); err != nil { + return nil, err + } + m.sendMarkAsReadNotification(ctx, req.ConversationID, constant.SingleChatType, req.UserID, req.UserID, nil, req.HasReadSeq) } - m.sendMarkAsReadNotification(ctx, req.ConversationID, constant.SingleChatType, req.UserID, req.UserID, nil, req.HasReadSeq) return &msg.SetConversationHasReadSeqResp{}, nil } diff --git a/pkg/apistruct/msg_test.go b/pkg/apistruct/msg_test.go new file mode 100644 index 0000000000..28f878a9fd --- /dev/null +++ b/pkg/apistruct/msg_test.go @@ -0,0 +1 @@ +package apistruct diff --git a/pkg/common/storage/cache/redis/online_test.go b/pkg/common/storage/cache/redis/online_test.go new file mode 100644 index 0000000000..2ce9432520 --- /dev/null +++ b/pkg/common/storage/cache/redis/online_test.go @@ -0,0 +1,43 @@ +package redis + +import ( + "context" + "github.com/openimsdk/open-im-server/v3/pkg/common/config" + "github.com/openimsdk/tools/db/redisutil" + "testing" + "time" +) + +/* +address: [ 172.16.8.48:7001, 172.16.8.48:7002, 172.16.8.48:7003, 172.16.8.48:7004, 172.16.8.48:7005, 172.16.8.48:7006 ] +username: +password: passwd123 +clusterMode: true +db: 0 +maxRetry: 10 +*/ +func TestName111111(t *testing.T) { + conf := config.Redis{ + Address: []string{ + "172.16.8.48:7001", + "172.16.8.48:7002", + "172.16.8.48:7003", + "172.16.8.48:7004", + "172.16.8.48:7005", + "172.16.8.48:7006", + }, + ClusterMode: true, + Password: "passwd123", + } + ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) + defer cancel() + rdb, err := redisutil.NewRedisClient(ctx, conf.Build()) + if err != nil { + panic(err) + } + online := NewUserOnline(rdb) + + userID := "123456" + t.Log(online.GetOnline(ctx, userID)) + +} diff --git a/pkg/common/storage/cache/redis/seq_user.go b/pkg/common/storage/cache/redis/seq_user.go index edbc66b21b..5458b6594b 100644 --- a/pkg/common/storage/cache/redis/seq_user.go +++ b/pkg/common/storage/cache/redis/seq_user.go @@ -73,15 +73,15 @@ func (s *seqUserCacheRedis) GetUserReadSeq(ctx context.Context, conversationID s }) } -func (s *seqUserCacheRedis) SetUserReadSeq(ctx context.Context, conversationID string, userID string, seq int64) error { - if seq%s.readSeqWriteRatio == 0 { +func (s *seqUserCacheRedis) SetUserReadSeq(ctx context.Context, conversationID string, userID string, seq int64, writeDB bool) error { + if err := s.rocks.RawSet(ctx, s.getSeqUserReadSeqKey(conversationID, userID), strconv.Itoa(int(seq)), s.readExpireTime); err != nil { + return errs.Wrap(err) + } + if writeDB { if err := s.mgo.SetUserReadSeq(ctx, conversationID, userID, seq); err != nil { return err } } - if err := s.rocks.RawSet(ctx, s.getSeqUserReadSeqKey(conversationID, userID), strconv.Itoa(int(seq)), s.readExpireTime); err != nil { - return errs.Wrap(err) - } return nil } diff --git a/pkg/common/storage/cache/seq_user.go b/pkg/common/storage/cache/seq_user.go index 61dbc0ab45..5bb9cad043 100644 --- a/pkg/common/storage/cache/seq_user.go +++ b/pkg/common/storage/cache/seq_user.go @@ -8,7 +8,7 @@ type SeqUser interface { GetUserMinSeq(ctx context.Context, conversationID string, userID string) (int64, error) SetUserMinSeq(ctx context.Context, conversationID string, userID string, seq int64) error GetUserReadSeq(ctx context.Context, conversationID string, userID string) (int64, error) - SetUserReadSeq(ctx context.Context, conversationID string, userID string, seq int64) error + SetUserReadSeq(ctx context.Context, conversationID string, userID string, seq int64, writeDB bool) error SetUserMinSeqs(ctx context.Context, userID string, seqs map[string]int64) error SetUserReadSeqs(ctx context.Context, userID string, seqs map[string]int64) error GetUserReadSeqs(ctx context.Context, userID string, conversationIDs []string) (map[string]int64, error) diff --git a/pkg/common/storage/controller/msg.go b/pkg/common/storage/controller/msg.go index 8eb417f939..6a75afcb12 100644 --- a/pkg/common/storage/controller/msg.go +++ b/pkg/common/storage/controller/msg.go @@ -77,6 +77,7 @@ type CommonMsgDatabase interface { SetUserConversationsMinSeqs(ctx context.Context, userID string, seqs map[string]int64) (err error) SetHasReadSeq(ctx context.Context, userID string, conversationID string, hasReadSeq int64) error + SetHasReadSeqToDB(ctx context.Context, userID string, conversationID string, hasReadSeq int64) error GetHasReadSeqs(ctx context.Context, userID string, conversationIDs []string) (map[string]int64, error) GetHasReadSeq(ctx context.Context, userID string, conversationID string) (int64, error) UserSetHasReadSeqs(ctx context.Context, userID string, hasReadSeqs map[string]int64) error @@ -337,7 +338,7 @@ func (db *commonMsgDatabase) DeleteMessagesFromCache(ctx context.Context, conver func (db *commonMsgDatabase) setHasReadSeqs(ctx context.Context, conversationID string, userSeqMap map[string]int64) error { for userID, seq := range userSeqMap { - if err := db.seqUser.SetUserReadSeq(ctx, conversationID, userID, seq); err != nil { + if err := db.seqUser.SetUserReadSeq(ctx, conversationID, userID, seq, false); err != nil { return err } } @@ -805,7 +806,11 @@ func (db *commonMsgDatabase) UserSetHasReadSeqs(ctx context.Context, userID stri } func (db *commonMsgDatabase) SetHasReadSeq(ctx context.Context, userID string, conversationID string, hasReadSeq int64) error { - return db.seqUser.SetUserReadSeq(ctx, conversationID, userID, hasReadSeq) + return db.seqUser.SetUserReadSeq(ctx, conversationID, userID, hasReadSeq, false) +} + +func (db *commonMsgDatabase) SetHasReadSeqToDB(ctx context.Context, userID string, conversationID string, hasReadSeq int64) error { + return db.seqUser.SetUserReadSeq(ctx, conversationID, userID, hasReadSeq, true) } func (db *commonMsgDatabase) GetHasReadSeqs(ctx context.Context, userID string, conversationIDs []string) (map[string]int64, error) { From 3b6463de35477db5b1c5106c3e73ebab5500dd92 Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Mon, 26 Aug 2024 14:55:09 +0800 Subject: [PATCH 20/27] feat: online status supports redis cluster --- go.mod | 2 +- go.sum | 4 +-- internal/push/push_handler.go | 4 +-- internal/rpc/conversation/conversaion.go | 5 ++++ pkg/common/storage/cache/redis/online.go | 26 +++++++++++----- pkg/common/storage/cache/redis/online_test.go | 30 ++++++++++++------- 6 files changed, 48 insertions(+), 23 deletions(-) diff --git a/go.mod b/go.mod index abfb4bab32..bc1b976b26 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/gorilla/websocket v1.5.1 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/mitchellh/mapstructure v1.5.0 - github.com/openimsdk/protocol v0.0.72-alpha.6 + github.com/openimsdk/protocol v0.0.72-alpha.7 github.com/openimsdk/tools v0.0.49-alpha.55 github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_golang v1.18.0 diff --git a/go.sum b/go.sum index 55490ed6a6..9b347423ac 100644 --- a/go.sum +++ b/go.sum @@ -319,8 +319,8 @@ github.com/onsi/gomega v1.25.0 h1:Vw7br2PCDYijJHSfBOWhov+8cAnUf8MfMaIOV323l6Y= github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= github.com/openimsdk/gomake v0.0.14-alpha.5 h1:VY9c5x515lTfmdhhPjMvR3BBRrRquAUCFsz7t7vbv7Y= github.com/openimsdk/gomake v0.0.14-alpha.5/go.mod h1:PndCozNc2IsQIciyn9mvEblYWZwJmAI+06z94EY+csI= -github.com/openimsdk/protocol v0.0.72-alpha.6 h1:FzSzXJtSyXYSAewt7vPaQf0DuU8T7QS6ePy68F7bXk8= -github.com/openimsdk/protocol v0.0.72-alpha.6/go.mod h1:OZQA9FR55lseYoN2Ql1XAHYKHJGu7OMNkUbuekrKCM8= +github.com/openimsdk/protocol v0.0.72-alpha.7 h1:OJTJ+FT/ujOg3+zGRt3ivebIJ9NTptLOGzW4QvwvWjs= +github.com/openimsdk/protocol v0.0.72-alpha.7/go.mod h1:OZQA9FR55lseYoN2Ql1XAHYKHJGu7OMNkUbuekrKCM8= github.com/openimsdk/tools v0.0.49-alpha.55 h1:KPgC53oqiwZYssLKljhtXbWXifMlTj2SSQEusj4Uf4k= github.com/openimsdk/tools v0.0.49-alpha.55/go.mod h1:h1cYmfyaVtgFbKmb1Cfsl8XwUOMTt8ubVUQrdGtsUh4= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= diff --git a/internal/push/push_handler.go b/internal/push/push_handler.go index bac09729d3..8979214dbe 100644 --- a/internal/push/push_handler.go +++ b/internal/push/push_handler.go @@ -151,7 +151,7 @@ func (c *ConsumerHandler) loopRead() { maxSeq := make(map[markKey]*markSeq, 1024*8) queue := memamq.NewMemoryQueue(32, 1024) defer queue.Stop() - ticker := time.NewTicker(time.Second * 1) + ticker := time.NewTicker(time.Second * 10) defer ticker.Stop() for { select { @@ -179,7 +179,7 @@ func (c *ConsumerHandler) loopRead() { go func() { for i := range markSeqs { seq := markSeqs[i] - queue.PushCtx(ctx, func() { + _ = queue.PushCtx(ctx, func() { ctx = mcontext.SetOperationID(ctx, opIDPrefix+strconv.FormatUint(incr.Add(1), 10)) _, err := c.msgRpcClient.Client.SetConversationHasReadSeq(ctx, &pbchat.SetConversationHasReadSeqReq{ ConversationID: seq.ConversationID, diff --git a/internal/rpc/conversation/conversaion.go b/internal/rpc/conversation/conversaion.go index f00c970e65..e03b96900a 100644 --- a/internal/rpc/conversation/conversaion.go +++ b/internal/rpc/conversation/conversaion.go @@ -52,6 +52,11 @@ type conversationServer struct { config *Config } +func (c *conversationServer) SetConversationMinSeq(ctx context.Context, req *pbconversation.SetConversationMinSeqReq) (*pbconversation.SetConversationMinSeqResp, error) { + //TODO implement me + panic("implement me") +} + type Config struct { RpcConfig config.Conversation RedisConfig config.Redis diff --git a/pkg/common/storage/cache/redis/online.go b/pkg/common/storage/cache/redis/online.go index a012e1cd2d..713e84e5c8 100644 --- a/pkg/common/storage/cache/redis/online.go +++ b/pkg/common/storage/cache/redis/online.go @@ -8,6 +8,7 @@ import ( "github.com/openimsdk/tools/log" "github.com/redis/go-redis/v9" "strconv" + "strings" "time" ) @@ -66,11 +67,10 @@ func (s *userOnline) SetUserOnline(ctx context.Context, userID string, online, o local change = (num1 ~= num2) or (num2 ~= num3) if change then local members = redis.call("ZRANGE", key, 0, -1) - table.insert(members, KEYS[2]) - redis.call("PUBLISH", KEYS[3], table.concat(members, ":")) - return 1 + table.insert(members, "1") + return members else - return 0 + return {"0"} end ` now := time.Now() @@ -82,12 +82,24 @@ func (s *userOnline) SetUserOnline(ctx context.Context, userID string, online, o for _, platformID := range online { argv = append(argv, platformID) } - keys := []string{s.getUserOnlineKey(userID), userID, s.channelName} - status, err := s.rdb.Eval(ctx, script, keys, argv).Result() + keys := []string{s.getUserOnlineKey(userID), userID} + platformIDs, err := s.rdb.Eval(ctx, script, keys, argv).StringSlice() if err != nil { log.ZError(ctx, "redis SetUserOnline", err, "userID", userID, "online", online, "offline", offline) return err } - log.ZDebug(ctx, "redis SetUserOnline", "userID", userID, "online", online, "offline", offline, "status", status) + if len(platformIDs) == 0 { + return errs.ErrInternalServer.WrapMsg("SetUserOnline redis lua invalid return value") + } + if platformIDs[len(platformIDs)-1] != "0" { + log.ZDebug(ctx, "redis SetUserOnline push", "userID", userID, "online", online, "offline", offline, "platformIDs", platformIDs[:len(platformIDs)-1]) + platformIDs[len(platformIDs)-1] = userID + msg := strings.Join(platformIDs, ":") + if err := s.rdb.Publish(ctx, s.channelName, msg).Err(); err != nil { + return errs.Wrap(err) + } + } else { + log.ZDebug(ctx, "redis SetUserOnline not push", "userID", userID, "online", online, "offline", offline) + } return nil } diff --git a/pkg/common/storage/cache/redis/online_test.go b/pkg/common/storage/cache/redis/online_test.go index 2ce9432520..2bda465822 100644 --- a/pkg/common/storage/cache/redis/online_test.go +++ b/pkg/common/storage/cache/redis/online_test.go @@ -18,18 +18,20 @@ maxRetry: 10 */ func TestName111111(t *testing.T) { conf := config.Redis{ - Address: []string{ - "172.16.8.48:7001", - "172.16.8.48:7002", - "172.16.8.48:7003", - "172.16.8.48:7004", - "172.16.8.48:7005", - "172.16.8.48:7006", - }, - ClusterMode: true, - Password: "passwd123", + //Address: []string{ + // "172.16.8.48:7001", + // "172.16.8.48:7002", + // "172.16.8.48:7003", + // "172.16.8.48:7004", + // "172.16.8.48:7005", + // "172.16.8.48:7006", + //}, + //ClusterMode: true, + //Password: "passwd123", + Address: []string{"localhost:16379"}, + Password: "openIM123", } - ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) + ctx, cancel := context.WithTimeout(context.Background(), time.Second*1000) defer cancel() rdb, err := redisutil.NewRedisClient(ctx, conf.Build()) if err != nil { @@ -39,5 +41,11 @@ func TestName111111(t *testing.T) { userID := "123456" t.Log(online.GetOnline(ctx, userID)) + t.Log(online.SetUserOnline(ctx, userID, []int32{1, 2, 3, 4}, nil)) + t.Log(online.GetOnline(ctx, userID)) + +} + +func TestName111(t *testing.T) { } From d2e16752cd0f82d039f0587d24f4a3a4bae8bd67 Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Mon, 26 Aug 2024 15:28:38 +0800 Subject: [PATCH 21/27] feat: online status supports redis cluster --- pkg/common/storage/cache/redis/online.go | 2 +- pkg/common/storage/cache/redis/online_test.go | 26 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/pkg/common/storage/cache/redis/online.go b/pkg/common/storage/cache/redis/online.go index 713e84e5c8..ee1db7e23b 100644 --- a/pkg/common/storage/cache/redis/online.go +++ b/pkg/common/storage/cache/redis/online.go @@ -82,7 +82,7 @@ func (s *userOnline) SetUserOnline(ctx context.Context, userID string, online, o for _, platformID := range online { argv = append(argv, platformID) } - keys := []string{s.getUserOnlineKey(userID), userID} + keys := []string{s.getUserOnlineKey(userID)} platformIDs, err := s.rdb.Eval(ctx, script, keys, argv).StringSlice() if err != nil { log.ZError(ctx, "redis SetUserOnline", err, "userID", userID, "online", online, "offline", offline) diff --git a/pkg/common/storage/cache/redis/online_test.go b/pkg/common/storage/cache/redis/online_test.go index 2bda465822..0306f6f5d7 100644 --- a/pkg/common/storage/cache/redis/online_test.go +++ b/pkg/common/storage/cache/redis/online_test.go @@ -18,18 +18,18 @@ maxRetry: 10 */ func TestName111111(t *testing.T) { conf := config.Redis{ - //Address: []string{ - // "172.16.8.48:7001", - // "172.16.8.48:7002", - // "172.16.8.48:7003", - // "172.16.8.48:7004", - // "172.16.8.48:7005", - // "172.16.8.48:7006", - //}, - //ClusterMode: true, - //Password: "passwd123", - Address: []string{"localhost:16379"}, - Password: "openIM123", + Address: []string{ + "172.16.8.124:7001", + "172.16.8.124:7002", + "172.16.8.124:7003", + "172.16.8.124:7004", + "172.16.8.124:7005", + "172.16.8.124:7006", + }, + ClusterMode: true, + Password: "passwd123", + //Address: []string{"localhost:16379"}, + //Password: "openIM123", } ctx, cancel := context.WithTimeout(context.Background(), time.Second*1000) defer cancel() @@ -39,7 +39,7 @@ func TestName111111(t *testing.T) { } online := NewUserOnline(rdb) - userID := "123456" + userID := "a123456" t.Log(online.GetOnline(ctx, userID)) t.Log(online.SetUserOnline(ctx, userID, []int32{1, 2, 3, 4}, nil)) t.Log(online.GetOnline(ctx, userID)) From 770dac32085c2d8d19a9e26e4388511c9f2867cb Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Mon, 26 Aug 2024 15:45:30 +0800 Subject: [PATCH 22/27] feat: online status supports redis cluster --- go.sum | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go.sum b/go.sum index 30fdacb4b9..9b347423ac 100644 --- a/go.sum +++ b/go.sum @@ -319,8 +319,8 @@ github.com/onsi/gomega v1.25.0 h1:Vw7br2PCDYijJHSfBOWhov+8cAnUf8MfMaIOV323l6Y= github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= github.com/openimsdk/gomake v0.0.14-alpha.5 h1:VY9c5x515lTfmdhhPjMvR3BBRrRquAUCFsz7t7vbv7Y= github.com/openimsdk/gomake v0.0.14-alpha.5/go.mod h1:PndCozNc2IsQIciyn9mvEblYWZwJmAI+06z94EY+csI= -github.com/openimsdk/protocol v0.0.72-alpha.5 h1:1Xjyx6ivTb782Sm7wMJXCLZP80iXADVo1CySis1rOG0= -github.com/openimsdk/protocol v0.0.72-alpha.5/go.mod h1:OZQA9FR55lseYoN2Ql1XAHYKHJGu7OMNkUbuekrKCM8= +github.com/openimsdk/protocol v0.0.72-alpha.7 h1:OJTJ+FT/ujOg3+zGRt3ivebIJ9NTptLOGzW4QvwvWjs= +github.com/openimsdk/protocol v0.0.72-alpha.7/go.mod h1:OZQA9FR55lseYoN2Ql1XAHYKHJGu7OMNkUbuekrKCM8= github.com/openimsdk/tools v0.0.49-alpha.55 h1:KPgC53oqiwZYssLKljhtXbWXifMlTj2SSQEusj4Uf4k= github.com/openimsdk/tools v0.0.49-alpha.55/go.mod h1:h1cYmfyaVtgFbKmb1Cfsl8XwUOMTt8ubVUQrdGtsUh4= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= From b909967631b902438fbae3f899bbcc8175e5d637 Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Mon, 26 Aug 2024 15:47:53 +0800 Subject: [PATCH 23/27] merge --- internal/rpc/conversation/conversaion.go | 5 ----- internal/rpc/group/group.go | 5 ----- 2 files changed, 10 deletions(-) diff --git a/internal/rpc/conversation/conversaion.go b/internal/rpc/conversation/conversaion.go index 92eb2311fe..cb6546f9b0 100644 --- a/internal/rpc/conversation/conversaion.go +++ b/internal/rpc/conversation/conversaion.go @@ -52,11 +52,6 @@ type conversationServer struct { config *Config } -func (c *conversationServer) SetConversationMinSeq(ctx context.Context, req *pbconversation.SetConversationMinSeqReq) (*pbconversation.SetConversationMinSeqResp, error) { - //TODO implement me - panic("implement me") -} - type Config struct { RpcConfig config.Conversation RedisConfig config.Redis diff --git a/internal/rpc/group/group.go b/internal/rpc/group/group.go index e18eb5289d..9589ed2494 100644 --- a/internal/rpc/group/group.go +++ b/internal/rpc/group/group.go @@ -66,11 +66,6 @@ type groupServer struct { webhookClient *webhook.Client } -func (s *groupServer) SetGroupInfoEX(ctx context.Context, req *pbgroup.SetGroupInfoEXReq) (*pbgroup.SetGroupInfoEXResp, error) { - //TODO implement me - panic("implement me") -} - type Config struct { RpcConfig config.Group RedisConfig config.Redis From 5f8713ad7e254b8833e4b366753edd3a49f292d2 Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Mon, 26 Aug 2024 16:34:57 +0800 Subject: [PATCH 24/27] merge --- go.sum | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/go.sum b/go.sum index 242b448236..815b6badfc 100644 --- a/go.sum +++ b/go.sum @@ -319,8 +319,7 @@ github.com/onsi/gomega v1.25.0 h1:Vw7br2PCDYijJHSfBOWhov+8cAnUf8MfMaIOV323l6Y= github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= github.com/openimsdk/gomake v0.0.14-alpha.5 h1:VY9c5x515lTfmdhhPjMvR3BBRrRquAUCFsz7t7vbv7Y= github.com/openimsdk/gomake v0.0.14-alpha.5/go.mod h1:PndCozNc2IsQIciyn9mvEblYWZwJmAI+06z94EY+csI= -github.com/openimsdk/protocol v0.0.72-alpha.8 h1:MhxSsdxXx2ZaeSLQk4uFftsB5L2rPh1Qup+dURQNzXQ= -github.com/openimsdk/protocol v0.0.72-alpha.8/go.mod h1:OZQA9FR55lseYoN2Ql1XAHYKHJGu7OMNkUbuekrKCM8= +github.com/openimsdk/protocol v0.0.72-alpha.9 h1:Dyx4vs88IU4rJ2YcP/TdYp4ww8JjsMkV89hB/Eazx+A= github.com/openimsdk/protocol v0.0.72-alpha.9/go.mod h1:OZQA9FR55lseYoN2Ql1XAHYKHJGu7OMNkUbuekrKCM8= github.com/openimsdk/tools v0.0.49-alpha.55 h1:KPgC53oqiwZYssLKljhtXbWXifMlTj2SSQEusj4Uf4k= github.com/openimsdk/tools v0.0.49-alpha.55/go.mod h1:h1cYmfyaVtgFbKmb1Cfsl8XwUOMTt8ubVUQrdGtsUh4= From 764b47ed9218aac771a23f4a43982cb08d96a66b Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Mon, 26 Aug 2024 18:35:02 +0800 Subject: [PATCH 25/27] read seq is written to mongo --- cmd/openim-msgtransfer/main.go | 4 + .../msgtransfer/online_history_msg_handler.go | 57 ++++++++ .../online_msg_to_mongo_handler.go | 1 - internal/push/push_handler.go | 136 ------------------ internal/rpc/msg/as_read.go | 12 +- pkg/common/storage/cache/redis/seq_user.go | 24 ++-- pkg/common/storage/cache/seq_user.go | 3 +- pkg/common/storage/controller/msg.go | 6 +- pkg/common/storage/database/mgo/seq_user.go | 7 + 9 files changed, 87 insertions(+), 163 deletions(-) diff --git a/cmd/openim-msgtransfer/main.go b/cmd/openim-msgtransfer/main.go index 23b629d69a..a3a14def8c 100644 --- a/cmd/openim-msgtransfer/main.go +++ b/cmd/openim-msgtransfer/main.go @@ -17,9 +17,13 @@ package main import ( "github.com/openimsdk/open-im-server/v3/pkg/common/cmd" "github.com/openimsdk/tools/system/program" + "os" ) func main() { + if len(os.Args) == 1 { + os.Args = append(os.Args, "-i", "0", "-c", "/Users/chao/Desktop/withchao/open-im-server/config/") + } if err := cmd.NewMsgTransferCmd().Exec(); err != nil { program.ExitWithError(err) } diff --git a/internal/msgtransfer/online_history_msg_handler.go b/internal/msgtransfer/online_history_msg_handler.go index 77161202cb..8c1978d48b 100644 --- a/internal/msgtransfer/online_history_msg_handler.go +++ b/internal/msgtransfer/online_history_msg_handler.go @@ -16,6 +16,7 @@ package msgtransfer import ( "context" + "encoding/json" "errors" "github.com/IBM/sarama" "github.com/go-redis/redis" @@ -89,6 +90,7 @@ func NewOnlineHistoryRedisConsumerHandler(kafkaConf *config.Kafka, database cont och.conversationRpcClient = conversationRpcClient och.groupRpcClient = groupRpcClient och.historyConsumerGroup = historyConsumerGroup + return &och, err } func (och *OnlineHistoryRedisConsumerHandler) do(ctx context.Context, channelID int, val *batcher.Msg[sarama.ConsumerMessage]) { @@ -97,6 +99,7 @@ func (och *OnlineHistoryRedisConsumerHandler) do(ctx context.Context, channelID ctx = withAggregationCtx(ctx, ctxMessages) log.ZInfo(ctx, "msg arrived channel", "channel id", channelID, "msgList length", len(ctxMessages), "key", val.Key()) + och.doSetReadSeq(ctx, ctxMessages) storageMsgList, notStorageMsgList, storageNotificationList, notStorageNotificationList := och.categorizeMessageLists(ctxMessages) @@ -110,6 +113,60 @@ func (och *OnlineHistoryRedisConsumerHandler) do(ctx context.Context, channelID och.handleNotification(ctx, val.Key(), conversationIDNotification, storageNotificationList, notStorageNotificationList) } +func (och *OnlineHistoryRedisConsumerHandler) doSetReadSeq(ctx context.Context, msgs []*ContextMsg) { + type seqKey struct { + conversationID string + userID string + } + var readSeq map[seqKey]int64 + for _, msg := range msgs { + if msg.message.ContentType != constant.HasReadReceipt { + continue + } + var elem sdkws.NotificationElem + if err := json.Unmarshal(msg.message.Content, &elem); err != nil { + log.ZError(ctx, "handlerConversationRead Unmarshal NotificationElem msg err", err, "msg", msg) + continue + } + var tips sdkws.MarkAsReadTips + if err := json.Unmarshal([]byte(elem.Detail), &tips); err != nil { + log.ZError(ctx, "handlerConversationRead Unmarshal MarkAsReadTips msg err", err, "msg", msg) + continue + } + if len(tips.Seqs) > 0 { + for _, seq := range tips.Seqs { + if tips.HasReadSeq < seq { + tips.HasReadSeq = seq + } + } + clear(tips.Seqs) + tips.Seqs = nil + } + if tips.HasReadSeq < 0 { + continue + } + if readSeq == nil { + readSeq = make(map[seqKey]int64) + } + key := seqKey{ + conversationID: tips.ConversationID, + userID: tips.MarkAsReadUserID, + } + if readSeq[key] > tips.HasReadSeq { + continue + } + readSeq[key] = tips.HasReadSeq + } + if readSeq == nil { + return + } + for key, seq := range readSeq { + if err := och.msgDatabase.SetHasReadSeqToDB(ctx, key.userID, key.conversationID, seq); err != nil { + log.ZError(ctx, "set read seq to db error", err, "userID", key.userID, "conversationID", key.conversationID, "seq", seq) + } + } +} + func (och *OnlineHistoryRedisConsumerHandler) parseConsumerMessages(ctx context.Context, consumerMessages []*sarama.ConsumerMessage) []*ContextMsg { var ctxMessages []*ContextMsg for i := 0; i < len(consumerMessages); i++ { diff --git a/internal/msgtransfer/online_msg_to_mongo_handler.go b/internal/msgtransfer/online_msg_to_mongo_handler.go index a72fb4792b..cea47fcd50 100644 --- a/internal/msgtransfer/online_msg_to_mongo_handler.go +++ b/internal/msgtransfer/online_msg_to_mongo_handler.go @@ -16,7 +16,6 @@ package msgtransfer import ( "context" - "github.com/IBM/sarama" "github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics" diff --git a/internal/push/push_handler.go b/internal/push/push_handler.go index 8979214dbe..8ecb3dad1a 100644 --- a/internal/push/push_handler.go +++ b/internal/push/push_handler.go @@ -17,7 +17,6 @@ package push import ( "context" "encoding/json" - "fmt" "github.com/IBM/sarama" "github.com/openimsdk/open-im-server/v3/internal/push/offlinepush" "github.com/openimsdk/open-im-server/v3/internal/push/offlinepush/options" @@ -36,17 +35,11 @@ import ( "github.com/openimsdk/tools/log" "github.com/openimsdk/tools/mcontext" "github.com/openimsdk/tools/mq/kafka" - "github.com/openimsdk/tools/mq/memamq" "github.com/openimsdk/tools/utils/datautil" "github.com/openimsdk/tools/utils/jsonutil" "github.com/openimsdk/tools/utils/timeutil" "github.com/redis/go-redis/v9" "google.golang.org/protobuf/proto" - "math/rand" - "os" - "strconv" - "sync/atomic" - "time" ) type ConsumerHandler struct { @@ -61,7 +54,6 @@ type ConsumerHandler struct { groupRpcClient rpcclient.GroupRpcClient webhookClient *webhook.Client config *Config - readCh chan *sdkws.MarkAsReadTips } func NewConsumerHandler(config *Config, offlinePusher offlinepush.OfflinePusher, rdb redis.UniversalClient, @@ -84,8 +76,6 @@ func NewConsumerHandler(config *Config, offlinePusher offlinepush.OfflinePusher, consumerHandler.webhookClient = webhook.NewWebhookClient(config.WebhooksConfig.URL) consumerHandler.config = config consumerHandler.onlineCache = rpccache.NewOnlineCache(userRpcClient, consumerHandler.groupLocalCache, rdb, nil) - consumerHandler.readCh = make(chan *sdkws.MarkAsReadTips, 1024*8) - go consumerHandler.loopRead() return &consumerHandler, nil } @@ -99,7 +89,6 @@ func (c *ConsumerHandler) handleMs2PsChat(ctx context.Context, msg []byte) { MsgData: msgFromMQ.MsgData, ConversationID: msgFromMQ.ConversationID, } - c.handlerConversationRead(ctx, pbData.MsgData) sec := msgFromMQ.MsgData.SendTime / 1000 nowSec := timeutil.GetCurrentTimestampBySecond() log.ZDebug(ctx, "push msg", "msg", pbData.String(), "sec", sec, "nowSec", nowSec) @@ -129,98 +118,6 @@ func (*ConsumerHandler) Setup(sarama.ConsumerGroupSession) error { return nil } func (*ConsumerHandler) Cleanup(sarama.ConsumerGroupSession) error { return nil } -func (c *ConsumerHandler) loopRead() { - type markKey struct { - ConversationID string - UserID string - } - type markSeq struct { - ReadSeq int64 - MarkSeq int64 - Count int64 - } - type asyncRequest struct { - ConversationID string - UserID string - ReadSeq int64 - } - ctx := context.Background() - ctx = mcontext.WithOpUserIDContext(ctx, c.config.Share.IMAdminUserID[0]) - opIDPrefix := fmt.Sprintf("mark_read_%d_%d_", os.Getpid(), rand.Uint32()) - var incr atomic.Uint64 - maxSeq := make(map[markKey]*markSeq, 1024*8) - queue := memamq.NewMemoryQueue(32, 1024) - defer queue.Stop() - ticker := time.NewTicker(time.Second * 10) - defer ticker.Stop() - for { - select { - case <-ticker.C: - var markSeqs []asyncRequest - for key, seq := range maxSeq { - if seq.MarkSeq >= seq.ReadSeq { - seq.Count++ - if seq.Count > 6 { - delete(maxSeq, key) - } - continue - } - seq.Count = 0 - seq.MarkSeq = seq.ReadSeq - markSeqs = append(markSeqs, asyncRequest{ - ConversationID: key.ConversationID, - UserID: key.UserID, - ReadSeq: seq.ReadSeq, - }) - } - if len(markSeqs) == 0 { - continue - } - go func() { - for i := range markSeqs { - seq := markSeqs[i] - _ = queue.PushCtx(ctx, func() { - ctx = mcontext.SetOperationID(ctx, opIDPrefix+strconv.FormatUint(incr.Add(1), 10)) - _, err := c.msgRpcClient.Client.SetConversationHasReadSeq(ctx, &pbchat.SetConversationHasReadSeqReq{ - ConversationID: seq.ConversationID, - UserID: seq.UserID, - HasReadSeq: seq.ReadSeq, - NoNotification: true, - }) - if err != nil { - log.ZError(ctx, "ConsumerHandler SetConversationHasReadSeq", err, "conversationID", seq.ConversationID, "userID", seq.UserID, "readSeq", seq.ReadSeq) - } - }) - } - }() - - case tips, ok := <-c.readCh: - if !ok { - return - } - if tips.HasReadSeq <= 0 { - continue - } - key := markKey{ - ConversationID: tips.ConversationID, - UserID: tips.MarkAsReadUserID, - } - ms, ok := maxSeq[key] - if ok { - if ms.ReadSeq < tips.HasReadSeq { - ms.ReadSeq = tips.HasReadSeq - } - } else { - ms = &markSeq{ - ReadSeq: tips.HasReadSeq, - MarkSeq: 0, - } - maxSeq[key] = ms - } - } - } -} - func (c *ConsumerHandler) ConsumeClaim(sess sarama.ConsumerGroupSession, claim sarama.ConsumerGroupClaim) error { for msg := range claim.Messages() { ctx := c.pushConsumerGroup.GetContextFromMsg(msg) @@ -318,39 +215,6 @@ func (c *ConsumerHandler) GetConnsAndOnlinePush(ctx context.Context, msg *sdkws. return result, nil } -func (c *ConsumerHandler) handlerConversationRead(ctx context.Context, msg *sdkws.MsgData) { - if msg.ContentType != constant.HasReadReceipt { - return - } - var elem sdkws.NotificationElem - if err := json.Unmarshal(msg.Content, &elem); err != nil { - log.ZError(ctx, "handlerConversationRead Unmarshal NotificationElem msg err", err, "msg", msg) - return - } - var tips sdkws.MarkAsReadTips - if err := json.Unmarshal([]byte(elem.Detail), &tips); err != nil { - log.ZError(ctx, "handlerConversationRead Unmarshal MarkAsReadTips msg err", err, "msg", msg) - return - } - if len(tips.Seqs) > 0 { - for _, seq := range tips.Seqs { - if tips.HasReadSeq < seq { - tips.HasReadSeq = seq - } - } - clear(tips.Seqs) - tips.Seqs = nil - } - if tips.HasReadSeq < 0 { - return - } - select { - case c.readCh <- &tips: - default: - log.ZWarn(ctx, "handlerConversationRead readCh is full", nil, "markAsReadTips", &tips) - } -} - func (c *ConsumerHandler) Push2Group(ctx context.Context, groupID string, msg *sdkws.MsgData) (err error) { log.ZDebug(ctx, "Get group msg from msg_transfer and push msg", "msg", msg.String(), "groupID", groupID) var pushToUserIDs []string diff --git a/internal/rpc/msg/as_read.go b/internal/rpc/msg/as_read.go index 9a3174e8ef..bfba4824fe 100644 --- a/internal/rpc/msg/as_read.go +++ b/internal/rpc/msg/as_read.go @@ -80,16 +80,10 @@ func (m *msgServer) SetConversationHasReadSeq(ctx context.Context, req *msg.SetC if req.HasReadSeq > maxSeq { return nil, errs.ErrArgs.WrapMsg("hasReadSeq must not be bigger than maxSeq") } - if req.NoNotification { - if err := m.MsgDatabase.SetHasReadSeqToDB(ctx, req.UserID, req.ConversationID, req.HasReadSeq); err != nil { - return nil, err - } - } else { - if err := m.MsgDatabase.SetHasReadSeq(ctx, req.UserID, req.ConversationID, req.HasReadSeq); err != nil { - return nil, err - } - m.sendMarkAsReadNotification(ctx, req.ConversationID, constant.SingleChatType, req.UserID, req.UserID, nil, req.HasReadSeq) + if err := m.MsgDatabase.SetHasReadSeq(ctx, req.UserID, req.ConversationID, req.HasReadSeq); err != nil { + return nil, err } + m.sendMarkAsReadNotification(ctx, req.ConversationID, constant.SingleChatType, req.UserID, req.UserID, nil, req.HasReadSeq) return &msg.SetConversationHasReadSeqResp{}, nil } diff --git a/pkg/common/storage/cache/redis/seq_user.go b/pkg/common/storage/cache/redis/seq_user.go index 5458b6594b..0cedfeee12 100644 --- a/pkg/common/storage/cache/redis/seq_user.go +++ b/pkg/common/storage/cache/redis/seq_user.go @@ -73,18 +73,23 @@ func (s *seqUserCacheRedis) GetUserReadSeq(ctx context.Context, conversationID s }) } -func (s *seqUserCacheRedis) SetUserReadSeq(ctx context.Context, conversationID string, userID string, seq int64, writeDB bool) error { - if err := s.rocks.RawSet(ctx, s.getSeqUserReadSeqKey(conversationID, userID), strconv.Itoa(int(seq)), s.readExpireTime); err != nil { - return errs.Wrap(err) +func (s *seqUserCacheRedis) SetUserReadSeq(ctx context.Context, conversationID string, userID string, seq int64) error { + dbSeq, err := s.GetUserReadSeq(ctx, conversationID, userID) + if err != nil { + return err } - if writeDB { - if err := s.mgo.SetUserReadSeq(ctx, conversationID, userID, seq); err != nil { - return err + if dbSeq < seq { + if err := s.rocks.RawSet(ctx, s.getSeqUserReadSeqKey(conversationID, userID), strconv.Itoa(int(seq)), s.readExpireTime); err != nil { + return errs.Wrap(err) } } return nil } +func (s *seqUserCacheRedis) SetUserReadSeqToDB(ctx context.Context, conversationID string, userID string, seq int64) error { + return s.mgo.SetUserReadSeq(ctx, conversationID, userID, seq) +} + func (s *seqUserCacheRedis) SetUserMinSeqs(ctx context.Context, userID string, seqs map[string]int64) error { keys := make([]string, 0, len(seqs)) for conversationID, seq := range seqs { @@ -128,13 +133,6 @@ func (s *seqUserCacheRedis) SetUserReadSeqs(ctx context.Context, userID string, if err := s.setUserRedisReadSeqs(ctx, userID, seqs); err != nil { return err } - for conversationID, seq := range seqs { - if seq%s.readSeqWriteRatio == 0 { - if err := s.mgo.SetUserReadSeq(ctx, conversationID, userID, seq); err != nil { - return err - } - } - } return nil } diff --git a/pkg/common/storage/cache/seq_user.go b/pkg/common/storage/cache/seq_user.go index 5bb9cad043..cef414e16e 100644 --- a/pkg/common/storage/cache/seq_user.go +++ b/pkg/common/storage/cache/seq_user.go @@ -8,7 +8,8 @@ type SeqUser interface { GetUserMinSeq(ctx context.Context, conversationID string, userID string) (int64, error) SetUserMinSeq(ctx context.Context, conversationID string, userID string, seq int64) error GetUserReadSeq(ctx context.Context, conversationID string, userID string) (int64, error) - SetUserReadSeq(ctx context.Context, conversationID string, userID string, seq int64, writeDB bool) error + SetUserReadSeq(ctx context.Context, conversationID string, userID string, seq int64) error + SetUserReadSeqToDB(ctx context.Context, conversationID string, userID string, seq int64) error SetUserMinSeqs(ctx context.Context, userID string, seqs map[string]int64) error SetUserReadSeqs(ctx context.Context, userID string, seqs map[string]int64) error GetUserReadSeqs(ctx context.Context, userID string, conversationIDs []string) (map[string]int64, error) diff --git a/pkg/common/storage/controller/msg.go b/pkg/common/storage/controller/msg.go index 6a75afcb12..7f884165de 100644 --- a/pkg/common/storage/controller/msg.go +++ b/pkg/common/storage/controller/msg.go @@ -338,7 +338,7 @@ func (db *commonMsgDatabase) DeleteMessagesFromCache(ctx context.Context, conver func (db *commonMsgDatabase) setHasReadSeqs(ctx context.Context, conversationID string, userSeqMap map[string]int64) error { for userID, seq := range userSeqMap { - if err := db.seqUser.SetUserReadSeq(ctx, conversationID, userID, seq, false); err != nil { + if err := db.seqUser.SetUserReadSeq(ctx, conversationID, userID, seq); err != nil { return err } } @@ -806,11 +806,11 @@ func (db *commonMsgDatabase) UserSetHasReadSeqs(ctx context.Context, userID stri } func (db *commonMsgDatabase) SetHasReadSeq(ctx context.Context, userID string, conversationID string, hasReadSeq int64) error { - return db.seqUser.SetUserReadSeq(ctx, conversationID, userID, hasReadSeq, false) + return db.seqUser.SetUserReadSeq(ctx, conversationID, userID, hasReadSeq) } func (db *commonMsgDatabase) SetHasReadSeqToDB(ctx context.Context, userID string, conversationID string, hasReadSeq int64) error { - return db.seqUser.SetUserReadSeq(ctx, conversationID, userID, hasReadSeq, true) + return db.seqUser.SetUserReadSeqToDB(ctx, conversationID, userID, hasReadSeq) } func (db *commonMsgDatabase) GetHasReadSeqs(ctx context.Context, userID string, conversationIDs []string) (map[string]int64, error) { diff --git a/pkg/common/storage/database/mgo/seq_user.go b/pkg/common/storage/database/mgo/seq_user.go index 9faad416ae..244de30000 100644 --- a/pkg/common/storage/database/mgo/seq_user.go +++ b/pkg/common/storage/database/mgo/seq_user.go @@ -115,5 +115,12 @@ func (s *seqUserMongo) GetUserReadSeqs(ctx context.Context, userID string, conve } func (s *seqUserMongo) SetUserReadSeq(ctx context.Context, conversationID string, userID string, seq int64) error { + dbSeq, err := s.GetUserReadSeq(ctx, conversationID, userID) + if err != nil { + return err + } + if dbSeq > seq { + return nil + } return s.setSeq(ctx, conversationID, userID, seq, "read_seq") } From 12bbd88a75585653bdaaf796291651b3cd0c8088 Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Mon, 26 Aug 2024 18:39:41 +0800 Subject: [PATCH 26/27] read seq is written to mongo --- cmd/openim-msgtransfer/main.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cmd/openim-msgtransfer/main.go b/cmd/openim-msgtransfer/main.go index a3a14def8c..23b629d69a 100644 --- a/cmd/openim-msgtransfer/main.go +++ b/cmd/openim-msgtransfer/main.go @@ -17,13 +17,9 @@ package main import ( "github.com/openimsdk/open-im-server/v3/pkg/common/cmd" "github.com/openimsdk/tools/system/program" - "os" ) func main() { - if len(os.Args) == 1 { - os.Args = append(os.Args, "-i", "0", "-c", "/Users/chao/Desktop/withchao/open-im-server/config/") - } if err := cmd.NewMsgTransferCmd().Exec(); err != nil { program.ExitWithError(err) } From e7a4ef38f2a59fbd2f2b64d9a3786f5f04430165 Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Tue, 27 Aug 2024 12:12:06 +0800 Subject: [PATCH 27/27] fix: invitation to join group notification --- internal/rpc/group/notification.go | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/internal/rpc/group/notification.go b/internal/rpc/group/notification.go index 44eb6f9e32..e87e7c495b 100644 --- a/internal/rpc/group/notification.go +++ b/internal/rpc/group/notification.go @@ -535,7 +535,28 @@ func (g *GroupNotificationSender) MemberEnterNotification(ctx context.Context, g if err := g.conversationRpcClient.GroupChatFirstCreateConversation(ctx, groupID, entrantUserID); err != nil { return err } - + opUserID := mcontext.GetOpUserID(ctx) + var opUser *sdkws.GroupMemberFullInfo + if authverify.IsAppManagerUid(ctx, g.config.Share.IMAdminUserID) { + opUser = &sdkws.GroupMemberFullInfo{ + GroupID: groupID, + UserID: opUserID, + AppMangerLevel: constant.AppAdmin, + } + } else { + users, err := g.getGroupMembers(ctx, groupID, []string{opUserID}) + if err != nil { + return err + } + if len(users) == 0 { + opUser = &sdkws.GroupMemberFullInfo{ + GroupID: groupID, + UserID: opUserID, + } + } else { + opUser = users[0] + } + } var group *sdkws.GroupInfo group, err = g.getGroupInfo(ctx, groupID) if err != nil { @@ -545,7 +566,7 @@ func (g *GroupNotificationSender) MemberEnterNotification(ctx context.Context, g if err != nil { return err } - tips := &sdkws.MemberInvitedTips{Group: group, InvitedUserList: users} + tips := &sdkws.MemberInvitedTips{Group: group, InvitedUserList: users, OpUser: opUser} g.setVersion(ctx, &tips.GroupMemberVersion, &tips.GroupMemberVersionID, database.GroupMemberVersionName, tips.Group.GroupID) g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.MemberInvitedNotification, tips) return nil