diff --git a/cmd/api/main.go b/cmd/api/main.go index e559445ab..48ff83206 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -17,7 +17,7 @@ import ( "github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/cache" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/log" "github.com/OpenIMSDK/Open-IM-Server/pkg/discoveryregistry" - "github.com/OpenIMSDK/openKeeper" + openKeeper "github.com/OpenIMSDK/Open-IM-Server/pkg/discoveryregistry/zookeeper" ) func main() { diff --git a/internal/api/auth.go b/internal/api/auth.go index aeda676ab..c2488f91c 100644 --- a/internal/api/auth.go +++ b/internal/api/auth.go @@ -5,25 +5,28 @@ import ( "github.com/OpenIMSDK/Open-IM-Server/pkg/a2r" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/config" + "github.com/OpenIMSDK/Open-IM-Server/pkg/common/log" "github.com/OpenIMSDK/Open-IM-Server/pkg/discoveryregistry" "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/auth" "github.com/gin-gonic/gin" + "google.golang.org/grpc" ) func NewAuth(c discoveryregistry.SvcDiscoveryRegistry) *Auth { - return &Auth{c: c} + conn, err := c.GetConn(context.Background(), config.Config.RpcRegisterName.OpenImAuthName) + if err != nil { + panic(err) + } + log.ZInfo(context.Background(), "auth rpc conn", "conn", conn) + return &Auth{conn: conn} } type Auth struct { - c discoveryregistry.SvcDiscoveryRegistry + conn *grpc.ClientConn } func (o *Auth) client(ctx context.Context) (auth.AuthClient, error) { - conn, err := o.c.GetConn(ctx, config.Config.RpcRegisterName.OpenImAuthName) - if err != nil { - return nil, err - } - return auth.NewAuthClient(conn), nil + return auth.NewAuthClient(o.conn), nil } func (o *Auth) UserRegister(c *gin.Context) { diff --git a/internal/api/conversation.go b/internal/api/conversation.go index dafdfe33b..ca4bb8690 100644 --- a/internal/api/conversation.go +++ b/internal/api/conversation.go @@ -8,22 +8,23 @@ import ( "github.com/OpenIMSDK/Open-IM-Server/pkg/discoveryregistry" "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/conversation" "github.com/gin-gonic/gin" + "google.golang.org/grpc" ) func NewConversation(c discoveryregistry.SvcDiscoveryRegistry) *Conversation { - return &Conversation{c: c} + conn, err := c.GetConn(context.Background(), config.Config.RpcRegisterName.OpenImConversationName) + if err != nil { + panic(err) + } + return &Conversation{conn: conn} } type Conversation struct { - c discoveryregistry.SvcDiscoveryRegistry + conn *grpc.ClientConn } func (o *Conversation) client(ctx context.Context) (conversation.ConversationClient, error) { - conn, err := o.c.GetConn(ctx, config.Config.RpcRegisterName.OpenImConversationName) - if err != nil { - return nil, err - } - return conversation.NewConversationClient(conn), nil + return conversation.NewConversationClient(o.conn), nil } func (o *Conversation) GetAllConversations(c *gin.Context) { diff --git a/internal/api/friend.go b/internal/api/friend.go index 42d700a06..2d4e4bbff 100644 --- a/internal/api/friend.go +++ b/internal/api/friend.go @@ -7,24 +7,25 @@ import ( "github.com/OpenIMSDK/Open-IM-Server/pkg/common/config" "github.com/OpenIMSDK/Open-IM-Server/pkg/discoveryregistry" "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/friend" + "google.golang.org/grpc" "github.com/gin-gonic/gin" ) func NewFriend(c discoveryregistry.SvcDiscoveryRegistry) *Friend { - return &Friend{c: c} + conn, err := c.GetConn(context.Background(), config.Config.RpcRegisterName.OpenImFriendName) + if err != nil { + panic(err) + } + return &Friend{conn: conn} } type Friend struct { - c discoveryregistry.SvcDiscoveryRegistry + conn *grpc.ClientConn } func (o *Friend) client(ctx context.Context) (friend.FriendClient, error) { - conn, err := o.c.GetConn(ctx, config.Config.RpcRegisterName.OpenImFriendName) - if err != nil { - return nil, err - } - return friend.NewFriendClient(conn), nil + return friend.NewFriendClient(o.conn), nil } func (o *Friend) ApplyToAddFriend(c *gin.Context) { diff --git a/internal/api/group.go b/internal/api/group.go index b0c84654c..e007a4ee2 100644 --- a/internal/api/group.go +++ b/internal/api/group.go @@ -5,28 +5,27 @@ import ( "github.com/OpenIMSDK/Open-IM-Server/pkg/a2r" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/config" - "github.com/OpenIMSDK/Open-IM-Server/pkg/common/log" "github.com/OpenIMSDK/Open-IM-Server/pkg/discoveryregistry" "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/group" + "google.golang.org/grpc" "github.com/gin-gonic/gin" ) func NewGroup(c discoveryregistry.SvcDiscoveryRegistry) *Group { - return &Group{c: c} + conn, err := c.GetConn(context.Background(), config.Config.RpcRegisterName.OpenImGroupName) + if err != nil { + panic(err) + } + return &Group{conn: conn} } type Group struct { - c discoveryregistry.SvcDiscoveryRegistry + conn *grpc.ClientConn } func (o *Group) client(ctx context.Context) (group.GroupClient, error) { - conn, err := o.c.GetConn(ctx, config.Config.RpcRegisterName.OpenImGroupName) - if err != nil { - return nil, err - } - log.ZDebug(ctx, "get conn", "local", o.c.GetClientLocalConns()) - return group.NewGroupClient(conn), nil + return group.NewGroupClient(o.conn), nil } func (o *Group) NewCreateGroup(c *gin.Context) { diff --git a/internal/api/msg.go b/internal/api/msg.go index 2b29371b1..7a21ff5b9 100644 --- a/internal/api/msg.go +++ b/internal/api/msg.go @@ -17,15 +17,20 @@ import ( "github.com/gin-gonic/gin" "github.com/go-playground/validator/v10" "github.com/mitchellh/mapstructure" + "google.golang.org/grpc" "google.golang.org/protobuf/proto" ) func NewMsg(c discoveryregistry.SvcDiscoveryRegistry) *Message { - return &Message{c: c, validate: validator.New()} + conn, err := c.GetConn(context.Background(), config.Config.RpcRegisterName.OpenImMsgName) + if err != nil { + panic(err) + } + return &Message{conn: conn, validate: validator.New()} } type Message struct { - c discoveryregistry.SvcDiscoveryRegistry + conn *grpc.ClientConn validate *validator.Validate } @@ -104,11 +109,7 @@ func (m Message) newUserSendMsgReq(c *gin.Context, params *apistruct.ManagementS } func (m *Message) client(ctx context.Context) (msg.MsgClient, error) { - conn, err := m.c.GetConn(ctx, config.Config.RpcRegisterName.OpenImMsgName) - if err != nil { - return nil, err - } - return msg.NewMsgClient(conn), nil + return msg.NewMsgClient(m.conn), nil } func (m *Message) GetSeq(c *gin.Context) { @@ -208,12 +209,7 @@ func (m *Message) SendMessage(c *gin.Context) { return } pbReq := m.newUserSendMsgReq(c, ¶ms) - conn, err := m.c.GetConn(c, config.Config.RpcRegisterName.OpenImMsgName) - if err != nil { - apiresp.GinError(c, errs.ErrInternalServer) - return - } - client := msg.NewMsgClient(conn) + client := msg.NewMsgClient(m.conn) var status int respPb, err := client.SendMsg(c, pbReq) if err != nil { diff --git a/internal/api/route.go b/internal/api/route.go index 9fbcd5575..70483e510 100644 --- a/internal/api/route.go +++ b/internal/api/route.go @@ -16,8 +16,8 @@ import ( "google.golang.org/grpc/credentials/insecure" ) -func NewGinRouter(zk discoveryregistry.SvcDiscoveryRegistry, rdb redis.UniversalClient) *gin.Engine { - zk.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials())) // 默认RPC中间件 +func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.UniversalClient) *gin.Engine { + discov.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials())) // 默认RPC中间件 gin.SetMode(gin.ReleaseMode) //f, _ := os.Create("../logs/api.log") //gin.DefaultWriter = io.MultiWriter(f) @@ -37,7 +37,7 @@ func NewGinRouter(zk discoveryregistry.SvcDiscoveryRegistry, rdb redis.Universal } userRouterGroup := r.Group("/user") { - u := NewUser(zk) + u := NewUser(discov) userRouterGroupChild := mw.NewRouterGroup(userRouterGroup, "") userRouterGroupChildToken := mw.NewRouterGroup(userRouterGroup, "", mw.WithGinParseToken(rdb)) userRouterGroupChild.POST("/user_register", u.UserRegister) @@ -52,7 +52,7 @@ func NewGinRouter(zk discoveryregistry.SvcDiscoveryRegistry, rdb redis.Universal //friend routing group friendRouterGroup := r.Group("/friend") { - f := NewFriend(zk) + f := NewFriend(discov) friendRouterGroup.Use(mw.GinParseToken(rdb)) friendRouterGroup.POST("/delete_friend", f.DeleteFriend) //1 friendRouterGroup.POST("/get_friend_apply_list", f.GetFriendApplyList) //1 @@ -67,7 +67,7 @@ func NewGinRouter(zk discoveryregistry.SvcDiscoveryRegistry, rdb redis.Universal friendRouterGroup.POST("/import_friend", f.ImportFriends) //1 friendRouterGroup.POST("/is_friend", f.IsFriend) //1 } - g := NewGroup(zk) + g := NewGroup(discov) groupRouterGroup := r.Group("/group") { @@ -105,8 +105,8 @@ func NewGinRouter(zk discoveryregistry.SvcDiscoveryRegistry, rdb redis.Universal ////certificate authRouterGroup := r.Group("/auth") { - a := NewAuth(zk) - u := NewUser(zk) + a := NewAuth(discov) + u := NewUser(discov) authRouterGroupChild := mw.NewRouterGroup(authRouterGroup, "") authRouterGroupChildToken := mw.NewRouterGroup(authRouterGroup, "", mw.WithGinParseToken(rdb)) authRouterGroupChild.POST("/user_register", u.UserRegister) //1 @@ -117,7 +117,7 @@ func NewGinRouter(zk discoveryregistry.SvcDiscoveryRegistry, rdb redis.Universal ////Third service thirdGroup := r.Group("/third") { - t := NewThird(zk) + t := NewThird(discov) thirdGroup.Use(mw.GinParseToken(rdb)) thirdGroup.POST("/get_rtc_invitation_info", t.GetSignalInvitationInfo) thirdGroup.POST("/get_rtc_invitation_start_app", t.GetSignalInvitationInfoStartApp) @@ -134,7 +134,7 @@ func NewGinRouter(zk discoveryregistry.SvcDiscoveryRegistry, rdb redis.Universal ////Message msgGroup := r.Group("/msg") { - m := NewMsg(zk) + m := NewMsg(discov) msgGroup.Use(mw.GinParseToken(rdb)) msgGroup.POST("/newest_seq", m.GetSeq) msgGroup.POST("/send_msg", m.SendMessage) @@ -158,7 +158,7 @@ func NewGinRouter(zk discoveryregistry.SvcDiscoveryRegistry, rdb redis.Universal ////Conversation conversationGroup := r.Group("/conversation") { - c := NewConversation(zk) + c := NewConversation(discov) conversationGroup.Use(mw.GinParseToken(rdb)) conversationGroup.POST("/get_all_conversations", c.GetAllConversations) conversationGroup.POST("/get_conversation", c.GetConversation) diff --git a/internal/api/third.go b/internal/api/third.go index aa107291c..cdb2e08d6 100644 --- a/internal/api/third.go +++ b/internal/api/third.go @@ -14,22 +14,23 @@ import ( "github.com/OpenIMSDK/Open-IM-Server/pkg/errs" "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/third" "github.com/gin-gonic/gin" + "google.golang.org/grpc" ) -func NewThird(c discoveryregistry.SvcDiscoveryRegistry) *Third { - return &Third{c: c} +func NewThird(discov discoveryregistry.SvcDiscoveryRegistry) *Third { + conn, err := discov.GetConn(context.Background(), config.Config.RpcRegisterName.OpenImThirdName) + if err != nil { + panic(err) + } + return &Third{conn: conn} } type Third struct { - c discoveryregistry.SvcDiscoveryRegistry + conn *grpc.ClientConn } func (o *Third) client(ctx context.Context) (third.ThirdClient, error) { - conn, err := o.c.GetConn(ctx, config.Config.RpcRegisterName.OpenImThirdName) - if err != nil { - return nil, err - } - return third.NewThirdClient(conn), nil + return third.NewThirdClient(o.conn), nil } func (o *Third) ApplyPut(c *gin.Context) { diff --git a/internal/api/user.go b/internal/api/user.go index 0762a5ba6..d9b6e0dcf 100644 --- a/internal/api/user.go +++ b/internal/api/user.go @@ -5,8 +5,10 @@ import ( "github.com/OpenIMSDK/Open-IM-Server/pkg/apiresp" "github.com/OpenIMSDK/Open-IM-Server/pkg/apistruct" + "github.com/OpenIMSDK/Open-IM-Server/pkg/common/log" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/tokenverify" "github.com/OpenIMSDK/Open-IM-Server/pkg/errs" + "google.golang.org/grpc" "github.com/OpenIMSDK/Open-IM-Server/pkg/a2r" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/config" @@ -15,20 +17,22 @@ import ( "github.com/gin-gonic/gin" ) -func NewUser(client discoveryregistry.SvcDiscoveryRegistry) *User { - return &User{c: client} +func NewUser(discov discoveryregistry.SvcDiscoveryRegistry) *User { + conn, err := discov.GetConn(context.Background(), config.Config.RpcRegisterName.OpenImUserName) + if err != nil { + panic(err) + } + log.ZInfo(context.Background(), "user rpc conn", "conn", conn) + + return &User{conn: conn} } type User struct { - c discoveryregistry.SvcDiscoveryRegistry + conn *grpc.ClientConn } func (u *User) client(ctx context.Context) (user.UserClient, error) { - conn, err := u.c.GetConn(ctx, config.Config.RpcRegisterName.OpenImUserName) - if err != nil { - return nil, err - } - return user.NewUserClient(conn), nil + return user.NewUserClient(u.conn), nil } func (u *User) UserRegister(c *gin.Context) { @@ -58,6 +62,7 @@ func (u *User) AccountCheck(c *gin.Context) { func (u *User) GetUsers(c *gin.Context) { a2r.Call(user.UserClient.GetPaginationUsers, u.client, c) } + func (u *User) GetUsersOnlineStatus(c *gin.Context) { params := apistruct.ManagementSendMsgReq{} if err := c.BindJSON(¶ms); err != nil { @@ -68,5 +73,4 @@ func (u *User) GetUsersOnlineStatus(c *gin.Context) { apiresp.GinError(c, errs.ErrNoPermission.Wrap("only app manager can send message")) return } - } diff --git a/internal/msgtransfer/init.go b/internal/msgtransfer/init.go index e7595bc99..82ee5842b 100644 --- a/internal/msgtransfer/init.go +++ b/internal/msgtransfer/init.go @@ -14,8 +14,8 @@ import ( "github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/unrelation" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/mw" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/prome" + openKeeper "github.com/OpenIMSDK/Open-IM-Server/pkg/discoveryregistry/zookeeper" "github.com/OpenIMSDK/Open-IM-Server/pkg/rpcclient" - "github.com/OpenIMSDK/openKeeper" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) diff --git a/internal/rpc/conversation/conversaion.go b/internal/rpc/conversation/conversaion.go index 99a18baac..3fed381ba 100644 --- a/internal/rpc/conversation/conversaion.go +++ b/internal/rpc/conversation/conversaion.go @@ -322,3 +322,11 @@ func (c *conversationServer) GetUserConversationIDsHash(ctx context.Context, req } return &pbConversation.GetUserConversationIDsHashResp{Hash: hash}, nil } + +func (c *conversationServer) GetConversationByConversationID(ctx context.Context, req *pbConversation.GetConversationByConversationIDReq) (*pbConversation.GetConversationByConversationIDResp, error) { + conversation, err := c.conversationDatabase.GetConversationByConversationID(ctx, req.ConversationID) + if err != nil { + return nil, err + } + return &pbConversation.GetConversationByConversationIDResp{Conversation: convert.ConversationDB2Pb(conversation)}, nil +} diff --git a/internal/rpc/group/group.go b/internal/rpc/group/group.go index f917763d4..d22b8a909 100644 --- a/internal/rpc/group/group.go +++ b/internal/rpc/group/group.go @@ -54,12 +54,12 @@ func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e pbGroup.RegisterGroupServer(server, &groupServer{ GroupDatabase: database, User: user, - Notification: notification.NewGroupNotificationSender(database, client, func(ctx context.Context, userIDs []string) ([]rpcclient.CommonUser, error) { + Notification: notification.NewGroupNotificationSender(database, client, func(ctx context.Context, userIDs []string) ([]notification.CommonUser, error) { users, err := user.GetUsersInfo(ctx, userIDs) if err != nil { return nil, err } - return utils.Slice(users, func(e *sdkws.UserInfo) rpcclient.CommonUser { return e }), nil + return utils.Slice(users, func(e *sdkws.UserInfo) notification.CommonUser { return e }), nil }), conversationRpcClient: rpcclient.NewConversationClient(client), msgRpcClient: rpcclient.NewMsgClient(client), diff --git a/internal/rpc/msg/delete.go b/internal/rpc/msg/delete.go index b0a18b999..572dc1160 100644 --- a/internal/rpc/msg/delete.go +++ b/internal/rpc/msg/delete.go @@ -3,9 +3,12 @@ package msg import ( "context" + "github.com/OpenIMSDK/Open-IM-Server/pkg/common/constant" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/log" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/tokenverify" "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/msg" + "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/sdkws" + "google.golang.org/protobuf/proto" ) func (m *msgServer) getMinSeqs(maxSeqs map[string]int64) map[string]int64 { @@ -27,6 +30,7 @@ func (m *msgServer) ClearConversationsMsg(ctx context.Context, req *msg.ClearCon if err := m.MsgDatabase.SetUserConversationsMinSeqs(ctx, req.UserID, m.getMinSeqs(maxSeqs)); err != nil { return nil, err } + m.conversationClearSync(ctx, req.DeleteSyncOpt, req.UserID, req.ConversationIDs) return &msg.ClearConversationsMsgResp{}, nil } @@ -46,6 +50,7 @@ func (m *msgServer) UserClearAllMsg(ctx context.Context, req *msg.UserClearAllMs if err := m.MsgDatabase.SetUserConversationsMinSeqs(ctx, req.UserID, m.getMinSeqs(maxSeqs)); err != nil { return nil, err } + m.conversationClearSync(ctx, req.DeleteSyncOpt, req.UserID, conversationIDs) return &msg.UserClearAllMsgResp{}, nil } @@ -56,6 +61,7 @@ func (m *msgServer) DeleteMsgs(ctx context.Context, req *msg.DeleteMsgsReq) (*ms if err := m.MsgDatabase.DeleteUserMsgsBySeqs(ctx, req.UserID, req.ConversationID, req.Seqs); err != nil { return nil, err } + m.DeleteMsgsNotification(ctx, req.ConversationID, req.UserID, req.Seqs, req.DeleteSyncOpt) return &msg.DeleteMsgsResp{}, nil } @@ -78,3 +84,53 @@ func (m *msgServer) DeleteMsgPhysical(ctx context.Context, req *msg.DeleteMsgPhy } return &msg.DeleteMsgPhysicalResp{}, nil } + +func (m *msgServer) conversationClearSync(ctx context.Context, opt *msg.DeleteSyncOpt, userID string, conversationIDs []string) { + if opt == nil { + return + } + if opt.IsSyncSelf { + tips := &sdkws.ClearConversationTips{UserID: userID, ConversationIDs: conversationIDs} + m.notificationSender.Notification(ctx, userID, userID, constant.ClearConversationNotification, tips) + } + if opt.IsSyncOther { + for _, conversationID := range conversationIDs { + m.getConversationAndNotification(ctx, conversationID, userID, &sdkws.ClearConversationTips{UserID: userID, ConversationIDs: []string{conversationID}}) + } + } +} + +func (m *msgServer) DeleteMsgsNotification(ctx context.Context, conversationID, userID string, seqs []int64, opt *msg.DeleteSyncOpt) { + if opt == nil { + return + } + if opt.IsSyncSelf { + tips := &sdkws.DeleteMsgsTips{UserID: userID, ConversationID: conversationID, Seqs: seqs} + m.notificationSender.Notification(ctx, userID, userID, constant.DeleteMsgsNotification, tips) + } + if opt.IsSyncOther { + m.getConversationAndNotification(ctx, conversationID, userID, &sdkws.DeleteMsgsTips{UserID: userID, ConversationID: conversationID, Seqs: seqs}) + } +} + +func (m *msgServer) getConversationAndNotification(ctx context.Context, conversationID, userID string, tips proto.Message) { + conversation, err := m.Conversation.GetConversationByConversationID(ctx, conversationID) + if err != nil { + log.ZWarn(ctx, "GetConversation error", err, "conversationID", conversationID, "userID", userID) + return + } + if conversation.ConversationType == constant.SingleChatType || conversation.ConversationType == constant.NotificationChatType { + var recvID string + if conversation.OwnerUserID == userID { + recvID = conversation.UserID + } else if conversation.UserID == userID { + recvID = conversation.OwnerUserID + } else { + log.ZWarn(ctx, "invalid recvID", nil, "conversation", conversation) + return + } + m.notificationSender.Notification(ctx, userID, recvID, constant.DeleteMsgsNotification, tips) + } else if conversation.ConversationType == constant.SuperGroupChatType { + m.notificationSender.Notification(ctx, userID, conversation.GroupID, constant.DeleteMsgsNotification, tips) + } +} diff --git a/internal/rpc/msg/revoke.go b/internal/rpc/msg/revoke.go index b4cc06b6a..3bfb200c9 100644 --- a/internal/rpc/msg/revoke.go +++ b/internal/rpc/msg/revoke.go @@ -5,7 +5,6 @@ import ( "encoding/json" "time" - "github.com/OpenIMSDK/Open-IM-Server/pkg/common/config" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/constant" unRelationTb "github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/table/unrelation" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/log" @@ -34,11 +33,11 @@ func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq) (*msg. if err != nil { return nil, err } - msgs, err := m.MsgDatabase.GetMsgBySeqs(ctx, req.UserID, req.ConversationID, []int64{req.Seq}) + _, msgs, err := m.MsgDatabase.GetMsgBySeqs(ctx, req.UserID, req.ConversationID, []int64{req.Seq}) if err != nil { return nil, err } - if len(msgs) == 0 { + if len(msgs) == 0 || msgs[0] == nil { return nil, errs.ErrRecordNotFound.Wrap("msg not found") } if msgs[0].SendID == "" || msgs[0].RecvID == "" { @@ -82,6 +81,7 @@ func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq) (*msg. if err != nil { return nil, err } + tips := sdkws.RevokeMsgTips{ RevokerUserID: req.UserID, ClientMsgID: "", @@ -90,36 +90,13 @@ func (m *msgServer) RevokeMsg(ctx context.Context, req *msg.RevokeMsgReq) (*msg. SesstionType: msgs[0].SessionType, ConversationID: req.ConversationID, } - detail, err := json.Marshal(&tips) - if err != nil { - return nil, err + var recvID string + if msgs[0].SessionType == constant.SuperGroupChatType { + recvID = msgs[0].GroupID + } else { + recvID = msgs[0].RecvID } - notificationElem := sdkws.NotificationElem{Detail: string(detail)} - content, err := json.Marshal(¬ificationElem) - if err != nil { - return nil, errs.Wrap(err) - } - msgData := sdkws.MsgData{ - SendID: req.UserID, - RecvID: msgs[0].RecvID, - GroupID: msgs[0].GroupID, - Content: content, - MsgFrom: constant.SysMsgType, - ContentType: constant.MsgRevokeNotification, - SessionType: msgs[0].SessionType, - CreateTime: utils.GetCurrentTimestampByMill(), - ClientMsgID: utils.GetMsgID(req.UserID), - Options: config.GetOptionsByNotification(config.NotificationConf{ - IsSendMsg: false, - ReliabilityLevel: 2, - }), - OfflinePushInfo: nil, - } - if msgData.SessionType == constant.SuperGroupChatType { - msgData.GroupID = msgData.RecvID - } - _, err = m.SendMsg(ctx, &msg.SendMsgReq{MsgData: &msgData}) - if err != nil { + if err := m.notificationSender.NotificationWithSesstionType(ctx, req.UserID, recvID, constant.MsgRevokeNotification, msgs[0].SessionType, &tips); err != nil { return nil, err } return &msg.RevokeMsgResp{}, nil diff --git a/internal/rpc/msg/server.go b/internal/rpc/msg/server.go index a6e95bdd0..f51ed2c2a 100644 --- a/internal/rpc/msg/server.go +++ b/internal/rpc/msg/server.go @@ -29,6 +29,7 @@ type msgServer struct { ConversationLocalCache *localcache.ConversationLocalCache MessageLocker MessageLocker Handlers MessageInterceptorChain + notificationSender *rpcclient.NotificationSender } func (m *msgServer) addInterceptorHandler(interceptorFunc ...MessageInterceptorFunc) { @@ -64,7 +65,6 @@ func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e extendMsgCacheModel := cache.NewExtendMsgSetCacheRedis(rdb, extendMsgModel, cache.GetDefaultOpt()) extendMsgDatabase := controller.NewExtendMsgDatabase(extendMsgModel, extendMsgCacheModel, tx.NewMongo(mongo.GetClient())) msgDatabase := controller.NewCommonMsgDatabase(msgDocModel, cacheModel) - s := &msgServer{ Conversation: rpcclient.NewConversationClient(client), User: rpcclient.NewUserClient(client), @@ -78,6 +78,7 @@ func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e friend: rpcclient.NewFriendClient(client), MessageLocker: NewLockerMessage(cacheModel), } + s.notificationSender = rpcclient.NewNotificationSender(rpcclient.WithLocalSendMsg(s.SendMsg)) s.addInterceptorHandler(MessageHasReadEnabled, MessageModifyCallback) s.initPrometheus() msg.RegisterMsgServer(server, s) diff --git a/internal/rpc/msg/sync_msg.go b/internal/rpc/msg/sync_msg.go index bf2beb6fc..6c45198cb 100644 --- a/internal/rpc/msg/sync_msg.go +++ b/internal/rpc/msg/sync_msg.go @@ -15,23 +15,23 @@ func (m *msgServer) PullMessageBySeqs(ctx context.Context, req *sdkws.PullMessag resp.NotificationMsgs = make(map[string]*sdkws.PullMsgs) for _, seq := range req.SeqRanges { if !utils.IsNotification(seq.ConversationID) { - msgs, err := m.MsgDatabase.GetMsgBySeqsRange(ctx, req.UserID, seq.ConversationID, seq.Begin, seq.End, seq.Num) + minSeq, msgs, err := m.MsgDatabase.GetMsgBySeqsRange(ctx, req.UserID, seq.ConversationID, seq.Begin, seq.End, seq.Num) if err != nil { log.ZWarn(ctx, "GetMsgBySeqsRange error", err, "conversationID", seq.ConversationID, "seq", seq) continue } - resp.Msgs[seq.ConversationID] = &sdkws.PullMsgs{Msgs: msgs} + resp.Msgs[seq.ConversationID] = &sdkws.PullMsgs{Msgs: msgs, MinSeq: minSeq} } else { var seqs []int64 for i := seq.Begin; i <= seq.End; i++ { seqs = append(seqs, i) } - notificationMsgs, err := m.MsgDatabase.GetMsgBySeqs(ctx, req.UserID, seq.ConversationID, seqs) + minSeq, notificationMsgs, err := m.MsgDatabase.GetMsgBySeqs(ctx, req.UserID, seq.ConversationID, seqs) if err != nil { log.ZWarn(ctx, "GetMsgBySeqs error", err, "conversationID", seq.ConversationID, "seq", seq) continue } - resp.NotificationMsgs[seq.ConversationID] = &sdkws.PullMsgs{Msgs: notificationMsgs} + resp.NotificationMsgs[seq.ConversationID] = &sdkws.PullMsgs{Msgs: notificationMsgs, MinSeq: minSeq} } } return resp, nil diff --git a/pkg/a2r/api2rpc.go b/pkg/a2r/api2rpc.go index 7c21961e9..2c5b05cf7 100644 --- a/pkg/a2r/api2rpc.go +++ b/pkg/a2r/api2rpc.go @@ -28,12 +28,14 @@ func Call[A, B, C any]( return } } + log.ZDebug(c, "gin bind json success", "req", req) cli, err := client(c) if err != nil { log.ZError(c, "get conn error", err, "req", req) apiresp.GinError(c, errs.ErrInternalServer.Wrap(err.Error())) // 获取RPC连接失败 return } + log.ZDebug(c, "get conn success", "req", req) data, err := rpc(cli, c, &req) if err != nil { apiresp.GinError(c, err) // RPC调用失败 diff --git a/pkg/common/config/config.go b/pkg/common/config/config.go index 848ff1472..41d32ec5f 100644 --- a/pkg/common/config/config.go +++ b/pkg/common/config/config.go @@ -1,6 +1,7 @@ package config import ( + _ "embed" "fmt" "io/ioutil" "os" @@ -172,7 +173,6 @@ type config struct { OpenImGroupName string `yaml:"openImGroupName"` OpenImAuthName string `yaml:"openImAuthName"` OpenImConversationName string `yaml:"openImConversationName"` - OpenImCacheName string `yaml:"openImCacheName"` OpenImRtcName string `yaml:"openImRtcName"` OpenImThirdName string `yaml:"openImThirdName"` } diff --git a/pkg/common/constant/constant.go b/pkg/common/constant/constant.go index ec756101f..54ab18cd3 100644 --- a/pkg/common/constant/constant.go +++ b/pkg/common/constant/constant.go @@ -90,6 +90,9 @@ const ( BusinessNotification = 2001 BusinessNotificationEnd = 2099 + ClearConversationNotification = 2101 + DeleteMsgsNotification = 2102 + NotificationEnd = 3000 //status diff --git a/pkg/common/db/controller/conversation.go b/pkg/common/db/controller/conversation.go index dccb9f4b8..2d28f03e5 100644 --- a/pkg/common/db/controller/conversation.go +++ b/pkg/common/db/controller/conversation.go @@ -33,6 +33,7 @@ type ConversationDatabase interface { GetUserConversationIDsHash(ctx context.Context, ownerUserID string) (hash uint64, err error) GetAllConversationIDs(ctx context.Context) ([]string, error) GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (map[string]int64, error) + GetConversationByConversationID(ctx context.Context, conversationID string) (*relationTb.ConversationModel, error) } func NewConversationDatabase(conversation relationTb.ConversationModelInterface, cache cache.ConversationCache, tx tx.Tx) ConversationDatabase { @@ -262,3 +263,7 @@ func (c *conversationDatabase) GetAllConversationIDs(ctx context.Context) ([]str func (c *conversationDatabase) GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (map[string]int64, error) { return c.cache.GetUserAllHasReadSeqs(ctx, ownerUserID) } + +func (c *conversationDatabase) GetConversationByConversationID(ctx context.Context, conversationID string) (*relationTb.ConversationModel, error) { + return c.conversationDB.GetConversationByConversationID(ctx, conversationID) +} diff --git a/pkg/common/db/controller/msg.go b/pkg/common/db/controller/msg.go index 0a43c5ce5..0072f4280 100644 --- a/pkg/common/db/controller/msg.go +++ b/pkg/common/db/controller/msg.go @@ -41,9 +41,9 @@ type CommonMsgDatabase interface { BatchInsertChat2Cache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) (seq int64, isNewConversation bool, err error) // 通过seqList获取mongo中写扩散消息 - GetMsgBySeqsRange(ctx context.Context, userID string, conversationID string, begin, end, num int64) (seqMsg []*sdkws.MsgData, err error) + GetMsgBySeqsRange(ctx context.Context, userID string, conversationID string, begin, end, num int64) (minSeq int64, seqMsg []*sdkws.MsgData, err error) // 通过seqList获取大群在 mongo里面的消息 - GetMsgBySeqs(ctx context.Context, userID string, conversationID string, seqs []int64) (seqMsg []*sdkws.MsgData, err error) + GetMsgBySeqs(ctx context.Context, userID string, conversationID string, seqs []int64) (minSeq int64, seqMsg []*sdkws.MsgData, err error) // 删除会话消息重置最小seq, remainTime为消息保留的时间单位秒,超时消息删除, 传0删除所有消息(此方法不删除redis cache) DeleteConversationMsgsAndSetMinSeq(ctx context.Context, conversationID string, remainTime int64) error // 用户根据seq删除消息 @@ -341,7 +341,7 @@ func (db *commonMsgDatabase) BatchInsertChat2Cache(ctx context.Context, conversa func (db *commonMsgDatabase) getMsgBySeqs(ctx context.Context, userID, conversationID string, seqs []int64) (totalMsgs []*sdkws.MsgData, err error) { var totalUnExistSeqs []int64 for docID, seqs := range db.msg.GetDocIDSeqsMap(conversationID, seqs) { - log.ZDebug(ctx, "getMsgBySeqs", "docID", docID, "seqs", seqs) + //log.ZDebug(ctx, "getMsgBySeqs", "docID", docID, "seqs", seqs) msgs, unexistSeqs, err := db.findMsgInfoBySeq(ctx, userID, docID, seqs) if err != nil { return nil, err @@ -396,7 +396,7 @@ func (db *commonMsgDatabase) getMsgBySeqs(ctx context.Context, userID, conversat // } func (db *commonMsgDatabase) findMsgInfoBySeq(ctx context.Context, userID, docID string, seqs []int64) (totalMsgs []*unRelationTb.MsgInfoModel, unExistSeqs []int64, err error) { - msgs, err := db.msgDocDatabase.GetMsgBySeqIndexIn1Doc(ctx, docID, userID, seqs) + msgs, err := db.msgDocDatabase.GetMsgBySeqIndexIn1Doc(ctx, userID, docID, seqs) if err != nil { return nil, nil, err } @@ -407,7 +407,7 @@ func (db *commonMsgDatabase) findMsgInfoBySeq(ctx context.Context, userID, docID } else { for _, seq := range seqs { for i, msg := range msgs { - if seq == msg.Msg.Seq { + if msg.Msg != nil && seq == msg.Msg.Seq { break } if i == len(msgs)-1 { @@ -448,21 +448,21 @@ func (db *commonMsgDatabase) getMsgBySeqsRange(ctx context.Context, userID strin return seqMsgs, nil } -func (db *commonMsgDatabase) GetMsgBySeqsRange(ctx context.Context, userID string, conversationID string, begin, end, num int64) (seqMsg []*sdkws.MsgData, err error) { +func (db *commonMsgDatabase) GetMsgBySeqsRange(ctx context.Context, userID string, conversationID string, begin, end, num int64) (int64, []*sdkws.MsgData, error) { userMinSeq, err := db.cache.GetConversationUserMinSeq(ctx, conversationID, userID) if err != nil && errs.Unwrap(err) != redis.Nil { - return nil, err + return 0, nil, err } minSeq, err := db.cache.GetMinSeq(ctx, conversationID) if err != nil && errs.Unwrap(err) != redis.Nil { - return nil, err + return 0, nil, err } if userMinSeq < minSeq { minSeq = userMinSeq } if minSeq > end { log.ZInfo(ctx, "minSeq > end", "minSeq", minSeq, "end", end) - return nil, nil + return 0, nil, nil } if begin < minSeq { begin = minSeq @@ -492,22 +492,22 @@ func (db *commonMsgDatabase) GetMsgBySeqsRange(ctx context.Context, userID strin mongoMsgs, err := db.getMsgBySeqsRange(ctx, userID, conversationID, failedSeqs, begin, end) if err != nil { prome.Add(prome.MsgPullFromMongoFailedCounter, len(failedSeqs)) - return nil, err + return 0, nil, err } prome.Add(prome.MsgPullFromMongoSuccessCounter, len(mongoMsgs)) successMsgs = append(successMsgs, mongoMsgs...) } - return successMsgs, nil + return minSeq, successMsgs, nil } -func (db *commonMsgDatabase) GetMsgBySeqs(ctx context.Context, userID string, conversationID string, seqs []int64) (successMsgs []*sdkws.MsgData, err error) { +func (db *commonMsgDatabase) GetMsgBySeqs(ctx context.Context, userID string, conversationID string, seqs []int64) (int64, []*sdkws.MsgData, error) { userMinSeq, err := db.cache.GetConversationUserMinSeq(ctx, conversationID, userID) if err != nil && errs.Unwrap(err) != redis.Nil { - return nil, err + return 0, nil, err } minSeq, err := db.cache.GetMinSeq(ctx, conversationID) if err != nil && errs.Unwrap(err) != redis.Nil { - return nil, err + return 0, nil, err } if userMinSeq < minSeq { minSeq = userMinSeq @@ -531,12 +531,12 @@ func (db *commonMsgDatabase) GetMsgBySeqs(ctx context.Context, userID string, co mongoMsgs, err := db.getMsgBySeqs(ctx, userID, conversationID, failedSeqs) if err != nil { prome.Add(prome.MsgPullFromMongoFailedCounter, len(failedSeqs)) - return nil, err + return 0, nil, err } prome.Add(prome.MsgPullFromMongoSuccessCounter, len(mongoMsgs)) successMsgs = append(successMsgs, mongoMsgs...) } - return successMsgs, nil + return minSeq, successMsgs, nil } func (db *commonMsgDatabase) DeleteConversationMsgsAndSetMinSeq(ctx context.Context, conversationID string, remainTime int64) error { diff --git a/pkg/common/db/controller/msg_test.go b/pkg/common/db/controller/msg_test.go index 3d1f117cd..b1c8415f3 100644 --- a/pkg/common/db/controller/msg_test.go +++ b/pkg/common/db/controller/msg_test.go @@ -2,7 +2,6 @@ package controller import ( "context" - "encoding/json" "fmt" "math/rand" "strconv" @@ -165,7 +164,7 @@ func Test_Insert(t *testing.T) { Content: fmt.Sprintf("test-%d", i), }) } - if err := db.BatchInsertBlock(ctx, "test", arr, updateKeyMsg, 0); err != nil { + if err := db.BatchInsertBlock(ctx, "test", arr, updateKeyMsg, 1); err != nil { t.Fatal(err) } } @@ -189,12 +188,14 @@ func Test_Revoke(t *testing.T) { func Test_FindBySeq(t *testing.T) { db := GetDB() ctx := context.Background() - res, err := db.msgDocDatabase.GetMsgBySeqIndexIn1Doc(ctx, "123456", "test:0", []int64{1, 2, 3}) - if err != nil { - t.Fatal(err) - } - data, _ := json.Marshal(res) - fmt.Println(string(data)) + fmt.Println(db.getMsgBySeqs(ctx, "100", "si_100_101", []int64{1})) + //res, err := db.msgDocDatabase.GetMsgBySeqIndexIn1Doc(ctx, "123456", "test:0", []int64{1, 2, 3}) + //if err != nil { + // t.Fatal(err) + //} + //db.GetMsgBySeqs(ctx, "100", "si_100_101:0", []int64{6}) + //data, _ := json.Marshal(res) + //fmt.Println(string(data)) } //func Test_Delete(t *testing.T) { diff --git a/pkg/common/db/localcache/conversation.go b/pkg/common/db/localcache/conversation.go index 734fe2e6d..9f49dc3b6 100644 --- a/pkg/common/db/localcache/conversation.go +++ b/pkg/common/db/localcache/conversation.go @@ -7,13 +7,14 @@ import ( "github.com/OpenIMSDK/Open-IM-Server/pkg/common/config" "github.com/OpenIMSDK/Open-IM-Server/pkg/discoveryregistry" "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/conversation" + "google.golang.org/grpc" ) type ConversationLocalCache struct { lock sync.Mutex SuperGroupRecvMsgNotNotifyUserIDs map[string]Hash ConversationIDs map[string]Hash - client discoveryregistry.SvcDiscoveryRegistry + conn *grpc.ClientConn } type Hash struct { @@ -22,19 +23,19 @@ type Hash struct { } func NewConversationLocalCache(client discoveryregistry.SvcDiscoveryRegistry) *ConversationLocalCache { + conn, err := client.GetConn(context.Background(), config.Config.RpcRegisterName.OpenImConversationName) + if err != nil { + panic(err) + } return &ConversationLocalCache{ SuperGroupRecvMsgNotNotifyUserIDs: make(map[string]Hash), ConversationIDs: make(map[string]Hash), - client: client, + conn: conn, } } func (g *ConversationLocalCache) GetRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error) { - conn, err := g.client.GetConn(ctx, config.Config.RpcRegisterName.OpenImConversationName) - if err != nil { - return nil, err - } - client := conversation.NewConversationClient(conn) + client := conversation.NewConversationClient(g.conn) resp, err := client.GetRecvMsgNotNotifyUserIDs(ctx, &conversation.GetRecvMsgNotNotifyUserIDsReq{ GroupID: groupID, }) @@ -45,11 +46,7 @@ func (g *ConversationLocalCache) GetRecvMsgNotNotifyUserIDs(ctx context.Context, } func (g *ConversationLocalCache) GetConversationIDs(ctx context.Context, userID string) ([]string, error) { - conn, err := g.client.GetConn(ctx, config.Config.RpcRegisterName.OpenImConversationName) - if err != nil { - return nil, err - } - client := conversation.NewConversationClient(conn) + client := conversation.NewConversationClient(g.conn) resp, err := client.GetUserConversationIDsHash(ctx, &conversation.GetUserConversationIDsHashReq{ OwnerUserID: userID, }) diff --git a/pkg/common/db/localcache/group.go b/pkg/common/db/localcache/group.go index a8e35109c..c0b9d4cd8 100644 --- a/pkg/common/db/localcache/group.go +++ b/pkg/common/db/localcache/group.go @@ -8,12 +8,13 @@ import ( "github.com/OpenIMSDK/Open-IM-Server/pkg/discoveryregistry" "github.com/OpenIMSDK/Open-IM-Server/pkg/errs" "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/group" + "google.golang.org/grpc" ) type GroupLocalCache struct { - lock sync.Mutex - cache map[string]GroupMemberIDsHash - client discoveryregistry.SvcDiscoveryRegistry + lock sync.Mutex + cache map[string]GroupMemberIDsHash + conn *grpc.ClientConn } type GroupMemberIDsHash struct { @@ -22,20 +23,20 @@ type GroupMemberIDsHash struct { } func NewGroupLocalCache(client discoveryregistry.SvcDiscoveryRegistry) *GroupLocalCache { + conn, err := client.GetConn(context.Background(), config.Config.RpcRegisterName.OpenImGroupName) + if err != nil { + panic(err) + } return &GroupLocalCache{ - cache: make(map[string]GroupMemberIDsHash, 0), - client: client, + cache: make(map[string]GroupMemberIDsHash, 0), + conn: conn, } } func (g *GroupLocalCache) GetGroupMemberIDs(ctx context.Context, groupID string) ([]string, error) { g.lock.Lock() defer g.lock.Unlock() - conn, err := g.client.GetConn(ctx, config.Config.RpcRegisterName.OpenImGroupName) - if err != nil { - return nil, err - } - client := group.NewGroupClient(conn) + client := group.NewGroupClient(g.conn) resp, err := client.GetGroupAbstractInfo(ctx, &group.GetGroupAbstractInfoReq{ GroupIDs: []string{groupID}, }) diff --git a/pkg/common/db/relation/conversation_model.go b/pkg/common/db/relation/conversation_model.go index f6cd94317..459a7945c 100644 --- a/pkg/common/db/relation/conversation_model.go +++ b/pkg/common/db/relation/conversation_model.go @@ -90,3 +90,8 @@ func (c *ConversationGorm) GetUserAllHasReadSeqs(ctx context.Context, ownerUserI } return hasReadSeqs, err } + +func (c *ConversationGorm) GetConversationByConversationID(ctx context.Context, conversationID string) (*relation.ConversationModel, error) { + var conversation relation.ConversationModel + return &conversation, utils.Wrap(c.db(ctx).Where("conversation_id = ?", conversationID).Take(&conversation).Error, "") +} diff --git a/pkg/common/db/table/relation/conversation.go b/pkg/common/db/table/relation/conversation.go index d5fc2bea0..34bb344b8 100644 --- a/pkg/common/db/table/relation/conversation.go +++ b/pkg/common/db/table/relation/conversation.go @@ -46,5 +46,6 @@ type ConversationModelInterface interface { FindSuperGroupRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error) GetAllConversationIDs(ctx context.Context) ([]string, error) GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (hashReadSeqs map[string]int64, err error) + GetConversationByConversationID(ctx context.Context, conversationID string) (*ConversationModel, error) NewTx(tx any) ConversationModelInterface } diff --git a/pkg/common/db/unrelation/mongo.go b/pkg/common/db/unrelation/mongo.go index fc98b85eb..6f384417b 100644 --- a/pkg/common/db/unrelation/mongo.go +++ b/pkg/common/db/unrelation/mongo.go @@ -99,7 +99,7 @@ func (m *Mongo) createMongoIndex(collection string, isUnique bool, keys ...strin index := mongo.IndexModel{ Keys: keysDoc, } - if isUnique == true { + if isUnique { index.Options = options.Index().SetUnique(true) } result, err := indexView.CreateOne( diff --git a/pkg/common/db/unrelation/msg.go b/pkg/common/db/unrelation/msg.go index 75d888105..7f55d9cc9 100644 --- a/pkg/common/db/unrelation/msg.go +++ b/pkg/common/db/unrelation/msg.go @@ -191,6 +191,7 @@ func (m *MsgMongoDriver) GetMsgBySeqIndexIn1Doc(ctx context.Context, userID stri { {"$project", bson.D{ {"_id", 0}, + {"doc_id", 1}, {"msgs", bson.D{ {"$map", bson.D{ {"input", indexs}, @@ -219,7 +220,6 @@ func (m *MsgMongoDriver) GetMsgBySeqIndexIn1Doc(ctx context.Context, userID stri }, { {"$project", bson.D{ - {"doc_id", 0}, {"msgs.del_list", 0}, }}, }, diff --git a/pkg/common/mw/rpc_client_interceptor.go b/pkg/common/mw/rpc_client_interceptor.go index eed52f003..554ae0a8f 100644 --- a/pkg/common/mw/rpc_client_interceptor.go +++ b/pkg/common/mw/rpc_client_interceptor.go @@ -28,6 +28,7 @@ func RpcClientInterceptor(ctx context.Context, method string, req, resp interfac if err != nil { return err } + log.ZDebug(ctx, "get rpc ctx success", "conn target", cc.Target()) err = invoker(ctx, method, req, resp, cc, opts...) if err == nil { // log.ZInfo(ctx, "rpc client resp", "funcName", method, "resp", rpcString(resp)) diff --git a/pkg/common/mw/rpc_server_interceptor.go b/pkg/common/mw/rpc_server_interceptor.go index 61b3efe57..6d2df5459 100644 --- a/pkg/common/mw/rpc_server_interceptor.go +++ b/pkg/common/mw/rpc_server_interceptor.go @@ -29,6 +29,8 @@ func rpcString(v interface{}) string { } func RpcServerInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { + log.ZDebug(ctx, "rpc server req", "req", rpcString(req)) + //defer func() { // if r := recover(); r != nil { // log.ZError(ctx, "rpc panic", nil, "FullMethod", info.FullMethod, "type:", fmt.Sprintf("%T", r), "panic:", r) diff --git a/pkg/discoveryregistry/zookeeper/conf.go b/pkg/discoveryregistry/zookeeper/conf.go new file mode 100644 index 000000000..04ee6b179 --- /dev/null +++ b/pkg/discoveryregistry/zookeeper/conf.go @@ -0,0 +1,27 @@ +package openKeeper + +import ( + "github.com/go-zookeeper/zk" +) + +func (s *ZkClient) RegisterConf2Registry(key string, conf []byte) error { + exists, _, err := s.conn.Exists(s.getPath(key)) + if err != nil { + return err + } + if exists { + if err := s.conn.Delete(s.getPath(key), 0); err != nil { + return err + } + } + _, err = s.conn.Create(s.getPath(key), conf, 0, zk.WorldACL(zk.PermAll)) + if err != zk.ErrNodeExists { + return err + } + return nil +} + +func (s *ZkClient) GetConfFromRegistry(key string) ([]byte, error) { + bytes, _, err := s.conn.Get(s.getPath(key)) + return bytes, err +} diff --git a/pkg/discoveryregistry/zookeeper/discover.go b/pkg/discoveryregistry/zookeeper/discover.go new file mode 100644 index 000000000..aa0f74266 --- /dev/null +++ b/pkg/discoveryregistry/zookeeper/discover.go @@ -0,0 +1,110 @@ +package openKeeper + +import ( + "context" + "fmt" + "strings" + "sync" + + "github.com/pkg/errors" + + "github.com/go-zookeeper/zk" + "google.golang.org/grpc" + "google.golang.org/grpc/resolver" +) + +var ErrConnIsNil = errors.New("conn is nil") +var ErrConnIsNilButLocalNotNil = errors.New("conn is nil, but local is not nil") + +func (s *ZkClient) watch(wg *sync.WaitGroup) { + wg.Done() + for { + event := <-s.eventChan + switch event.Type { + case zk.EventSession: + case zk.EventNodeCreated: + case zk.EventNodeChildrenChanged: + l := strings.Split(event.Path, "/") + s.lock.Lock() + if len(l) > 1 { + rpcName := l[len(l)-1] + s.flushResolver(rpcName) + if len(s.localConns[rpcName]) != 0 { + delete(s.localConns, rpcName) + } + } + s.lock.Unlock() + case zk.EventNodeDataChanged: + case zk.EventNodeDeleted: + case zk.EventNotWatching: + } + } + +} + +func (s *ZkClient) GetConnsRemote(serviceName string) (conns []resolver.Address, err error) { + path := s.getPath(serviceName) + childNodes, _, err := s.conn.Children(path) + if err != nil { + return nil, errors.Wrap(err, "get children error") + } + for _, child := range childNodes { + fullPath := path + "/" + child + data, _, err := s.conn.Get(fullPath) + if err != nil { + if err == zk.ErrNoNode { + return nil, errors.Wrap(err, "this is zk ErrNoNode") + } + return nil, errors.Wrap(err, "get children error") + } + conns = append(conns, resolver.Address{Addr: string(data), ServerName: serviceName}) + } + _, _, _, err = s.conn.ChildrenW(s.getPath(serviceName)) + if err != nil { + return nil, errors.Wrap(err, "children watch error") + } + if len(conns) == 0 { + return nil, fmt.Errorf("no conn for service %s, grpc server may not exist, local conn is %v, please check zookeeper server %v, path: %s", serviceName, s.localConns, s.zkServers, s.zkRoot) + } + return conns, nil +} + +func (s *ZkClient) GetConns(ctx context.Context, serviceName string, opts ...grpc.DialOption) ([]*grpc.ClientConn, error) { + s.lock.Lock() + defer s.lock.Unlock() + opts = append(s.options, opts...) + conns := s.localConns[serviceName] + if len(conns) == 0 { + var err error + conns, err = s.GetConnsRemote(serviceName) + if err != nil { + return nil, err + } + s.localConns[serviceName] = conns + } + var ret []*grpc.ClientConn + for _, conn := range conns { + c, err := grpc.DialContext(ctx, conn.Addr, append(s.options, opts...)...) + if err != nil { + return nil, errors.Wrap(err, fmt.Sprintf("conns dialContext error, conn: %s", conn.Addr)) + } + ret = append(ret, c) + } + return ret, nil +} + +func (s *ZkClient) GetConn(ctx context.Context, serviceName string, opts ...grpc.DialOption) (*grpc.ClientConn, error) { + newOpts := append(s.options, grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, s.balancerName))) + return grpc.DialContext(ctx, fmt.Sprintf("%s:///%s", s.scheme, serviceName), append(newOpts, opts...)...) +} + +func (s *ZkClient) GetFirstConn(ctx context.Context, serviceName string, opts ...grpc.DialOption) (*grpc.ClientConn, error) { + conns, err := s.GetConns(ctx, serviceName, opts...) + if err != nil { + return nil, err + } + if len(conns) == 0 { + return nil, ErrConnIsNil + } + return conns[0], nil +} diff --git a/pkg/discoveryregistry/zookeeper/register.go b/pkg/discoveryregistry/zookeeper/register.go new file mode 100644 index 000000000..b27b5bd28 --- /dev/null +++ b/pkg/discoveryregistry/zookeeper/register.go @@ -0,0 +1,39 @@ +package openKeeper + +import ( + "github.com/go-zookeeper/zk" + "google.golang.org/grpc" + "google.golang.org/grpc/resolver" +) + +func (s *ZkClient) Register(rpcRegisterName, host string, port int, opts ...grpc.DialOption) error { + s.lock.Lock() + defer s.lock.Unlock() + if err := s.ensureName(rpcRegisterName); err != nil { + return err + } + addr := s.getAddr(host, port) + _, err := grpc.Dial(addr, opts...) + if err != nil { + return err + } + node, err := s.conn.CreateProtectedEphemeralSequential(s.getPath(rpcRegisterName)+"/"+addr+"_", []byte(addr), zk.WorldACL(zk.PermAll)) + if err != nil { + return err + } + s.node = node + return nil +} + +func (s *ZkClient) UnRegister() error { + s.lock.Lock() + defer s.lock.Unlock() + err := s.conn.Delete(s.node, -1) + if err != nil { + return err + } + s.node = "" + s.localConns = make(map[string][]resolver.Address) + s.resolvers = make(map[string]*Resolver) + return nil +} diff --git a/pkg/discoveryregistry/zookeeper/resolver.go b/pkg/discoveryregistry/zookeeper/resolver.go new file mode 100644 index 000000000..38925e6b0 --- /dev/null +++ b/pkg/discoveryregistry/zookeeper/resolver.go @@ -0,0 +1,51 @@ +package openKeeper + +import ( + "context" + "strings" + "sync" + + "github.com/OpenIMSDK/Open-IM-Server/pkg/common/log" + "google.golang.org/grpc/resolver" +) + +type Resolver struct { + target resolver.Target + cc resolver.ClientConn + addrs []resolver.Address + lock sync.RWMutex + + getConnsRemote func(serviceName string) (conns []resolver.Address, err error) +} + +func (r *Resolver) ResolveNow(o resolver.ResolveNowOptions) { + log.ZDebug(context.Background(), "start resolve now", "target", r.target) + newConns, err := r.getConnsRemote(strings.TrimLeft(r.target.URL.Path, "/")) + if err != nil { + return + } + log.ZDebug(context.Background(), "resolve now", "newConns", newConns, "target", r.target) + r.lock.Lock() + r.addrs = newConns + r.lock.Unlock() + r.cc.UpdateState(resolver.State{Addresses: r.addrs}) + log.ZDebug(context.Background(), "resolve now ok", "newConns", newConns, "target", r.target) +} + +func (s *Resolver) Close() {} + +func (s *ZkClient) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) { + log.ZDebug(context.Background(), "build resolver", "target", target, "opts", opts, "cc", cc) + r := &Resolver{} + r.target = target + r.cc = cc + r.getConnsRemote = s.GetConnsRemote + r.ResolveNow(resolver.ResolveNowOptions{}) + s.lock.Lock() + defer s.lock.Unlock() + s.resolvers[strings.TrimLeft(target.URL.Path, "/")] = r + log.ZDebug(context.Background(), "build resolver ok", "target", target) + return r, nil +} + +func (s *ZkClient) Scheme() string { return s.scheme } diff --git a/pkg/discoveryregistry/zookeeper/zk.go b/pkg/discoveryregistry/zookeeper/zk.go new file mode 100644 index 000000000..de110410f --- /dev/null +++ b/pkg/discoveryregistry/zookeeper/zk.go @@ -0,0 +1,187 @@ +package openKeeper + +import ( + "net" + "strconv" + "sync" + "time" + + "github.com/go-zookeeper/zk" + "google.golang.org/grpc" + "google.golang.org/grpc/resolver" +) + +const ( + defaultFreq = time.Minute * 30 + timeout = 5 +) + +type ZkClient struct { + zkServers []string + zkRoot string + userName string + password string + + scheme string + + timeout int + conn *zk.Conn + eventChan <-chan zk.Event + node string + ticker *time.Ticker + + lock sync.RWMutex + options []grpc.DialOption + + resolvers map[string]*Resolver + localConns map[string][]resolver.Address + balancerName string +} + +type ZkOption func(*ZkClient) + +func WithRoundRobin() ZkOption { + return func(client *ZkClient) { + client.balancerName = "round_robin" + } +} + +func WithUserNameAndPassword(userName, password string) ZkOption { + return func(client *ZkClient) { + client.userName = userName + client.password = password + } +} + +func WithOptions(opts ...grpc.DialOption) ZkOption { + return func(client *ZkClient) { + client.options = opts + } +} + +func WithFreq(freq time.Duration) ZkOption { + return func(client *ZkClient) { + client.ticker = time.NewTicker(freq) + } +} + +func WithTimeout(timeout int) ZkOption { + return func(client *ZkClient) { + client.timeout = timeout + } +} + +func NewClient(zkServers []string, zkRoot string, options ...ZkOption) (*ZkClient, error) { + client := &ZkClient{ + zkServers: zkServers, + zkRoot: "/", + scheme: zkRoot, + timeout: timeout, + localConns: make(map[string][]resolver.Address), + resolvers: make(map[string]*Resolver), + } + client.ticker = time.NewTicker(defaultFreq) + for _, option := range options { + option(client) + } + conn, eventChan, err := zk.Connect(zkServers, time.Duration(client.timeout)*time.Second, zk.WithLogInfo(false)) + if err != nil { + return nil, err + } + if client.userName != "" && client.password != "" { + if err := conn.AddAuth("digest", []byte(client.userName+":"+client.password)); err != nil { + return nil, err + } + } + client.zkRoot += zkRoot + client.eventChan = eventChan + client.conn = conn + if err := client.ensureRoot(); err != nil { + client.CloseZK() + return nil, err + } + resolver.Register(client) + var wg sync.WaitGroup + wg.Add(2) + go client.refresh(&wg) + go client.watch(&wg) + wg.Wait() + return client, nil +} + +func (s *ZkClient) CloseZK() { + s.conn.Close() +} + +func (s *ZkClient) ensureAndCreate(node string) error { + exists, _, err := s.conn.Exists(node) + if err != nil { + return err + } + if !exists { + _, err := s.conn.Create(node, []byte(""), 0, zk.WorldACL(zk.PermAll)) + if err != nil && err != zk.ErrNodeExists { + return err + } + } + return nil +} + +func (s *ZkClient) refresh(wg *sync.WaitGroup) { + wg.Done() + for range s.ticker.C { + s.lock.Lock() + for rpcName := range s.resolvers { + s.flushResolver(rpcName) + } + for rpcName := range s.localConns { + delete(s.localConns, rpcName) + } + s.lock.Unlock() + } + +} + +func (s *ZkClient) flushResolver(serviceName string) { + r, ok := s.resolvers[serviceName] + if ok { + r.ResolveNow(resolver.ResolveNowOptions{}) + s.resolvers[serviceName] = r + } +} + +func (s *ZkClient) GetZkConn() *zk.Conn { + return s.conn +} + +func (s *ZkClient) GetRootPath() string { + return s.zkRoot +} + +func (s *ZkClient) GetNode() string { + return s.node +} + +func (s *ZkClient) ensureRoot() error { + return s.ensureAndCreate(s.zkRoot) +} + +func (s *ZkClient) ensureName(rpcRegisterName string) error { + return s.ensureAndCreate(s.getPath(rpcRegisterName)) +} + +func (s *ZkClient) getPath(rpcRegisterName string) string { + return s.zkRoot + "/" + rpcRegisterName +} + +func (s *ZkClient) getAddr(host string, port int) string { + return net.JoinHostPort(host, strconv.Itoa(port)) +} + +func (s *ZkClient) AddOption(opts ...grpc.DialOption) { + s.options = append(s.options, opts...) +} + +func (s *ZkClient) GetClientLocalConns() map[string][]resolver.Address { + return s.localConns +} diff --git a/pkg/proto/conversation/conversation.pb.go b/pkg/proto/conversation/conversation.pb.go index 841a6c01d..fc9f434ab 100644 --- a/pkg/proto/conversation/conversation.pb.go +++ b/pkg/proto/conversation/conversation.pb.go @@ -1878,6 +1878,100 @@ func (x *GetUserConversationIDsHashResp) GetHash() uint64 { return 0 } +type GetConversationByConversationIDReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ConversationID string `protobuf:"bytes,1,opt,name=conversationID,proto3" json:"conversationID"` +} + +func (x *GetConversationByConversationIDReq) Reset() { + *x = GetConversationByConversationIDReq{} + if protoimpl.UnsafeEnabled { + mi := &file_conversation_conversation_proto_msgTypes[33] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetConversationByConversationIDReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetConversationByConversationIDReq) ProtoMessage() {} + +func (x *GetConversationByConversationIDReq) ProtoReflect() protoreflect.Message { + mi := &file_conversation_conversation_proto_msgTypes[33] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetConversationByConversationIDReq.ProtoReflect.Descriptor instead. +func (*GetConversationByConversationIDReq) Descriptor() ([]byte, []int) { + return file_conversation_conversation_proto_rawDescGZIP(), []int{33} +} + +func (x *GetConversationByConversationIDReq) GetConversationID() string { + if x != nil { + return x.ConversationID + } + return "" +} + +type GetConversationByConversationIDResp struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Conversation *Conversation `protobuf:"bytes,1,opt,name=conversation,proto3" json:"conversation"` +} + +func (x *GetConversationByConversationIDResp) Reset() { + *x = GetConversationByConversationIDResp{} + if protoimpl.UnsafeEnabled { + mi := &file_conversation_conversation_proto_msgTypes[34] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetConversationByConversationIDResp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetConversationByConversationIDResp) ProtoMessage() {} + +func (x *GetConversationByConversationIDResp) ProtoReflect() protoreflect.Message { + mi := &file_conversation_conversation_proto_msgTypes[34] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetConversationByConversationIDResp.ProtoReflect.Descriptor instead. +func (*GetConversationByConversationIDResp) Descriptor() ([]byte, []int) { + return file_conversation_conversation_proto_rawDescGZIP(), []int{34} +} + +func (x *GetConversationByConversationIDResp) GetConversation() *Conversation { + if x != nil { + return x.Conversation + } + return nil +} + var File_conversation_conversation_proto protoreflect.FileDescriptor var file_conversation_conversation_proto_rawDesc = []byte{ @@ -2137,138 +2231,161 @@ var file_conversation_conversation_proto_rawDesc = []byte{ 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x22, 0x34, 0x0a, 0x1e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x73, 0x48, 0x61, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x32, 0xe7, 0x0f, 0x0a, - 0x0c, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x88, 0x01, - 0x0a, 0x17, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x35, 0x2e, 0x4f, 0x70, 0x65, 0x6e, - 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x6e, 0x76, - 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x65, 0x71, - 0x1a, 0x36, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, - 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x6f, 0x64, - 0x69, 0x66, 0x79, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x52, 0x65, 0x73, 0x70, 0x12, 0x70, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x43, - 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x2e, 0x4f, 0x70, - 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, - 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, - 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x2e, 0x2e, 0x4f, 0x70, 0x65, - 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, - 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, - 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x7c, 0x0a, 0x13, 0x47, 0x65, - 0x74, 0x41, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x12, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, - 0x74, 0x41, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x52, 0x65, 0x71, 0x1a, 0x32, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x2e, 0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x73, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x43, - 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x2e, 0x4f, - 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, - 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, - 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x2f, 0x2e, 0x4f, - 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, - 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, - 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x82, 0x01, - 0x0a, 0x15, 0x42, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, - 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x33, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x22, 0x4c, 0x0a, 0x22, + 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, + 0x79, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x52, + 0x65, 0x71, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x76, + 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x22, 0x72, 0x0a, 0x23, 0x47, 0x65, + 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x43, + 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x52, 0x65, 0x73, + 0x70, 0x12, 0x4b, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, - 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x34, 0x2e, 0x4f, + 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x8a, + 0x11, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x88, 0x01, 0x0a, 0x17, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, + 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x35, 0x2e, 0x4f, 0x70, + 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, + 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x43, 0x6f, + 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, + 0x65, 0x71, 0x1a, 0x36, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, + 0x6f, 0x64, 0x69, 0x66, 0x79, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x65, 0x73, 0x70, 0x12, 0x70, 0x0a, 0x0f, 0x47, 0x65, + 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x2e, + 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, + 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, + 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x2e, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, - 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, - 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x12, 0x70, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x2e, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x2e, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x73, 0x70, 0x12, 0x6a, 0x0a, 0x0d, 0x53, 0x65, 0x74, 0x52, 0x65, 0x63, 0x76, 0x4d, - 0x73, 0x67, 0x4f, 0x70, 0x74, 0x12, 0x2b, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x63, 0x76, 0x4d, 0x73, 0x67, 0x4f, 0x70, 0x74, 0x52, - 0x65, 0x71, 0x1a, 0x2c, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, - 0x65, 0x74, 0x52, 0x65, 0x63, 0x76, 0x4d, 0x73, 0x67, 0x4f, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x12, 0x91, 0x01, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x76, 0x4d, 0x73, 0x67, 0x4e, - 0x6f, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x73, 0x12, - 0x38, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, - 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x52, - 0x65, 0x63, 0x76, 0x4d, 0x73, 0x67, 0x4e, 0x6f, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x55, - 0x73, 0x65, 0x72, 0x49, 0x44, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x39, 0x2e, 0x4f, 0x70, 0x65, 0x6e, - 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x76, 0x4d, 0x73, 0x67, - 0x4e, 0x6f, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x12, 0x9a, 0x01, 0x0a, 0x1d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, - 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x43, 0x68, 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3b, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x43, - 0x68, 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x52, 0x65, 0x71, 0x1a, 0x3c, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, + 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x7c, 0x0a, 0x13, + 0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x43, 0x68, 0x61, 0x74, - 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x12, 0x97, 0x01, 0x0a, 0x1c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, - 0x70, 0x43, 0x68, 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x3a, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x68, 0x61, 0x74, 0x43, 0x6f, - 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x3b, + 0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x32, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x73, 0x0a, 0x10, 0x47, 0x65, + 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, - 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x68, 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, - 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x8e, 0x01, 0x0a, 0x19, - 0x44, 0x65, 0x6c, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x68, 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x76, - 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x37, 0x2e, 0x4f, 0x70, 0x65, 0x6e, + 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, + 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x2f, + 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, + 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, + 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, + 0x82, 0x01, 0x0a, 0x15, 0x42, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, + 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x33, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x6c, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x68, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x74, 0x43, 0x6f, + 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x34, + 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, + 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, + 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x12, 0x70, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, + 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x2e, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x6a, 0x0a, 0x0d, 0x53, 0x65, 0x74, 0x52, 0x65, 0x63, + 0x76, 0x4d, 0x73, 0x67, 0x4f, 0x70, 0x74, 0x12, 0x2b, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x63, 0x76, 0x4d, 0x73, 0x67, 0x4f, 0x70, + 0x74, 0x52, 0x65, 0x71, 0x1a, 0x2c, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x2e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x63, 0x76, 0x4d, 0x73, 0x67, 0x4f, 0x70, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x12, 0x91, 0x01, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x76, 0x4d, 0x73, + 0x67, 0x4e, 0x6f, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, + 0x73, 0x12, 0x38, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, + 0x74, 0x52, 0x65, 0x63, 0x76, 0x4d, 0x73, 0x67, 0x4e, 0x6f, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, + 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x39, 0x2e, 0x4f, 0x70, + 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, + 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x76, 0x4d, + 0x73, 0x67, 0x4e, 0x6f, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, + 0x44, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x9a, 0x01, 0x0a, 0x1d, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x43, 0x68, 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, + 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3b, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, + 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x69, 0x6e, 0x67, 0x6c, + 0x65, 0x43, 0x68, 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x3c, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x43, 0x68, 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, - 0x65, 0x71, 0x1a, 0x38, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, - 0x65, 0x6c, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x68, 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, - 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x79, 0x0a, 0x12, - 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, - 0x44, 0x73, 0x12, 0x30, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, - 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, - 0x73, 0x52, 0x65, 0x71, 0x1a, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, + 0x65, 0x73, 0x70, 0x12, 0x97, 0x01, 0x0a, 0x1c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x47, 0x72, + 0x6f, 0x75, 0x70, 0x43, 0x68, 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3a, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x68, 0x61, 0x74, + 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, + 0x1a, 0x3b, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, + 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x68, 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x76, + 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x8e, 0x01, + 0x0a, 0x19, 0x44, 0x65, 0x6c, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x68, 0x61, 0x74, 0x43, 0x6f, + 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x37, 0x2e, 0x4f, 0x70, + 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, + 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x6c, 0x47, 0x72, 0x6f, 0x75, 0x70, + 0x43, 0x68, 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x52, 0x65, 0x71, 0x1a, 0x38, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x2e, 0x44, 0x65, 0x6c, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x68, 0x61, 0x74, 0x43, 0x6f, 0x6e, + 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x79, + 0x0a, 0x12, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x49, 0x44, 0x73, 0x12, 0x30, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x49, 0x44, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0xa3, 0x01, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x43, - 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x48, 0x61, 0x73, 0x52, - 0x65, 0x61, 0x64, 0x41, 0x6e, 0x64, 0x4d, 0x61, 0x78, 0x53, 0x65, 0x71, 0x12, 0x3e, 0x2e, 0x4f, + 0x49, 0x44, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x49, 0x44, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0xa3, 0x01, 0x0a, 0x20, 0x47, 0x65, + 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x48, 0x61, + 0x73, 0x52, 0x65, 0x61, 0x64, 0x41, 0x6e, 0x64, 0x4d, 0x61, 0x78, 0x53, 0x65, 0x71, 0x12, 0x3e, + 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, + 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, + 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x48, 0x61, 0x73, 0x52, 0x65, + 0x61, 0x64, 0x41, 0x6e, 0x64, 0x4d, 0x61, 0x78, 0x53, 0x65, 0x71, 0x52, 0x65, 0x71, 0x1a, 0x3f, + 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, + 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, + 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x48, 0x61, 0x73, 0x52, 0x65, + 0x61, 0x64, 0x41, 0x6e, 0x64, 0x4d, 0x61, 0x78, 0x53, 0x65, 0x71, 0x52, 0x65, 0x73, 0x70, 0x12, + 0x73, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x52, 0x65, 0x71, 0x1a, 0x2f, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x12, 0x91, 0x01, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, + 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x73, 0x48, + 0x61, 0x73, 0x68, 0x12, 0x38, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x73, 0x48, 0x61, 0x73, 0x68, 0x52, 0x65, 0x71, 0x1a, 0x39, 0x2e, + 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, + 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, + 0x72, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x73, + 0x48, 0x61, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x12, 0xa0, 0x01, 0x0a, 0x1f, 0x47, 0x65, 0x74, + 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x43, 0x6f, + 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x12, 0x3d, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, - 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x48, 0x61, 0x73, 0x52, 0x65, 0x61, 0x64, - 0x41, 0x6e, 0x64, 0x4d, 0x61, 0x78, 0x53, 0x65, 0x71, 0x52, 0x65, 0x71, 0x1a, 0x3f, 0x2e, 0x4f, - 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, - 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, - 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x48, 0x61, 0x73, 0x52, 0x65, 0x61, 0x64, - 0x41, 0x6e, 0x64, 0x4d, 0x61, 0x78, 0x53, 0x65, 0x71, 0x52, 0x65, 0x73, 0x70, 0x12, 0x73, 0x0a, - 0x10, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x12, 0x2e, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x65, - 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, - 0x71, 0x1a, 0x2f, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x65, - 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x12, 0x91, 0x01, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, - 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x73, 0x48, 0x61, 0x73, - 0x68, 0x12, 0x38, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, - 0x74, 0x55, 0x73, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x49, 0x44, 0x73, 0x48, 0x61, 0x73, 0x68, 0x52, 0x65, 0x71, 0x1a, 0x39, 0x2e, 0x4f, 0x70, + 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, + 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x52, 0x65, 0x71, 0x1a, 0x3e, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, - 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x43, - 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x73, 0x48, 0x61, - 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x42, 0x3c, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x44, 0x4b, 0x2f, 0x4f, - 0x70, 0x65, 0x6e, 0x2d, 0x49, 0x4d, 0x2d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x6b, - 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, + 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x42, 0x3c, 0x5a, 0x3a, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, + 0x53, 0x44, 0x4b, 0x2f, 0x4f, 0x70, 0x65, 0x6e, 0x2d, 0x49, 0x4d, 0x2d, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6e, + 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( @@ -2283,7 +2400,7 @@ func file_conversation_conversation_proto_rawDescGZIP() []byte { return file_conversation_conversation_proto_rawDescData } -var file_conversation_conversation_proto_msgTypes = make([]protoimpl.MessageInfo, 34) +var file_conversation_conversation_proto_msgTypes = make([]protoimpl.MessageInfo, 36) var file_conversation_conversation_proto_goTypes = []interface{}{ (*Conversation)(nil), // 0: OpenIMServer.conversation.Conversation (*ConversationReq)(nil), // 1: OpenIMServer.conversation.ConversationReq @@ -2318,68 +2435,73 @@ var file_conversation_conversation_proto_goTypes = []interface{}{ (*SetConversationsResp)(nil), // 30: OpenIMServer.conversation.SetConversationsResp (*GetUserConversationIDsHashReq)(nil), // 31: OpenIMServer.conversation.GetUserConversationIDsHashReq (*GetUserConversationIDsHashResp)(nil), // 32: OpenIMServer.conversation.GetUserConversationIDsHashResp - nil, // 33: OpenIMServer.conversation.GetConversationsHasReadAndMaxSeqResp.SeqsEntry - (*wrapperspb.Int32Value)(nil), // 34: OpenIMServer.protobuf.Int32Value - (*wrapperspb.Int64Value)(nil), // 35: OpenIMServer.protobuf.Int64Value - (*wrapperspb.BoolValue)(nil), // 36: OpenIMServer.protobuf.BoolValue - (*wrapperspb.StringValue)(nil), // 37: OpenIMServer.protobuf.StringValue + (*GetConversationByConversationIDReq)(nil), // 33: OpenIMServer.conversation.GetConversationByConversationIDReq + (*GetConversationByConversationIDResp)(nil), // 34: OpenIMServer.conversation.GetConversationByConversationIDResp + nil, // 35: OpenIMServer.conversation.GetConversationsHasReadAndMaxSeqResp.SeqsEntry + (*wrapperspb.Int32Value)(nil), // 36: OpenIMServer.protobuf.Int32Value + (*wrapperspb.Int64Value)(nil), // 37: OpenIMServer.protobuf.Int64Value + (*wrapperspb.BoolValue)(nil), // 38: OpenIMServer.protobuf.BoolValue + (*wrapperspb.StringValue)(nil), // 39: OpenIMServer.protobuf.StringValue } var file_conversation_conversation_proto_depIdxs = []int32{ - 34, // 0: OpenIMServer.conversation.ConversationReq.recvMsgOpt:type_name -> OpenIMServer.protobuf.Int32Value - 35, // 1: OpenIMServer.conversation.ConversationReq.draftTextTime:type_name -> OpenIMServer.protobuf.Int64Value - 36, // 2: OpenIMServer.conversation.ConversationReq.isPinned:type_name -> OpenIMServer.protobuf.BoolValue - 37, // 3: OpenIMServer.conversation.ConversationReq.attachedInfo:type_name -> OpenIMServer.protobuf.StringValue - 36, // 4: OpenIMServer.conversation.ConversationReq.isPrivateChat:type_name -> OpenIMServer.protobuf.BoolValue - 37, // 5: OpenIMServer.conversation.ConversationReq.ex:type_name -> OpenIMServer.protobuf.StringValue - 35, // 6: OpenIMServer.conversation.ConversationReq.updateUnreadCountTime:type_name -> OpenIMServer.protobuf.Int64Value - 34, // 7: OpenIMServer.conversation.ConversationReq.burnDuration:type_name -> OpenIMServer.protobuf.Int32Value - 35, // 8: OpenIMServer.conversation.ConversationReq.minSeq:type_name -> OpenIMServer.protobuf.Int64Value - 35, // 9: OpenIMServer.conversation.ConversationReq.maxSeq:type_name -> OpenIMServer.protobuf.Int64Value - 35, // 10: OpenIMServer.conversation.ConversationReq.hasReadSeq:type_name -> OpenIMServer.protobuf.Int64Value + 36, // 0: OpenIMServer.conversation.ConversationReq.recvMsgOpt:type_name -> OpenIMServer.protobuf.Int32Value + 37, // 1: OpenIMServer.conversation.ConversationReq.draftTextTime:type_name -> OpenIMServer.protobuf.Int64Value + 38, // 2: OpenIMServer.conversation.ConversationReq.isPinned:type_name -> OpenIMServer.protobuf.BoolValue + 39, // 3: OpenIMServer.conversation.ConversationReq.attachedInfo:type_name -> OpenIMServer.protobuf.StringValue + 38, // 4: OpenIMServer.conversation.ConversationReq.isPrivateChat:type_name -> OpenIMServer.protobuf.BoolValue + 39, // 5: OpenIMServer.conversation.ConversationReq.ex:type_name -> OpenIMServer.protobuf.StringValue + 37, // 6: OpenIMServer.conversation.ConversationReq.updateUnreadCountTime:type_name -> OpenIMServer.protobuf.Int64Value + 36, // 7: OpenIMServer.conversation.ConversationReq.burnDuration:type_name -> OpenIMServer.protobuf.Int32Value + 37, // 8: OpenIMServer.conversation.ConversationReq.minSeq:type_name -> OpenIMServer.protobuf.Int64Value + 37, // 9: OpenIMServer.conversation.ConversationReq.maxSeq:type_name -> OpenIMServer.protobuf.Int64Value + 37, // 10: OpenIMServer.conversation.ConversationReq.hasReadSeq:type_name -> OpenIMServer.protobuf.Int64Value 0, // 11: OpenIMServer.conversation.ModifyConversationFieldReq.conversation:type_name -> OpenIMServer.conversation.Conversation 0, // 12: OpenIMServer.conversation.SetConversationReq.conversation:type_name -> OpenIMServer.conversation.Conversation 0, // 13: OpenIMServer.conversation.GetConversationResp.conversation:type_name -> OpenIMServer.conversation.Conversation 0, // 14: OpenIMServer.conversation.GetConversationsResp.conversations:type_name -> OpenIMServer.conversation.Conversation 0, // 15: OpenIMServer.conversation.GetAllConversationsResp.conversations:type_name -> OpenIMServer.conversation.Conversation 0, // 16: OpenIMServer.conversation.BatchSetConversationsReq.Conversations:type_name -> OpenIMServer.conversation.Conversation - 33, // 17: OpenIMServer.conversation.GetConversationsHasReadAndMaxSeqResp.seqs:type_name -> OpenIMServer.conversation.GetConversationsHasReadAndMaxSeqResp.SeqsEntry + 35, // 17: OpenIMServer.conversation.GetConversationsHasReadAndMaxSeqResp.seqs:type_name -> OpenIMServer.conversation.GetConversationsHasReadAndMaxSeqResp.SeqsEntry 1, // 18: OpenIMServer.conversation.SetConversationsReq.conversation:type_name -> OpenIMServer.conversation.ConversationReq - 27, // 19: OpenIMServer.conversation.GetConversationsHasReadAndMaxSeqResp.SeqsEntry.value:type_name -> OpenIMServer.conversation.Seqs - 2, // 20: OpenIMServer.conversation.conversation.ModifyConversationField:input_type -> OpenIMServer.conversation.ModifyConversationFieldReq - 8, // 21: OpenIMServer.conversation.conversation.GetConversation:input_type -> OpenIMServer.conversation.GetConversationReq - 12, // 22: OpenIMServer.conversation.conversation.GetAllConversations:input_type -> OpenIMServer.conversation.GetAllConversationsReq - 10, // 23: OpenIMServer.conversation.conversation.GetConversations:input_type -> OpenIMServer.conversation.GetConversationsReq - 14, // 24: OpenIMServer.conversation.conversation.BatchSetConversations:input_type -> OpenIMServer.conversation.BatchSetConversationsReq - 4, // 25: OpenIMServer.conversation.conversation.SetConversation:input_type -> OpenIMServer.conversation.SetConversationReq - 6, // 26: OpenIMServer.conversation.conversation.SetRecvMsgOpt:input_type -> OpenIMServer.conversation.SetRecvMsgOptReq - 16, // 27: OpenIMServer.conversation.conversation.GetRecvMsgNotNotifyUserIDs:input_type -> OpenIMServer.conversation.GetRecvMsgNotNotifyUserIDsReq - 18, // 28: OpenIMServer.conversation.conversation.CreateSingleChatConversations:input_type -> OpenIMServer.conversation.CreateSingleChatConversationsReq - 20, // 29: OpenIMServer.conversation.conversation.CreateGroupChatConversations:input_type -> OpenIMServer.conversation.CreateGroupChatConversationsReq - 22, // 30: OpenIMServer.conversation.conversation.DelGroupChatConversations:input_type -> OpenIMServer.conversation.DelGroupChatConversationsReq - 24, // 31: OpenIMServer.conversation.conversation.GetConversationIDs:input_type -> OpenIMServer.conversation.GetConversationIDsReq - 26, // 32: OpenIMServer.conversation.conversation.GetConversationsHasReadAndMaxSeq:input_type -> OpenIMServer.conversation.GetConversationsHasReadAndMaxSeqReq - 29, // 33: OpenIMServer.conversation.conversation.SetConversations:input_type -> OpenIMServer.conversation.SetConversationsReq - 31, // 34: OpenIMServer.conversation.conversation.GetUserConversationIDsHash:input_type -> OpenIMServer.conversation.GetUserConversationIDsHashReq - 3, // 35: OpenIMServer.conversation.conversation.ModifyConversationField:output_type -> OpenIMServer.conversation.ModifyConversationFieldResp - 9, // 36: OpenIMServer.conversation.conversation.GetConversation:output_type -> OpenIMServer.conversation.GetConversationResp - 13, // 37: OpenIMServer.conversation.conversation.GetAllConversations:output_type -> OpenIMServer.conversation.GetAllConversationsResp - 11, // 38: OpenIMServer.conversation.conversation.GetConversations:output_type -> OpenIMServer.conversation.GetConversationsResp - 15, // 39: OpenIMServer.conversation.conversation.BatchSetConversations:output_type -> OpenIMServer.conversation.BatchSetConversationsResp - 5, // 40: OpenIMServer.conversation.conversation.SetConversation:output_type -> OpenIMServer.conversation.SetConversationResp - 7, // 41: OpenIMServer.conversation.conversation.SetRecvMsgOpt:output_type -> OpenIMServer.conversation.SetRecvMsgOptResp - 17, // 42: OpenIMServer.conversation.conversation.GetRecvMsgNotNotifyUserIDs:output_type -> OpenIMServer.conversation.GetRecvMsgNotNotifyUserIDsResp - 19, // 43: OpenIMServer.conversation.conversation.CreateSingleChatConversations:output_type -> OpenIMServer.conversation.CreateSingleChatConversationsResp - 21, // 44: OpenIMServer.conversation.conversation.CreateGroupChatConversations:output_type -> OpenIMServer.conversation.CreateGroupChatConversationsResp - 23, // 45: OpenIMServer.conversation.conversation.DelGroupChatConversations:output_type -> OpenIMServer.conversation.DelGroupChatConversationsResp - 25, // 46: OpenIMServer.conversation.conversation.GetConversationIDs:output_type -> OpenIMServer.conversation.GetConversationIDsResp - 28, // 47: OpenIMServer.conversation.conversation.GetConversationsHasReadAndMaxSeq:output_type -> OpenIMServer.conversation.GetConversationsHasReadAndMaxSeqResp - 30, // 48: OpenIMServer.conversation.conversation.SetConversations:output_type -> OpenIMServer.conversation.SetConversationsResp - 32, // 49: OpenIMServer.conversation.conversation.GetUserConversationIDsHash:output_type -> OpenIMServer.conversation.GetUserConversationIDsHashResp - 35, // [35:50] is the sub-list for method output_type - 20, // [20:35] is the sub-list for method input_type - 20, // [20:20] is the sub-list for extension type_name - 20, // [20:20] is the sub-list for extension extendee - 0, // [0:20] is the sub-list for field type_name + 0, // 19: OpenIMServer.conversation.GetConversationByConversationIDResp.conversation:type_name -> OpenIMServer.conversation.Conversation + 27, // 20: OpenIMServer.conversation.GetConversationsHasReadAndMaxSeqResp.SeqsEntry.value:type_name -> OpenIMServer.conversation.Seqs + 2, // 21: OpenIMServer.conversation.conversation.ModifyConversationField:input_type -> OpenIMServer.conversation.ModifyConversationFieldReq + 8, // 22: OpenIMServer.conversation.conversation.GetConversation:input_type -> OpenIMServer.conversation.GetConversationReq + 12, // 23: OpenIMServer.conversation.conversation.GetAllConversations:input_type -> OpenIMServer.conversation.GetAllConversationsReq + 10, // 24: OpenIMServer.conversation.conversation.GetConversations:input_type -> OpenIMServer.conversation.GetConversationsReq + 14, // 25: OpenIMServer.conversation.conversation.BatchSetConversations:input_type -> OpenIMServer.conversation.BatchSetConversationsReq + 4, // 26: OpenIMServer.conversation.conversation.SetConversation:input_type -> OpenIMServer.conversation.SetConversationReq + 6, // 27: OpenIMServer.conversation.conversation.SetRecvMsgOpt:input_type -> OpenIMServer.conversation.SetRecvMsgOptReq + 16, // 28: OpenIMServer.conversation.conversation.GetRecvMsgNotNotifyUserIDs:input_type -> OpenIMServer.conversation.GetRecvMsgNotNotifyUserIDsReq + 18, // 29: OpenIMServer.conversation.conversation.CreateSingleChatConversations:input_type -> OpenIMServer.conversation.CreateSingleChatConversationsReq + 20, // 30: OpenIMServer.conversation.conversation.CreateGroupChatConversations:input_type -> OpenIMServer.conversation.CreateGroupChatConversationsReq + 22, // 31: OpenIMServer.conversation.conversation.DelGroupChatConversations:input_type -> OpenIMServer.conversation.DelGroupChatConversationsReq + 24, // 32: OpenIMServer.conversation.conversation.GetConversationIDs:input_type -> OpenIMServer.conversation.GetConversationIDsReq + 26, // 33: OpenIMServer.conversation.conversation.GetConversationsHasReadAndMaxSeq:input_type -> OpenIMServer.conversation.GetConversationsHasReadAndMaxSeqReq + 29, // 34: OpenIMServer.conversation.conversation.SetConversations:input_type -> OpenIMServer.conversation.SetConversationsReq + 31, // 35: OpenIMServer.conversation.conversation.GetUserConversationIDsHash:input_type -> OpenIMServer.conversation.GetUserConversationIDsHashReq + 33, // 36: OpenIMServer.conversation.conversation.GetConversationByConversationID:input_type -> OpenIMServer.conversation.GetConversationByConversationIDReq + 3, // 37: OpenIMServer.conversation.conversation.ModifyConversationField:output_type -> OpenIMServer.conversation.ModifyConversationFieldResp + 9, // 38: OpenIMServer.conversation.conversation.GetConversation:output_type -> OpenIMServer.conversation.GetConversationResp + 13, // 39: OpenIMServer.conversation.conversation.GetAllConversations:output_type -> OpenIMServer.conversation.GetAllConversationsResp + 11, // 40: OpenIMServer.conversation.conversation.GetConversations:output_type -> OpenIMServer.conversation.GetConversationsResp + 15, // 41: OpenIMServer.conversation.conversation.BatchSetConversations:output_type -> OpenIMServer.conversation.BatchSetConversationsResp + 5, // 42: OpenIMServer.conversation.conversation.SetConversation:output_type -> OpenIMServer.conversation.SetConversationResp + 7, // 43: OpenIMServer.conversation.conversation.SetRecvMsgOpt:output_type -> OpenIMServer.conversation.SetRecvMsgOptResp + 17, // 44: OpenIMServer.conversation.conversation.GetRecvMsgNotNotifyUserIDs:output_type -> OpenIMServer.conversation.GetRecvMsgNotNotifyUserIDsResp + 19, // 45: OpenIMServer.conversation.conversation.CreateSingleChatConversations:output_type -> OpenIMServer.conversation.CreateSingleChatConversationsResp + 21, // 46: OpenIMServer.conversation.conversation.CreateGroupChatConversations:output_type -> OpenIMServer.conversation.CreateGroupChatConversationsResp + 23, // 47: OpenIMServer.conversation.conversation.DelGroupChatConversations:output_type -> OpenIMServer.conversation.DelGroupChatConversationsResp + 25, // 48: OpenIMServer.conversation.conversation.GetConversationIDs:output_type -> OpenIMServer.conversation.GetConversationIDsResp + 28, // 49: OpenIMServer.conversation.conversation.GetConversationsHasReadAndMaxSeq:output_type -> OpenIMServer.conversation.GetConversationsHasReadAndMaxSeqResp + 30, // 50: OpenIMServer.conversation.conversation.SetConversations:output_type -> OpenIMServer.conversation.SetConversationsResp + 32, // 51: OpenIMServer.conversation.conversation.GetUserConversationIDsHash:output_type -> OpenIMServer.conversation.GetUserConversationIDsHashResp + 34, // 52: OpenIMServer.conversation.conversation.GetConversationByConversationID:output_type -> OpenIMServer.conversation.GetConversationByConversationIDResp + 37, // [37:53] is the sub-list for method output_type + 21, // [21:37] is the sub-list for method input_type + 21, // [21:21] is the sub-list for extension type_name + 21, // [21:21] is the sub-list for extension extendee + 0, // [0:21] is the sub-list for field type_name } func init() { file_conversation_conversation_proto_init() } @@ -2784,6 +2906,30 @@ func file_conversation_conversation_proto_init() { return nil } } + file_conversation_conversation_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetConversationByConversationIDReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_conversation_conversation_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetConversationByConversationIDResp); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -2791,7 +2937,7 @@ func file_conversation_conversation_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_conversation_conversation_proto_rawDesc, NumEnums: 0, - NumMessages: 34, + NumMessages: 36, NumExtensions: 0, NumServices: 1, }, @@ -2832,6 +2978,7 @@ type ConversationClient interface { GetConversationsHasReadAndMaxSeq(ctx context.Context, in *GetConversationsHasReadAndMaxSeqReq, opts ...grpc.CallOption) (*GetConversationsHasReadAndMaxSeqResp, error) SetConversations(ctx context.Context, in *SetConversationsReq, opts ...grpc.CallOption) (*SetConversationsResp, error) GetUserConversationIDsHash(ctx context.Context, in *GetUserConversationIDsHashReq, opts ...grpc.CallOption) (*GetUserConversationIDsHashResp, error) + GetConversationByConversationID(ctx context.Context, in *GetConversationByConversationIDReq, opts ...grpc.CallOption) (*GetConversationByConversationIDResp, error) } type conversationClient struct { @@ -2977,6 +3124,15 @@ func (c *conversationClient) GetUserConversationIDsHash(ctx context.Context, in return out, nil } +func (c *conversationClient) GetConversationByConversationID(ctx context.Context, in *GetConversationByConversationIDReq, opts ...grpc.CallOption) (*GetConversationByConversationIDResp, error) { + out := new(GetConversationByConversationIDResp) + err := c.cc.Invoke(ctx, "/OpenIMServer.conversation.conversation/GetConversationByConversationID", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // ConversationServer is the server API for Conversation service. type ConversationServer interface { ModifyConversationField(context.Context, *ModifyConversationFieldReq) (*ModifyConversationFieldResp, error) @@ -2994,6 +3150,7 @@ type ConversationServer interface { GetConversationsHasReadAndMaxSeq(context.Context, *GetConversationsHasReadAndMaxSeqReq) (*GetConversationsHasReadAndMaxSeqResp, error) SetConversations(context.Context, *SetConversationsReq) (*SetConversationsResp, error) GetUserConversationIDsHash(context.Context, *GetUserConversationIDsHashReq) (*GetUserConversationIDsHashResp, error) + GetConversationByConversationID(context.Context, *GetConversationByConversationIDReq) (*GetConversationByConversationIDResp, error) } // UnimplementedConversationServer can be embedded to have forward compatible implementations. @@ -3045,6 +3202,9 @@ func (*UnimplementedConversationServer) SetConversations(context.Context, *SetCo func (*UnimplementedConversationServer) GetUserConversationIDsHash(context.Context, *GetUserConversationIDsHashReq) (*GetUserConversationIDsHashResp, error) { return nil, status.Errorf(codes.Unimplemented, "method GetUserConversationIDsHash not implemented") } +func (*UnimplementedConversationServer) GetConversationByConversationID(context.Context, *GetConversationByConversationIDReq) (*GetConversationByConversationIDResp, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetConversationByConversationID not implemented") +} func RegisterConversationServer(s *grpc.Server, srv ConversationServer) { s.RegisterService(&_Conversation_serviceDesc, srv) @@ -3320,6 +3480,24 @@ func _Conversation_GetUserConversationIDsHash_Handler(srv interface{}, ctx conte return interceptor(ctx, in, info, handler) } +func _Conversation_GetConversationByConversationID_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetConversationByConversationIDReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ConversationServer).GetConversationByConversationID(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/OpenIMServer.conversation.conversation/GetConversationByConversationID", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ConversationServer).GetConversationByConversationID(ctx, req.(*GetConversationByConversationIDReq)) + } + return interceptor(ctx, in, info, handler) +} + var _Conversation_serviceDesc = grpc.ServiceDesc{ ServiceName: "OpenIMServer.conversation.conversation", HandlerType: (*ConversationServer)(nil), @@ -3384,6 +3562,10 @@ var _Conversation_serviceDesc = grpc.ServiceDesc{ MethodName: "GetUserConversationIDsHash", Handler: _Conversation_GetUserConversationIDsHash_Handler, }, + { + MethodName: "GetConversationByConversationID", + Handler: _Conversation_GetConversationByConversationID_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "conversation/conversation.proto", diff --git a/pkg/proto/conversation/conversation.proto b/pkg/proto/conversation/conversation.proto index b2181d40a..4549a0112 100644 --- a/pkg/proto/conversation/conversation.proto +++ b/pkg/proto/conversation/conversation.proto @@ -173,6 +173,14 @@ message GetUserConversationIDsHashResp { uint64 hash = 1; } +message GetConversationByConversationIDReq { + string conversationID = 1; +} + +message GetConversationByConversationIDResp { + Conversation conversation = 1; +} + service conversation { rpc ModifyConversationField(ModifyConversationFieldReq)returns(ModifyConversationFieldResp); rpc GetConversation(GetConversationReq)returns(GetConversationResp); @@ -189,4 +197,5 @@ service conversation { rpc GetConversationsHasReadAndMaxSeq(GetConversationsHasReadAndMaxSeqReq) returns(GetConversationsHasReadAndMaxSeqResp); rpc SetConversations(SetConversationsReq) returns(SetConversationsResp); rpc GetUserConversationIDsHash(GetUserConversationIDsHashReq) returns(GetUserConversationIDsHashResp); + rpc GetConversationByConversationID(GetConversationByConversationIDReq) returns(GetConversationByConversationIDResp); } diff --git a/pkg/proto/msg/msg.proto b/pkg/proto/msg/msg.proto index c38a6113c..070287ba6 100644 --- a/pkg/proto/msg/msg.proto +++ b/pkg/proto/msg/msg.proto @@ -167,9 +167,15 @@ message RevokeMsgReq { message RevokeMsgResp { } +message DeleteSyncOpt { + bool IsSyncSelf = 3; + bool IsSyncOther = 4; +} + message ClearConversationsMsgReq { repeated string conversationIDs = 1; string userID = 2; + DeleteSyncOpt deleteSyncOpt = 3; } message ClearConversationsMsgResp { @@ -177,6 +183,7 @@ message ClearConversationsMsgResp { message UserClearAllMsgReq { string userID = 1; + DeleteSyncOpt deleteSyncOpt = 3; } message UserClearAllMsgResp { @@ -186,6 +193,7 @@ message DeleteMsgsReq { string conversationID = 1; repeated int64 seqs = 2; string userID = 3; + DeleteSyncOpt deleteSyncOpt = 4; } message DeleteMsgsResp { diff --git a/pkg/proto/sdkws/sdkws.proto b/pkg/proto/sdkws/sdkws.proto index bf30026bc..e315841d4 100644 --- a/pkg/proto/sdkws/sdkws.proto +++ b/pkg/proto/sdkws/sdkws.proto @@ -441,6 +441,17 @@ message RevokeMsgTips{ string conversationID = 7; } +message ClearConversationTips { + string userID = 1; + repeated string conversationIDs = 2; +} + +message DeleteMsgsTips { + string userID = 1; + string conversationID = 2; + repeated int64 seqs = 3; +} + ///////////////////signal////////////// message SignalReq { oneof payload { diff --git a/pkg/rpcclient/black.go b/pkg/rpcclient/black.go index 161adb40c..aaab0b563 100644 --- a/pkg/rpcclient/black.go +++ b/pkg/rpcclient/black.go @@ -6,23 +6,24 @@ import ( "github.com/OpenIMSDK/Open-IM-Server/pkg/common/config" discoveryRegistry "github.com/OpenIMSDK/Open-IM-Server/pkg/discoveryregistry" "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/friend" + "google.golang.org/grpc" ) type BlackClient struct { - *MetaClient + conn *grpc.ClientConn } -func NewBlackClient(zk discoveryRegistry.SvcDiscoveryRegistry) *BlackClient { - return &BlackClient{NewMetaClient(zk, config.Config.RpcRegisterName.OpenImFriendName)} +func NewBlackClient(discov discoveryRegistry.SvcDiscoveryRegistry) *BlackClient { + conn, err := discov.GetConn(context.Background(), config.Config.RpcRegisterName.OpenImFriendName) + if err != nil { + panic(err) + } + return &BlackClient{conn: conn} } // possibleBlackUserID是否被userID拉黑,也就是是否在userID的黑名单中 func (b *BlackClient) IsBlocked(ctx context.Context, possibleBlackUserID, userID string) (bool, error) { - cc, err := b.getConn(ctx) - if err != nil { - return false, err - } - r, err := friend.NewFriendClient(cc).IsBlack(ctx, &friend.IsBlackReq{UserID1: possibleBlackUserID, UserID2: userID}) + r, err := friend.NewFriendClient(b.conn).IsBlack(ctx, &friend.IsBlackReq{UserID1: possibleBlackUserID, UserID2: userID}) if err != nil { return false, err } diff --git a/pkg/rpcclient/conversation.go b/pkg/rpcclient/conversation.go index 05141e576..1a2e23818 100644 --- a/pkg/rpcclient/conversation.go +++ b/pkg/rpcclient/conversation.go @@ -5,36 +5,32 @@ import ( "github.com/OpenIMSDK/Open-IM-Server/pkg/common/config" discoveryRegistry "github.com/OpenIMSDK/Open-IM-Server/pkg/discoveryregistry" - "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/conversation" pbConversation "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/conversation" + "google.golang.org/grpc" ) type ConversationClient struct { - *MetaClient + conn *grpc.ClientConn } -func NewConversationClient(zk discoveryRegistry.SvcDiscoveryRegistry) *ConversationClient { - return &ConversationClient{NewMetaClient(zk, config.Config.RpcRegisterName.OpenImConversationName)} +func NewConversationClient(discov discoveryRegistry.SvcDiscoveryRegistry) *ConversationClient { + conn, err := discov.GetConn(context.Background(), config.Config.RpcRegisterName.OpenImConversationName) + if err != nil { + panic(err) + } + return &ConversationClient{conn: conn} } func (c *ConversationClient) ModifyConversationField(ctx context.Context, req *pbConversation.ModifyConversationFieldReq) error { - cc, err := c.getConn(ctx) - if err != nil { - return err - } - _, err = conversation.NewConversationClient(cc).ModifyConversationField(ctx, req) + _, err := pbConversation.NewConversationClient(c.conn).ModifyConversationField(ctx, req) return err } func (c *ConversationClient) GetSingleConversationRecvMsgOpt(ctx context.Context, userID, conversationID string) (int32, error) { - cc, err := c.getConn(ctx) - if err != nil { - return 0, err - } - var req conversation.GetConversationReq + var req pbConversation.GetConversationReq req.OwnerUserID = userID req.ConversationID = conversationID - conversation, err := conversation.NewConversationClient(cc).GetConversation(ctx, &req) + conversation, err := pbConversation.NewConversationClient(c.conn).GetConversation(ctx, &req) if err != nil { return 0, err } @@ -42,37 +38,31 @@ func (c *ConversationClient) GetSingleConversationRecvMsgOpt(ctx context.Context } func (c *ConversationClient) SingleChatFirstCreateConversation(ctx context.Context, recvID, sendID string) error { - cc, err := c.getConn(ctx) - if err != nil { - return err - } - _, err = conversation.NewConversationClient(cc).CreateSingleChatConversations(ctx, &pbConversation.CreateSingleChatConversationsReq{RecvID: recvID, SendID: sendID}) + _, err := pbConversation.NewConversationClient(c.conn).CreateSingleChatConversations(ctx, &pbConversation.CreateSingleChatConversationsReq{RecvID: recvID, SendID: sendID}) return err } func (c *ConversationClient) GroupChatFirstCreateConversation(ctx context.Context, groupID string, userIDs []string) error { - cc, err := c.getConn(ctx) - if err != nil { - return err - } - _, err = conversation.NewConversationClient(cc).CreateGroupChatConversations(ctx, &pbConversation.CreateGroupChatConversationsReq{UserIDs: userIDs, GroupID: groupID}) + _, err := pbConversation.NewConversationClient(c.conn).CreateGroupChatConversations(ctx, &pbConversation.CreateGroupChatConversationsReq{UserIDs: userIDs, GroupID: groupID}) return err } func (c *ConversationClient) DelGroupChatConversations(ctx context.Context, ownerUserIDs []string, groupID string, maxSeq int64) error { - cc, err := c.getConn(ctx) - if err != nil { - return err - } - _, err = conversation.NewConversationClient(cc).DelGroupChatConversations(ctx, &pbConversation.DelGroupChatConversationsReq{OwnerUserID: ownerUserIDs, GroupID: groupID, MaxSeq: maxSeq}) + _, err := pbConversation.NewConversationClient(c.conn).DelGroupChatConversations(ctx, &pbConversation.DelGroupChatConversationsReq{OwnerUserID: ownerUserIDs, GroupID: groupID, MaxSeq: maxSeq}) return err } func (c *ConversationClient) GetConversationIDs(ctx context.Context, ownerUserID string) ([]string, error) { - cc, err := c.getConn(ctx) - if err != nil { - return nil, err - } - resp, err := conversation.NewConversationClient(cc).GetConversationIDs(ctx, &pbConversation.GetConversationIDsReq{UserID: ownerUserID}) + resp, err := pbConversation.NewConversationClient(c.conn).GetConversationIDs(ctx, &pbConversation.GetConversationIDsReq{UserID: ownerUserID}) return resp.ConversationIDs, err } + +func (c *ConversationClient) GetConversation(ctx context.Context, ownerUserID, conversationID string) (*pbConversation.Conversation, error) { + resp, err := pbConversation.NewConversationClient(c.conn).GetConversation(ctx, &pbConversation.GetConversationReq{OwnerUserID: ownerUserID, ConversationID: conversationID}) + return resp.Conversation, err +} + +func (c *ConversationClient) GetConversationByConversationID(ctx context.Context, conversationID string) (*pbConversation.Conversation, error) { + resp, err := pbConversation.NewConversationClient(c.conn).GetConversationByConversationID(ctx, &pbConversation.GetConversationByConversationIDReq{ConversationID: conversationID}) + return resp.Conversation, err +} diff --git a/pkg/rpcclient/friend.go b/pkg/rpcclient/friend.go index 44745e4c2..d290cc958 100644 --- a/pkg/rpcclient/friend.go +++ b/pkg/rpcclient/friend.go @@ -7,22 +7,23 @@ import ( discoveryRegistry "github.com/OpenIMSDK/Open-IM-Server/pkg/discoveryregistry" "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/friend" sdkws "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/sdkws" + "google.golang.org/grpc" ) type FriendClient struct { - *MetaClient + conn *grpc.ClientConn } -func NewFriendClient(zk discoveryRegistry.SvcDiscoveryRegistry) *FriendClient { - return &FriendClient{NewMetaClient(zk, config.Config.RpcRegisterName.OpenImFriendName)} +func NewFriendClient(discov discoveryRegistry.SvcDiscoveryRegistry) *FriendClient { + conn, err := discov.GetConn(context.Background(), config.Config.RpcRegisterName.OpenImFriendName) + if err != nil { + panic(err) + } + return &FriendClient{conn: conn} } func (f *FriendClient) GetFriendsInfo(ctx context.Context, ownerUserID, friendUserID string) (resp *sdkws.FriendInfo, err error) { - cc, err := f.getConn(ctx) - if err != nil { - return nil, err - } - r, err := friend.NewFriendClient(cc).GetDesignatedFriends(ctx, &friend.GetDesignatedFriendsReq{OwnerUserID: ownerUserID, FriendUserIDs: []string{friendUserID}}) + r, err := friend.NewFriendClient(f.conn).GetDesignatedFriends(ctx, &friend.GetDesignatedFriendsReq{OwnerUserID: ownerUserID, FriendUserIDs: []string{friendUserID}}) if err != nil { return nil, err } @@ -32,11 +33,7 @@ func (f *FriendClient) GetFriendsInfo(ctx context.Context, ownerUserID, friendUs // possibleFriendUserID是否在userID的好友中 func (f *FriendClient) IsFriend(ctx context.Context, possibleFriendUserID, userID string) (bool, error) { - cc, err := f.getConn(ctx) - if err != nil { - return false, err - } - resp, err := friend.NewFriendClient(cc).IsFriend(ctx, &friend.IsFriendReq{UserID1: userID, UserID2: possibleFriendUserID}) + resp, err := friend.NewFriendClient(f.conn).IsFriend(ctx, &friend.IsFriendReq{UserID1: userID, UserID2: possibleFriendUserID}) if err != nil { return false, err } @@ -45,12 +42,8 @@ func (f *FriendClient) IsFriend(ctx context.Context, possibleFriendUserID, userI } func (f *FriendClient) GetFriendIDs(ctx context.Context, ownerUserID string) (friendIDs []string, err error) { - cc, err := f.getConn(ctx) - if err != nil { - return nil, err - } req := friend.GetFriendIDsReq{UserID: ownerUserID} - resp, err := friend.NewFriendClient(cc).GetFriendIDs(ctx, &req) + resp, err := friend.NewFriendClient(f.conn).GetFriendIDs(ctx, &req) if err != nil { return nil, err } diff --git a/pkg/rpcclient/group.go b/pkg/rpcclient/group.go index f480a95b4..8be048d08 100644 --- a/pkg/rpcclient/group.go +++ b/pkg/rpcclient/group.go @@ -11,27 +11,23 @@ import ( "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/group" "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/sdkws" "github.com/OpenIMSDK/Open-IM-Server/pkg/utils" + "google.golang.org/grpc" ) type GroupClient struct { - MetaClient + conn *grpc.ClientConn } -func NewGroupClient(client discoveryregistry.SvcDiscoveryRegistry) *GroupClient { - return &GroupClient{ - MetaClient: MetaClient{ - client: client, - rpcRegisterName: config.Config.RpcRegisterName.OpenImGroupName, - }, +func NewGroupClient(discov discoveryregistry.SvcDiscoveryRegistry) *GroupClient { + conn, err := discov.GetConn(context.Background(), config.Config.RpcRegisterName.OpenImGroupName) + if err != nil { + panic(err) } + return &GroupClient{conn: conn} } func (g *GroupClient) GetGroupInfos(ctx context.Context, groupIDs []string, complete bool) ([]*sdkws.GroupInfo, error) { - cc, err := g.getConn(ctx) - if err != nil { - return nil, err - } - resp, err := group.NewGroupClient(cc).GetGroupsInfo(ctx, &group.GetGroupsInfoReq{ + resp, err := group.NewGroupClient(g.conn).GetGroupsInfo(ctx, &group.GetGroupsInfoReq{ GroupIDs: groupIDs, }) if err != nil { @@ -66,11 +62,7 @@ func (g *GroupClient) GetGroupInfoMap(ctx context.Context, groupIDs []string, co } func (g *GroupClient) GetGroupMemberInfos(ctx context.Context, groupID string, userIDs []string, complete bool) ([]*sdkws.GroupMemberFullInfo, error) { - cc, err := g.getConn(ctx) - if err != nil { - return nil, err - } - resp, err := group.NewGroupClient(cc).GetGroupMembersInfo(ctx, &group.GetGroupMembersInfoReq{ + resp, err := group.NewGroupClient(g.conn).GetGroupMembersInfo(ctx, &group.GetGroupMembersInfoReq{ GroupID: groupID, UserIDs: userIDs, }) @@ -106,11 +98,7 @@ func (g *GroupClient) GetGroupMemberInfoMap(ctx context.Context, groupID string, } func (g *GroupClient) GetOwnerAndAdminInfos(ctx context.Context, groupID string) ([]*sdkws.GroupMemberFullInfo, error) { - cc, err := g.getConn(ctx) - if err != nil { - return nil, err - } - resp, err := group.NewGroupClient(cc).GetGroupMemberRoleLevel(ctx, &group.GetGroupMemberRoleLevelReq{ + resp, err := group.NewGroupClient(g.conn).GetGroupMemberRoleLevel(ctx, &group.GetGroupMemberRoleLevelReq{ GroupID: groupID, RoleLevels: []int32{constant.GroupOwner, constant.GroupAdmin}, }) @@ -121,11 +109,7 @@ func (g *GroupClient) GetOwnerAndAdminInfos(ctx context.Context, groupID string) } func (g *GroupClient) GetOwnerInfo(ctx context.Context, groupID string) (*sdkws.GroupMemberFullInfo, error) { - cc, err := g.getConn(ctx) - if err != nil { - return nil, err - } - resp, err := group.NewGroupClient(cc).GetGroupMemberRoleLevel(ctx, &group.GetGroupMemberRoleLevelReq{ + resp, err := group.NewGroupClient(g.conn).GetGroupMemberRoleLevel(ctx, &group.GetGroupMemberRoleLevelReq{ GroupID: groupID, RoleLevels: []int32{constant.GroupOwner}, }) @@ -133,11 +117,7 @@ func (g *GroupClient) GetOwnerInfo(ctx context.Context, groupID string) (*sdkws. } func (g *GroupClient) GetGroupMemberIDs(ctx context.Context, groupID string) ([]string, error) { - cc, err := g.getConn(ctx) - if err != nil { - return nil, err - } - resp, err := group.NewGroupClient(cc).GetGroupMemberUserIDs(ctx, &group.GetGroupMemberUserIDsReq{ + resp, err := group.NewGroupClient(g.conn).GetGroupMemberUserIDs(ctx, &group.GetGroupMemberUserIDsReq{ GroupID: groupID, }) if err != nil { diff --git a/pkg/rpcclient/meta.go b/pkg/rpcclient/meta.go deleted file mode 100644 index 678488b77..000000000 --- a/pkg/rpcclient/meta.go +++ /dev/null @@ -1,45 +0,0 @@ -package rpcclient - -import ( - "context" - - "github.com/OpenIMSDK/Open-IM-Server/pkg/discoveryregistry" - "google.golang.org/grpc" -) - -type MetaClient struct { - // contains filtered or unexported fields - client discoveryregistry.SvcDiscoveryRegistry - rpcRegisterName string -} - -func NewMetaClient(client discoveryregistry.SvcDiscoveryRegistry, rpcRegisterName string, opts ...MetaClientOptions) *MetaClient { - c := &MetaClient{ - client: client, - rpcRegisterName: rpcRegisterName, - } - for _, opt := range opts { - opt(c) - } - return c -} - -type MetaClientOptions func(*MetaClient) - -func (m *MetaClient) getConn(ctx context.Context) (*grpc.ClientConn, error) { - return m.client.GetConn(ctx, m.rpcRegisterName) -} - -type CommonUser interface { - GetNickname() string - GetFaceURL() string - GetUserID() string - GetEx() string -} - -type CommonGroup interface { - GetNickname() string - GetFaceURL() string - GetGroupID() string - GetEx() string -} diff --git a/pkg/rpcclient/msg.go b/pkg/rpcclient/msg.go index 43ad4fa39..c86c9a5d9 100644 --- a/pkg/rpcclient/msg.go +++ b/pkg/rpcclient/msg.go @@ -4,15 +4,14 @@ import ( "context" "encoding/json" - "github.com/OpenIMSDK/Open-IM-Server/pkg/common/log" - "github.com/OpenIMSDK/Open-IM-Server/pkg/common/config" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/constant" + "github.com/OpenIMSDK/Open-IM-Server/pkg/common/log" "github.com/OpenIMSDK/Open-IM-Server/pkg/discoveryregistry" "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/msg" "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/sdkws" "github.com/OpenIMSDK/Open-IM-Server/pkg/utils" - + "google.golang.org/grpc" "google.golang.org/protobuf/proto" // "google.golang.org/protobuf/proto" ) @@ -54,6 +53,8 @@ func newContentTypeConf() map[int32]config.NotificationConf { constant.ConversationChangeNotification: config.Config.Notification.ConversationChanged, constant.ConversationUnreadNotification: config.Config.Notification.ConversationChanged, constant.ConversationPrivateChatNotification: config.Config.Notification.ConversationSetPrivate, + // msg + constant.MsgRevokeNotification: {IsSendMsg: false, ReliabilityLevel: constant.ReliableNotificationNoMsg}, } } @@ -98,43 +99,61 @@ func newSessionTypeConf() map[int32]int32 { } type MsgClient struct { - *MetaClient - contentTypeConf map[int32]config.NotificationConf - sessionTypeConf map[int32]int32 + conn *grpc.ClientConn } -func NewMsgClient(zk discoveryregistry.SvcDiscoveryRegistry) *MsgClient { - return &MsgClient{MetaClient: NewMetaClient(zk, config.Config.RpcRegisterName.OpenImMsgName), contentTypeConf: newContentTypeConf(), sessionTypeConf: newSessionTypeConf()} +func NewMsgClient(discov discoveryregistry.SvcDiscoveryRegistry) *MsgClient { + conn, err := discov.GetConn(context.Background(), config.Config.RpcRegisterName.OpenImMsgName) + if err != nil { + panic(err) + } + return &MsgClient{conn: conn} } func (m *MsgClient) SendMsg(ctx context.Context, req *msg.SendMsgReq) (*msg.SendMsgResp, error) { - cc, err := m.getConn(ctx) - if err != nil { - return nil, err - } - resp, err := msg.NewMsgClient(cc).SendMsg(ctx, req) + resp, err := msg.NewMsgClient(m.conn).SendMsg(ctx, req) return resp, err } func (m *MsgClient) GetMaxSeq(ctx context.Context, req *sdkws.GetMaxSeqReq) (*sdkws.GetMaxSeqResp, error) { - cc, err := m.getConn(ctx) - if err != nil { - return nil, err - } - resp, err := msg.NewMsgClient(cc).GetMaxSeq(ctx, req) + resp, err := msg.NewMsgClient(m.conn).GetMaxSeq(ctx, req) return resp, err } func (m *MsgClient) PullMessageBySeqList(ctx context.Context, req *sdkws.PullMessageBySeqsReq) (*sdkws.PullMessageBySeqsResp, error) { - cc, err := m.getConn(ctx) - if err != nil { - return nil, err - } - resp, err := msg.NewMsgClient(cc).PullMessageBySeqs(ctx, req) + resp, err := msg.NewMsgClient(m.conn).PullMessageBySeqs(ctx, req) return resp, err } -func (c *MsgClient) Notification(ctx context.Context, sendID, recvID string, contentType int32, m proto.Message, opts ...utils.OptionsOpt) error { +type NotificationSender struct { + contentTypeConf map[int32]config.NotificationConf + sessionTypeConf map[int32]int32 + sendMsg func(ctx context.Context, req *msg.SendMsgReq) (*msg.SendMsgResp, error) +} + +type NewNotificationSenderOptions func(*NotificationSender) + +func WithLocalSendMsg(sendMsg func(ctx context.Context, req *msg.SendMsgReq) (*msg.SendMsgResp, error)) NewNotificationSenderOptions { + return func(s *NotificationSender) { + s.sendMsg = sendMsg + } +} + +func WithDiscov(discov discoveryregistry.SvcDiscoveryRegistry) NewNotificationSenderOptions { + return func(s *NotificationSender) { + s.sendMsg = NewMsgClient(discov).SendMsg + } +} + +func NewNotificationSender(opts ...NewNotificationSenderOptions) *NotificationSender { + notificationSender := &NotificationSender{contentTypeConf: newContentTypeConf(), sessionTypeConf: newSessionTypeConf()} + for _, opt := range opts { + opt(notificationSender) + } + return notificationSender +} + +func (s *NotificationSender) NotificationWithSesstionType(ctx context.Context, sendID, recvID string, contentType, sesstionType int32, m proto.Message, opts ...utils.OptionsOpt) (err error) { n := sdkws.NotificationElem{Detail: utils.StructToJsonString(m)} content, err := json.Marshal(&n) if err != nil { @@ -150,13 +169,13 @@ func (c *MsgClient) Notification(ctx context.Context, sendID, recvID string, con msg.Content = content msg.MsgFrom = constant.SysMsgType msg.ContentType = contentType - msg.SessionType = c.sessionTypeConf[contentType] + msg.SessionType = sesstionType if msg.SessionType == constant.SuperGroupChatType { msg.GroupID = recvID } msg.CreateTime = utils.GetCurrentTimestampByMill() msg.ClientMsgID = utils.GetMsgID(sendID) - options := config.GetOptionsByNotification(c.contentTypeConf[contentType]) + options := config.GetOptionsByNotification(s.contentTypeConf[contentType]) options = utils.WithOptions(options, opts...) msg.Options = options offlineInfo.Title = title @@ -164,7 +183,7 @@ func (c *MsgClient) Notification(ctx context.Context, sendID, recvID string, con offlineInfo.Ex = ex msg.OfflinePushInfo = &offlineInfo req.MsgData = &msg - _, err = c.SendMsg(ctx, &req) + _, err = s.sendMsg(ctx, &req) if err == nil { log.ZDebug(ctx, "MsgClient Notification SendMsg success", "req", &req) } else { @@ -172,3 +191,7 @@ func (c *MsgClient) Notification(ctx context.Context, sendID, recvID string, con } return err } + +func (s *NotificationSender) Notification(ctx context.Context, sendID, recvID string, contentType int32, m proto.Message, opts ...utils.OptionsOpt) error { + return s.NotificationWithSesstionType(ctx, sendID, recvID, contentType, s.sessionTypeConf[contentType], m, opts...) +} diff --git a/pkg/rpcclient/notification/common.go b/pkg/rpcclient/notification/common.go new file mode 100644 index 000000000..ea0174000 --- /dev/null +++ b/pkg/rpcclient/notification/common.go @@ -0,0 +1,15 @@ +package notification + +type CommonUser interface { + GetNickname() string + GetFaceURL() string + GetUserID() string + GetEx() string +} + +type CommonGroup interface { + GetNickname() string + GetFaceURL() string + GetGroupID() string + GetEx() string +} diff --git a/pkg/rpcclient/notification/conevrsation.go b/pkg/rpcclient/notification/conevrsation.go index 35161f662..e5ef6d130 100644 --- a/pkg/rpcclient/notification/conevrsation.go +++ b/pkg/rpcclient/notification/conevrsation.go @@ -10,11 +10,11 @@ import ( ) type ConversationNotificationSender struct { - *rpcclient.MsgClient + *rpcclient.NotificationSender } func NewConversationNotificationSender(client discoveryregistry.SvcDiscoveryRegistry) *ConversationNotificationSender { - return &ConversationNotificationSender{rpcclient.NewMsgClient(client)} + return &ConversationNotificationSender{rpcclient.NewNotificationSender(rpcclient.WithDiscov(client))} } // SetPrivate调用 diff --git a/pkg/rpcclient/notification/friend.go b/pkg/rpcclient/notification/friend.go index 7e0e48c84..7c655686d 100644 --- a/pkg/rpcclient/notification/friend.go +++ b/pkg/rpcclient/notification/friend.go @@ -2,6 +2,7 @@ package notification import ( "context" + "github.com/OpenIMSDK/Open-IM-Server/pkg/common/constant" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/convert" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/controller" @@ -13,9 +14,9 @@ import ( ) type FriendNotificationSender struct { - *rpcclient.MsgClient + *rpcclient.NotificationSender // 找不到报错 - getUsersInfo func(ctx context.Context, userIDs []string) ([]rpcclient.CommonUser, error) + getUsersInfo func(ctx context.Context, userIDs []string) ([]CommonUser, error) // db controller db controller.FriendDatabase } @@ -30,7 +31,7 @@ func WithFriendDB(db controller.FriendDatabase) friendNotificationSenderOptions func WithDBFunc(fn func(ctx context.Context, userIDs []string) (users []*relationTb.UserModel, err error)) friendNotificationSenderOptions { return func(s *FriendNotificationSender) { - f := func(ctx context.Context, userIDs []string) (result []rpcclient.CommonUser, err error) { + f := func(ctx context.Context, userIDs []string) (result []CommonUser, err error) { users, err := fn(ctx, userIDs) if err != nil { return nil, err @@ -46,7 +47,7 @@ func WithDBFunc(fn func(ctx context.Context, userIDs []string) (users []*relatio func WithRpcFunc(fn func(ctx context.Context, userIDs []string) ([]*sdkws.UserInfo, error)) friendNotificationSenderOptions { return func(s *FriendNotificationSender) { - f := func(ctx context.Context, userIDs []string) (result []rpcclient.CommonUser, err error) { + f := func(ctx context.Context, userIDs []string) (result []CommonUser, err error) { users, err := fn(ctx, userIDs) if err != nil { return nil, err @@ -62,7 +63,7 @@ func WithRpcFunc(fn func(ctx context.Context, userIDs []string) ([]*sdkws.UserIn func NewFriendNotificationSender(client discoveryregistry.SvcDiscoveryRegistry, opts ...friendNotificationSenderOptions) *FriendNotificationSender { f := &FriendNotificationSender{ - MsgClient: rpcclient.NewMsgClient(client), + NotificationSender: rpcclient.NewNotificationSender(rpcclient.WithDiscov(client)), } for _, opt := range opts { opt(f) diff --git a/pkg/rpcclient/notification/group.go b/pkg/rpcclient/notification/group.go index fc94c2fc1..10a969b8a 100644 --- a/pkg/rpcclient/notification/group.go +++ b/pkg/rpcclient/notification/group.go @@ -3,7 +3,6 @@ package notification import ( "context" "fmt" - "time" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/constant" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/controller" @@ -13,23 +12,22 @@ import ( "github.com/OpenIMSDK/Open-IM-Server/pkg/discoveryregistry" "github.com/OpenIMSDK/Open-IM-Server/pkg/errs" pbGroup "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/group" - "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/msg" "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/sdkws" "github.com/OpenIMSDK/Open-IM-Server/pkg/rpcclient" "github.com/OpenIMSDK/Open-IM-Server/pkg/utils" ) -func NewGroupNotificationSender(db controller.GroupDatabase, sdr discoveryregistry.SvcDiscoveryRegistry, fn func(ctx context.Context, userIDs []string) ([]rpcclient.CommonUser, error)) *GroupNotificationSender { +func NewGroupNotificationSender(db controller.GroupDatabase, sdr discoveryregistry.SvcDiscoveryRegistry, fn func(ctx context.Context, userIDs []string) ([]CommonUser, error)) *GroupNotificationSender { return &GroupNotificationSender{ - msgClient: rpcclient.NewMsgClient(sdr), - getUsersInfo: fn, - db: db, + NotificationSender: rpcclient.NewNotificationSender(rpcclient.WithDiscov(sdr)), + getUsersInfo: fn, + db: db, } } type GroupNotificationSender struct { - msgClient *rpcclient.MsgClient - getUsersInfo func(ctx context.Context, userIDs []string) ([]rpcclient.CommonUser, error) + *rpcclient.NotificationSender + getUsersInfo func(ctx context.Context, userIDs []string) ([]CommonUser, error) db controller.GroupDatabase } @@ -306,7 +304,7 @@ func (g *GroupNotificationSender) mergeGroupFull(ctx context.Context, groupID st //} func (g *GroupNotificationSender) GroupCreatedNotification(ctx context.Context, tips *sdkws.GroupCreatedTips) (err error) { - return g.msgClient.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupCreatedNotification, tips) + return g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupCreatedNotification, tips) } //func (g *GroupNotificationSender) GroupInfoSetNotification(ctx context.Context, group *relation.GroupModel, members []*relation.GroupMemberModel, needVerification *int32) (err error) { @@ -330,7 +328,7 @@ func (g *GroupNotificationSender) GroupInfoSetNotification(ctx context.Context, //if needVerification != nil { // tips.Group.NeedVerification = *needVerification //} - return g.msgClient.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupInfoSetNotification, tips) + return g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupInfoSetNotification, tips) } func (g *GroupNotificationSender) JoinGroupApplicationNotification(ctx context.Context, req *pbGroup.JoinGroupReq) (err error) { @@ -355,7 +353,7 @@ func (g *GroupNotificationSender) JoinGroupApplicationNotification(ctx context.C userIDs = append(userIDs, req.InviterUserID, mcontext.GetOpUserID(ctx)) tips := &sdkws.JoinGroupApplicationTips{Group: group, Applicant: user, ReqMsg: req.ReqMessage} for _, userID := range utils.Distinct(userIDs) { - err = g.msgClient.Notification(ctx, mcontext.GetOpUserID(ctx), userID, constant.JoinGroupApplicationNotification, tips) + err = g.Notification(ctx, mcontext.GetOpUserID(ctx), userID, constant.JoinGroupApplicationNotification, tips) if err != nil { log.ZError(ctx, "JoinGroupApplicationNotification failed", err, "group", req.GroupID, "userID", userID) } @@ -395,7 +393,7 @@ func (g *GroupNotificationSender) MemberQuitNotification(ctx context.Context, re // log.ZError(ctx, "MemberQuitNotification failed", err, "group", req.GroupID, "userID", userID) // } //} - return g.msgClient.Notification(ctx, mcontext.GetOpUserID(ctx), req.GroupID, constant.MemberQuitNotification, tips) + return g.Notification(ctx, mcontext.GetOpUserID(ctx), req.GroupID, constant.MemberQuitNotification, tips) } func (g *GroupNotificationSender) GroupApplicationAcceptedNotification(ctx context.Context, req *pbGroup.GroupApplicationResponseReq) (err error) { @@ -419,7 +417,7 @@ func (g *GroupNotificationSender) GroupApplicationAcceptedNotification(ctx conte } tips := &sdkws.GroupApplicationAcceptedTips{Group: group, OpUser: user, HandleMsg: req.HandledMsg, ReceiverAs: 1} for _, userID := range append(userIDs, mcontext.GetOpUserID(ctx)) { - err = g.msgClient.Notification(ctx, mcontext.GetOpUserID(ctx), userID, constant.GroupApplicationAcceptedNotification, tips) + err = g.Notification(ctx, mcontext.GetOpUserID(ctx), userID, constant.GroupApplicationAcceptedNotification, tips) if err != nil { log.ZError(ctx, "failed", err) } @@ -448,7 +446,7 @@ func (g *GroupNotificationSender) GroupApplicationRejectedNotification(ctx conte } tips := &sdkws.GroupApplicationRejectedTips{Group: group, OpUser: user, HandleMsg: req.HandledMsg} for _, userID := range append(userIDs, mcontext.GetOpUserID(ctx)) { - err = g.msgClient.Notification(ctx, mcontext.GetOpUserID(ctx), userID, constant.GroupApplicationRejectedNotification, tips) + err = g.Notification(ctx, mcontext.GetOpUserID(ctx), userID, constant.GroupApplicationRejectedNotification, tips) if err != nil { log.ZError(ctx, "failed", err) } @@ -473,7 +471,7 @@ func (g *GroupNotificationSender) GroupOwnerTransferredNotification(ctx context. return err } tips := &sdkws.GroupOwnerTransferredTips{Group: group, OpUser: member[opUserID], NewGroupOwner: member[req.NewOwnerUserID]} - return g.msgClient.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupOwnerTransferredNotification, tips) + return g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupOwnerTransferredNotification, tips) } func (g *GroupNotificationSender) MemberKickedNotification(ctx context.Context, tips *sdkws.MemberKickedTips) (err error) { @@ -499,7 +497,7 @@ func (g *GroupNotificationSender) MemberKickedNotification(ctx context.Context, // } // MemberKickedTips.KickedUserList = append(MemberKickedTips.KickedUserList, &groupMemberInfo) //} - return g.msgClient.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.MemberKickedNotification, tips) + return g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.MemberKickedNotification, tips) } func (g *GroupNotificationSender) MemberInvitedNotification(ctx context.Context, groupID, reason string, invitedUserIDList []string) (err error) { @@ -522,7 +520,7 @@ func (g *GroupNotificationSender) MemberInvitedNotification(ctx context.Context, return err } tips := &sdkws.MemberInvitedTips{Group: group, OpUser: opUser, InvitedUserList: users} - return g.msgClient.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.MemberInvitedNotification, tips) + return g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.MemberInvitedNotification, tips) } func (g *GroupNotificationSender) MemberEnterNotification(ctx context.Context, req *pbGroup.GroupApplicationResponseReq) (err error) { @@ -541,7 +539,7 @@ func (g *GroupNotificationSender) MemberEnterNotification(ctx context.Context, r return err } tips := &sdkws.MemberEnterTips{Group: group, EntrantUser: user} - return g.msgClient.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.MemberEnterNotification, tips) + return g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.MemberEnterNotification, tips) } func (g *GroupNotificationSender) GroupDismissedNotification(ctx context.Context, req *pbGroup.DismissGroupReq) (err error) { @@ -568,7 +566,7 @@ func (g *GroupNotificationSender) GroupDismissedNotification(ctx context.Context UserID: mcontext.GetOpUserID(ctx), } } - return g.msgClient.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupDismissedNotification, tips) + return g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupDismissedNotification, tips) } func (g *GroupNotificationSender) GroupMemberMutedNotification(ctx context.Context, groupID, groupMemberUserID string, mutedSeconds uint32) (err error) { @@ -588,7 +586,7 @@ func (g *GroupNotificationSender) GroupMemberMutedNotification(ctx context.Conte } tips := &sdkws.GroupMemberMutedTips{Group: group, MutedSeconds: mutedSeconds, OpUser: user[mcontext.GetOpUserID(ctx)], MutedUser: user[groupMemberUserID]} - return g.msgClient.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMemberMutedNotification, tips) + return g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMemberMutedNotification, tips) } func (g *GroupNotificationSender) GroupMemberCancelMutedNotification(ctx context.Context, groupID, groupMemberUserID string) (err error) { @@ -607,7 +605,7 @@ func (g *GroupNotificationSender) GroupMemberCancelMutedNotification(ctx context return err } tips := &sdkws.GroupMemberCancelMutedTips{Group: group, OpUser: user[mcontext.GetOpUserID(ctx)], MutedUser: user[groupMemberUserID]} - return g.msgClient.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMemberCancelMutedNotification, tips) + return g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMemberCancelMutedNotification, tips) } func (g *GroupNotificationSender) GroupMutedNotification(ctx context.Context, groupID string) (err error) { @@ -631,7 +629,7 @@ func (g *GroupNotificationSender) GroupMutedNotification(ctx context.Context, gr } else { tips.OpUser = &sdkws.GroupMemberFullInfo{UserID: mcontext.GetOpUserID(ctx), GroupID: groupID} } - return g.msgClient.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMutedNotification, tips) + return g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMutedNotification, tips) } func (g *GroupNotificationSender) GroupCancelMutedNotification(ctx context.Context, groupID string) (err error) { @@ -655,7 +653,7 @@ func (g *GroupNotificationSender) GroupCancelMutedNotification(ctx context.Conte } else { tips.OpUser = &sdkws.GroupMemberFullInfo{UserID: mcontext.GetOpUserID(ctx), GroupID: groupID} } - return g.msgClient.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupCancelMutedNotification, tips) + return g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupCancelMutedNotification, tips) } func (g *GroupNotificationSender) GroupMemberInfoSetNotification(ctx context.Context, groupID, groupMemberUserID string) (err error) { @@ -674,7 +672,7 @@ func (g *GroupNotificationSender) GroupMemberInfoSetNotification(ctx context.Con return err } tips := &sdkws.GroupMemberInfoSetTips{Group: group, OpUser: user[mcontext.GetOpUserID(ctx)], ChangedUser: user[groupMemberUserID]} - return g.msgClient.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMemberCancelMutedNotification, tips) + return g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMemberCancelMutedNotification, tips) } func (g *GroupNotificationSender) GroupMemberSetToAdminNotification(ctx context.Context, groupID, groupMemberUserID string, notificationType int32) (err error) { @@ -693,7 +691,7 @@ func (g *GroupNotificationSender) GroupMemberSetToAdminNotification(ctx context. return err } tips := &sdkws.GroupMemberInfoSetTips{Group: group, OpUser: user[mcontext.GetOpUserID(ctx)], ChangedUser: user[groupMemberUserID]} - return g.msgClient.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMemberCancelMutedNotification, tips) + return g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.GroupMemberCancelMutedNotification, tips) } func (g *GroupNotificationSender) MemberEnterDirectlyNotification(ctx context.Context, groupID string, entrantUserID string) (err error) { @@ -712,7 +710,7 @@ func (g *GroupNotificationSender) MemberEnterDirectlyNotification(ctx context.Co return err } tips := &sdkws.MemberEnterTips{Group: group, EntrantUser: user} - return g.msgClient.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.MemberEnterNotification, tips) + return g.Notification(ctx, mcontext.GetOpUserID(ctx), group.GroupID, constant.MemberEnterNotification, tips) } func (g *GroupNotificationSender) SuperGroupNotification(ctx context.Context, sendID, recvID string) (err error) { @@ -722,25 +720,6 @@ func (g *GroupNotificationSender) SuperGroupNotification(ctx context.Context, se log.ZError(ctx, utils.GetFuncName(1)+" failed", err) } }() - req := &msg.SendMsgReq{ - MsgData: &sdkws.MsgData{ - SendID: sendID, - RecvID: recvID, - Content: nil, - MsgFrom: constant.SysMsgType, - ContentType: constant.SuperGroupUpdateNotification, - SessionType: constant.SingleChatType, - CreateTime: time.Now().UnixMilli(), - ClientMsgID: utils.GetMsgID(sendID), - SenderNickname: "", - SenderFaceURL: "", - OfflinePushInfo: &sdkws.OfflinePushInfo{ - Title: "", - Desc: "", - Ex: "", - }, - }, - } - _, err = g.msgClient.SendMsg(ctx, req) + err = g.Notification(ctx, sendID, recvID, constant.SuperGroupUpdateNotification, nil) return err } diff --git a/pkg/rpcclient/push.go b/pkg/rpcclient/push.go index 53cc2bee8..2640535f6 100644 --- a/pkg/rpcclient/push.go +++ b/pkg/rpcclient/push.go @@ -6,27 +6,23 @@ import ( "github.com/OpenIMSDK/Open-IM-Server/pkg/common/config" "github.com/OpenIMSDK/Open-IM-Server/pkg/discoveryregistry" "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/push" + "google.golang.org/grpc" ) type PushClient struct { - MetaClient + conn *grpc.ClientConn } -func NewPushClient(client discoveryregistry.SvcDiscoveryRegistry) *PushClient { - return &PushClient{ - MetaClient: MetaClient{ - client: client, - rpcRegisterName: config.Config.RpcRegisterName.OpenImPushName, - }, +func NewPushClient(discov discoveryregistry.SvcDiscoveryRegistry) *PushClient { + conn, err := discov.GetConn(context.Background(), config.Config.RpcRegisterName.OpenImPushName) + if err != nil { + panic(err) } + return &PushClient{conn: conn} } func (p *PushClient) DelUserPushToken(ctx context.Context, req *push.DelUserPushTokenReq) (*push.DelUserPushTokenResp, error) { - cc, err := p.getConn(ctx) - if err != nil { - return nil, err - } - resp, err := push.NewPushMsgServiceClient(cc).DelUserPushToken(ctx, req) + resp, err := push.NewPushMsgServiceClient(p.conn).DelUserPushToken(ctx, req) if err != nil { return nil, err } diff --git a/pkg/rpcclient/user.go b/pkg/rpcclient/user.go index 6324edd47..3dcb95572 100644 --- a/pkg/rpcclient/user.go +++ b/pkg/rpcclient/user.go @@ -11,27 +11,23 @@ import ( "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/sdkws" "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/user" "github.com/OpenIMSDK/Open-IM-Server/pkg/utils" + "google.golang.org/grpc" ) type UserClient struct { - MetaClient + conn *grpc.ClientConn } -func NewUserClient(client discoveryregistry.SvcDiscoveryRegistry) *UserClient { - return &UserClient{ - MetaClient: MetaClient{ - client: client, - rpcRegisterName: config.Config.RpcRegisterName.OpenImUserName, - }, +func NewUserClient(discov discoveryregistry.SvcDiscoveryRegistry) *UserClient { + conn, err := discov.GetConn(context.Background(), config.Config.RpcRegisterName.OpenImUserName) + if err != nil { + panic(err) } + return &UserClient{conn: conn} } func (u *UserClient) GetUsersInfo(ctx context.Context, userIDs []string) ([]*sdkws.UserInfo, error) { - cc, err := u.getConn(ctx) - if err != nil { - return nil, err - } - resp, err := user.NewUserClient(cc).GetDesignateUsers(ctx, &user.GetDesignateUsersReq{ + resp, err := user.NewUserClient(u.conn).GetDesignateUsers(ctx, &user.GetDesignateUsersReq{ UserIDs: userIDs, }) if err != nil { @@ -97,11 +93,7 @@ func (u *UserClient) GetPublicUserInfoMap(ctx context.Context, userIDs []string, } func (u *UserClient) GetUserGlobalMsgRecvOpt(ctx context.Context, userID string) (int32, error) { - cc, err := u.getConn(ctx) - if err != nil { - return 0, err - } - resp, err := user.NewUserClient(cc).GetGlobalRecvMessageOpt(ctx, &user.GetGlobalRecvMessageOptReq{ + resp, err := user.NewUserClient(u.conn).GetGlobalRecvMessageOpt(ctx, &user.GetGlobalRecvMessageOptReq{ UserID: userID, }) if err != nil { diff --git a/pkg/startrpc/start.go b/pkg/startrpc/start.go index ba46da86e..0d830c6f8 100644 --- a/pkg/startrpc/start.go +++ b/pkg/startrpc/start.go @@ -11,8 +11,8 @@ import ( "github.com/OpenIMSDK/Open-IM-Server/pkg/common/network" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/prome" "github.com/OpenIMSDK/Open-IM-Server/pkg/discoveryregistry" + openKeeper "github.com/OpenIMSDK/Open-IM-Server/pkg/discoveryregistry/zookeeper" "github.com/OpenIMSDK/Open-IM-Server/pkg/utils" - "github.com/OpenIMSDK/openKeeper" grpcPrometheus "github.com/grpc-ecosystem/go-grpc-prometheus" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure"