From b95496df73ae6f3bdf40139c957cc3d1a567874e Mon Sep 17 00:00:00 2001 From: wangchuxiao Date: Mon, 8 May 2023 12:39:45 +0800 Subject: [PATCH] refactor --- cmd/api/main.go | 5 +- go.mod | 36 +- go.sum | 37 + internal/api/auth.go | 4 +- internal/api/conversation.go | 4 +- internal/api/friend.go | 4 +- internal/api/group.go | 4 +- internal/api/msg.go | 6 +- internal/api/third.go | 13 +- internal/api/user.go | 5 +- internal/msggateway/client.go | 8 +- internal/msgtransfer/init.go | 9 +- .../msgtransfer/online_history_msg_handler.go | 54 +- .../online_msg_to_mongo_handler.go | 4 +- internal/rpc/msg/delete.go | 4 +- internal/rpc/msg/send_pull.go | 4 +- internal/rpc/msg/server.go | 4 +- internal/tools/msg.go | 6 +- pkg/a2r/api2rpc.go | 5 +- pkg/common/db/cache/msg.go | 6 +- pkg/common/db/controller/common_msg.go | 803 ++++++++++++++++- pkg/common/db/controller/extend_msg.go | 1 - pkg/common/db/controller/msg.go | 827 ------------------ pkg/common/db/controller/notification.go | 10 +- pkg/common/db/localcache/conversation.go | 5 +- pkg/common/db/localcache/group.go | 5 +- pkg/discoveryregistry/discovery_register.go | 6 +- pkg/discoveryregistry/dns.go | 22 +- pkg/rpcclient/black.go | 2 +- pkg/rpcclient/conversation.go | 12 +- pkg/rpcclient/friend.go | 6 +- pkg/rpcclient/group.go | 10 +- pkg/rpcclient/meta.go | 4 +- pkg/rpcclient/msg.go | 6 +- pkg/rpcclient/user.go | 4 +- pkg/startrpc/start.go | 5 +- 36 files changed, 969 insertions(+), 981 deletions(-) delete mode 100644 pkg/common/db/controller/msg.go diff --git a/cmd/api/main.go b/cmd/api/main.go index e74252d5c..f214bc23e 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -6,6 +6,7 @@ import ( "fmt" "net" "strconv" + "time" "gopkg.in/yaml.v3" @@ -38,7 +39,9 @@ func run(port int) error { return err } var client discoveryregistry.SvcDiscoveryRegistry - client, err = openKeeper.NewClient(config.Config.Zookeeper.ZkAddr, config.Config.Zookeeper.Schema, 10, config.Config.Zookeeper.UserName, config.Config.Zookeeper.Password) + client, err = openKeeper.NewClient(config.Config.Zookeeper.ZkAddr, config.Config.Zookeeper.Schema, + openKeeper.WithFreq(time.Hour), openKeeper.WithUserNameAndPassword(config.Config.Zookeeper.UserName, + config.Config.Zookeeper.Password), openKeeper.WithRoundRobin(), openKeeper.WithTimeout(10)) if err != nil { return err } diff --git a/go.mod b/go.mod index 1d9da27dd..1e8293056 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( firebase.google.com/go v3.13.0+incompatible - github.com/OpenIMSDK/openKeeper v0.0.6 + github.com/OpenIMSDK/openKeeper v0.9.9-0.20230426053850-80d254440004 github.com/OpenIMSDK/open_utils v1.0.8 github.com/Shopify/sarama v1.32.0 github.com/antonfisher/nested-logrus-formatter v1.3.1 @@ -33,8 +33,8 @@ require ( github.com/tencentyun/qcloud-cos-sts-sdk v0.0.0-20210325043845-84a0811633ca go.mongodb.org/mongo-driver v1.8.3 golang.org/x/image v0.3.0 - google.golang.org/api v0.103.0 - google.golang.org/grpc v1.52.3 + google.golang.org/api v0.114.0 + google.golang.org/grpc v1.55.0 google.golang.org/protobuf v1.30.0 gopkg.in/yaml.v3 v3.0.1 gorm.io/driver/mysql v1.3.5 @@ -51,15 +51,15 @@ require ( ) require ( - cloud.google.com/go v0.105.0 // indirect - cloud.google.com/go/compute v1.13.0 // indirect - cloud.google.com/go/compute/metadata v0.2.1 // indirect + cloud.google.com/go v0.110.0 // indirect + cloud.google.com/go/compute v1.19.0 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/firestore v1.9.0 // indirect - cloud.google.com/go/iam v0.8.0 // indirect - cloud.google.com/go/longrunning v0.3.0 // indirect - cloud.google.com/go/storage v1.27.0 // indirect + cloud.google.com/go/iam v0.13.0 // indirect + cloud.google.com/go/longrunning v0.4.1 // indirect + cloud.google.com/go/storage v1.28.1 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dustin/go-humanize v1.0.0 // indirect @@ -80,8 +80,8 @@ require ( github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.1.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect - github.com/googleapis/gax-go/v2 v2.7.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect + github.com/googleapis/gax-go/v2 v2.7.1 // indirect github.com/hashicorp/go-uuid v1.0.2 // indirect github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/jcmturner/aescts/v2 v2.0.0 // indirect @@ -121,12 +121,12 @@ require ( go.opencensus.io v0.24.0 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect - golang.org/x/net v0.8.0 // indirect - golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect + golang.org/x/net v0.9.0 // indirect + golang.org/x/oauth2 v0.6.0 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.6.0 // indirect - golang.org/x/term v0.6.0 // indirect - golang.org/x/text v0.8.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/term v0.7.0 // indirect + golang.org/x/text v0.9.0 // indirect golang.org/x/time v0.1.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/appengine v1.6.7 // indirect @@ -151,7 +151,7 @@ require ( github.com/ugorji/go/codec v1.2.8 // indirect go.uber.org/zap v1.24.0 golang.org/x/crypto v0.5.0 // indirect - google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect gopkg.in/ini.v1 v1.66.2 // indirect ) diff --git a/go.sum b/go.sum index a2a152a37..20ecd88bb 100644 --- a/go.sum +++ b/go.sum @@ -32,6 +32,8 @@ cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34h cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= cloud.google.com/go v0.105.0 h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y= cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= +cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= +cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= @@ -111,9 +113,13 @@ cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= cloud.google.com/go/compute v1.13.0 h1:AYrLkB8NPdDRslNp4Jxmzrhdr03fUAIDbiGFjLWowoU= cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= +cloud.google.com/go/compute v1.19.0 h1:+9zda3WGgW1ZSTlVppLCYFIr48Pa35q1uG2N1itbCEQ= +cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48= cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= @@ -196,6 +202,8 @@ cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHD cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= cloud.google.com/go/iam v0.8.0 h1:E2osAkZzxI/+8pZcxVLcDtAQx/u+hZXVryUaYQ5O0Kk= cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= +cloud.google.com/go/iam v0.13.0 h1:+CmB+K0J/33d0zSQ9SlFWUeCCEn5XJA0ZMZ3pHE9u8k= +cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= @@ -213,6 +221,8 @@ cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6 cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs= cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= +cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= +cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= @@ -330,6 +340,8 @@ cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= cloud.google.com/go/storage v1.27.0 h1:YOO045NZI9RKfCj1c5A/ZtuuENUc8OAW+gHdGnDgyMQ= cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= +cloud.google.com/go/storage v1.28.1 h1:F5QDG5ChchaAVQhINh24U99OWHURqrW8OmQcGKXcbgI= +cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= @@ -377,6 +389,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OpenIMSDK/openKeeper v0.0.6 h1:0eseL/h+evxZAM5Dqs85FEDbDFkTjpVwHBSINQOca5M= github.com/OpenIMSDK/openKeeper v0.0.6/go.mod h1:HwHgo+p3E+aAeiLOSyDwVB2zFJtu+QvnFNlfNjFG9vA= +github.com/OpenIMSDK/openKeeper v0.9.9-0.20230426053850-80d254440004 h1:+1t9eKPKV/NyQARgVUv6TgOWSf8uKu8rkS41+utSIMk= +github.com/OpenIMSDK/openKeeper v0.9.9-0.20230426053850-80d254440004/go.mod h1:HwHgo+p3E+aAeiLOSyDwVB2zFJtu+QvnFNlfNjFG9vA= github.com/OpenIMSDK/open_utils v1.0.8 h1:IopxWgJwEF5ZAPsRuiZZOfcxNOQOCt/p8VDENcHN9r4= github.com/OpenIMSDK/open_utils v1.0.8/go.mod h1:FLoaQblWUVKQgqt2LrNzfSZLT6D3DICBn1kcOMDLUOI= github.com/Shopify/sarama v1.29.0 h1:ARid8o8oieau9XrHI55f/L3EoRAhm9px6sonbD7yuUE= @@ -404,6 +418,8 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -571,6 +587,7 @@ github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIG github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ= github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -594,6 +611,8 @@ github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99 github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs= github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= +github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= @@ -605,6 +624,8 @@ github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqE github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= +github.com/googleapis/gax-go/v2 v2.7.1 h1:gF4c0zjUP2H/s/hEGyLA3I0fA2ZWjzYiONAD6cvPr8A= +github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= @@ -948,6 +969,8 @@ golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfS golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -974,6 +997,8 @@ golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw= +golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1067,12 +1092,16 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1088,6 +1117,8 @@ golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1210,6 +1241,8 @@ google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= google.golang.org/api v0.103.0 h1:9yuVqlu2JCvcLg9p8S3fcFLZij8EPSyvODIY1rkMizQ= google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= +google.golang.org/api v0.114.0 h1:1xQPji6cO2E2vLiI+C/XiFAnsn1WV3mjaEwGLhi3grE= +google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1325,6 +1358,8 @@ google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+ google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w= google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1362,6 +1397,8 @@ google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCD google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.52.3 h1:pf7sOysg4LdgBqduXveGKrcEwbStiK2rtfghdzlUYDQ= google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= +google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= +google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= diff --git a/internal/api/auth.go b/internal/api/auth.go index 861a10e6f..9c07bf3ab 100644 --- a/internal/api/auth.go +++ b/internal/api/auth.go @@ -20,8 +20,8 @@ type Auth struct { c discoveryregistry.SvcDiscoveryRegistry } -func (o *Auth) client() (auth.AuthClient, error) { - conn, err := o.c.GetConn(config.Config.RpcRegisterName.OpenImAuthName) +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 } diff --git a/internal/api/conversation.go b/internal/api/conversation.go index 218186518..fab5c4a7a 100644 --- a/internal/api/conversation.go +++ b/internal/api/conversation.go @@ -20,8 +20,8 @@ type Conversation struct { c discoveryregistry.SvcDiscoveryRegistry } -func (o *Conversation) client() (conversation.ConversationClient, error) { - conn, err := o.c.GetConn(config.Config.RpcRegisterName.OpenImConversationName) +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 } diff --git a/internal/api/friend.go b/internal/api/friend.go index b31dda45b..3ac40f7c5 100644 --- a/internal/api/friend.go +++ b/internal/api/friend.go @@ -21,8 +21,8 @@ type Friend struct { c discoveryregistry.SvcDiscoveryRegistry } -func (o *Friend) client() (friend.FriendClient, error) { - conn, err := o.c.GetConn(config.Config.RpcRegisterName.OpenImFriendName) +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 } diff --git a/internal/api/group.go b/internal/api/group.go index f1070aab5..bd517d050 100644 --- a/internal/api/group.go +++ b/internal/api/group.go @@ -21,8 +21,8 @@ type Group struct { c discoveryregistry.SvcDiscoveryRegistry } -func (o *Group) client() (group.GroupClient, error) { - conn, err := o.c.GetConn(config.Config.RpcRegisterName.OpenImGroupName) +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 } diff --git a/internal/api/msg.go b/internal/api/msg.go index c595308eb..94ee47aa2 100644 --- a/internal/api/msg.go +++ b/internal/api/msg.go @@ -107,8 +107,8 @@ func (m Message) newUserSendMsgReq(c *gin.Context, params *apistruct.ManagementS return &pbData } -func (m *Message) client() (msg.MsgClient, error) { - conn, err := m.c.GetConn(config.Config.RpcRegisterName.OpenImMsgName) +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 } @@ -199,7 +199,7 @@ func (m *Message) SendMessage(c *gin.Context) { return } pbReq := m.newUserSendMsgReq(c, ¶ms) - conn, err := m.c.GetConn(config.Config.RpcRegisterName.OpenImMsgName) + conn, err := m.c.GetConn(c, config.Config.RpcRegisterName.OpenImMsgName) if err != nil { apiresp.GinError(c, errs.ErrInternalServer) return diff --git a/internal/api/third.go b/internal/api/third.go index 6e95b72e5..9cdd82217 100644 --- a/internal/api/third.go +++ b/internal/api/third.go @@ -2,6 +2,10 @@ package api import ( "context" + "math/rand" + "net/http" + "strconv" + "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/constant" @@ -10,9 +14,6 @@ import ( "github.com/OpenIMSDK/Open-IM-Server/pkg/errs" "github.com/OpenIMSDK/Open-IM-Server/pkg/proto/third" "github.com/gin-gonic/gin" - "math/rand" - "net/http" - "strconv" ) var _ context.Context // 解决goland编辑器bug @@ -25,8 +26,8 @@ type Third struct { c discoveryregistry.SvcDiscoveryRegistry } -func (o *Third) client() (third.ThirdClient, error) { - conn, err := o.c.GetConn(config.Config.RpcRegisterName.OpenImThirdName) +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 } @@ -84,7 +85,7 @@ func (o *Third) GetURL(c *gin.Context) { expires = 3600 * 1000 } attachment, _ := strconv.ParseBool(c.Query("attachment")) - client, err := o.client() + client, err := o.client(c) if err != nil { c.String(http.StatusInternalServerError, err.Error()) return diff --git a/internal/api/user.go b/internal/api/user.go index ae9291251..405b03fd4 100644 --- a/internal/api/user.go +++ b/internal/api/user.go @@ -2,6 +2,7 @@ package api import ( "context" + "github.com/OpenIMSDK/Open-IM-Server/pkg/apiresp" "github.com/OpenIMSDK/Open-IM-Server/pkg/apistruct" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/tokenverify" @@ -24,8 +25,8 @@ type User struct { c discoveryregistry.SvcDiscoveryRegistry } -func (u *User) client() (user.UserClient, error) { - conn, err := u.c.GetConn(config.Config.RpcRegisterName.OpenImUserName) +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 } diff --git a/internal/msggateway/client.go b/internal/msggateway/client.go index 01aa2bd7b..bf0966283 100644 --- a/internal/msggateway/client.go +++ b/internal/msggateway/client.go @@ -203,7 +203,13 @@ func (c *Client) replyMessage(ctx context.Context, binaryReq *Req, err error, re } func (c *Client) PushMessage(ctx context.Context, msgData *sdkws.MsgData) error { var msg sdkws.PushMessages - msg.Msgs = append(msg.Msgs, msgData) + conversationID := utils.GetConversationIDByMsg(msgData) + m := map[string]*sdkws.PullMsgs{conversationID: {Msgs: []*sdkws.MsgData{msgData}}} + if utils.IsNotification(conversationID) { + msg.NotificationMsgs = m + } else { + msg.Msgs = m + } data, err := proto.Marshal(&msg) if err != nil { return err diff --git a/internal/msgtransfer/init.go b/internal/msgtransfer/init.go index 19280a215..41643ccd3 100644 --- a/internal/msgtransfer/init.go +++ b/internal/msgtransfer/init.go @@ -2,6 +2,7 @@ package msgtransfer import ( "fmt" + "time" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/config" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/cache" @@ -38,7 +39,9 @@ func StartTransfer(prometheusPort int) error { if err != nil { return err } - client, err := openKeeper.NewClient(config.Config.Zookeeper.ZkAddr, config.Config.Zookeeper.Schema, 10, config.Config.Zookeeper.UserName, config.Config.Zookeeper.Password) + client, err := openKeeper.NewClient(config.Config.Zookeeper.ZkAddr, config.Config.Zookeeper.Schema, + openKeeper.WithFreq(time.Hour), openKeeper.WithUserNameAndPassword(config.Config.Zookeeper.UserName, + config.Config.Zookeeper.Password), openKeeper.WithRoundRobin(), openKeeper.WithTimeout(10)) if err != nil { return err } @@ -50,7 +53,7 @@ func StartTransfer(prometheusPort int) error { extendMsgCache := cache.NewExtendMsgSetCacheRedis(rdb, extendMsgModel, cache.GetDefaultOpt()) chatLogDatabase := controller.NewChatLogDatabase(relation.NewChatLogGorm(db)) extendMsgDatabase := controller.NewExtendMsgDatabase(extendMsgModel, extendMsgCache, tx.NewMongo(mongo.GetClient())) - msgDatabase := controller.NewMsgDatabase(msgDocModel, msgModel) + msgDatabase := controller.NewCommonMsgDatabase(msgDocModel, msgModel) notificationDatabase := controller.NewNotificationDatabase(notificationDocModel, notificationModel) conversationRpcClient := rpcclient.NewConversationClient(client) @@ -60,7 +63,7 @@ func StartTransfer(prometheusPort int) error { } func NewMsgTransfer(chatLogDatabase controller.ChatLogDatabase, - extendMsgDatabase controller.ExtendMsgDatabase, msgDatabase controller.MsgDatabase, notificationDatabase controller.NotificationDatabase, + extendMsgDatabase controller.ExtendMsgDatabase, msgDatabase controller.CommonMsgDatabase, notificationDatabase controller.NotificationDatabase, conversationRpcClient *rpcclient.ConversationClient) *MsgTransfer { return &MsgTransfer{persistentCH: NewPersistentConsumerHandler(chatLogDatabase), historyCH: NewOnlineHistoryRedisConsumerHandler(msgDatabase, conversationRpcClient), historyMongoCH: NewOnlineHistoryMongoConsumerHandler(msgDatabase, notificationDatabase), modifyCH: NewModifyMsgConsumerHandler(extendMsgDatabase)} diff --git a/internal/msgtransfer/online_history_msg_handler.go b/internal/msgtransfer/online_history_msg_handler.go index 4c4cbd907..357cd0938 100644 --- a/internal/msgtransfer/online_history_msg_handler.go +++ b/internal/msgtransfer/online_history_msg_handler.go @@ -11,7 +11,6 @@ import ( "github.com/OpenIMSDK/Open-IM-Server/pkg/common/kafka" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/log" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/mcontext" - "github.com/OpenIMSDK/Open-IM-Server/pkg/common/prome" "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" @@ -55,12 +54,12 @@ type OnlineHistoryRedisConsumerHandler struct { singleMsgSuccessCountMutex sync.Mutex singleMsgFailedCountMutex sync.Mutex - msgDatabase controller.MsgDatabase + msgDatabase controller.CommonMsgDatabase conversationRpcClient *rpcclient.ConversationClient groupRpcClient *rpcclient.GroupClient } -func NewOnlineHistoryRedisConsumerHandler(database controller.MsgDatabase, conversationRpcClient *rpcclient.ConversationClient) *OnlineHistoryRedisConsumerHandler { +func NewOnlineHistoryRedisConsumerHandler(database controller.CommonMsgDatabase, conversationRpcClient *rpcclient.ConversationClient) *OnlineHistoryRedisConsumerHandler { var och OnlineHistoryRedisConsumerHandler och.msgDatabase = database och.msgDistributionCh = make(chan Cmd2Value) //no buffer channel @@ -143,7 +142,7 @@ func (och *OnlineHistoryRedisConsumerHandler) getPushStorageMsgList(conversation func (och *OnlineHistoryRedisConsumerHandler) handleNotification(ctx context.Context, conversationID string, storageList, notStorageList []*sdkws.MsgData) { och.toPushTopic(ctx, conversationID, notStorageList) if len(storageList) > 0 { - lastSeq, err := och.msgDatabase.NotificationBatchInsertChat2Cache(ctx, conversationID, storageList) + lastSeq, _, err := och.msgDatabase.BatchInsertChat2Cache(ctx, conversationID, storageList) if err != nil { log.ZError(ctx, "notification batch insert to redis error", err, "conversationID", conversationID, "storageList", storageList) return @@ -163,31 +162,8 @@ func (och *OnlineHistoryRedisConsumerHandler) toPushTopic(ctx context.Context, c func (och *OnlineHistoryRedisConsumerHandler) handleMsg(ctx context.Context, conversationID string, storageList, notStorageList []*sdkws.MsgData) { och.toPushTopic(ctx, conversationID, notStorageList) if len(storageList) > 0 { - currentMaxSeq, err := och.msgDatabase.GetMaxSeq(ctx, conversationID) - if err == redis.Nil { - if storageList[0].SessionType == constant.SuperGroupChatType { - log.ZInfo(ctx, "group chat first create conversation", "conversationID", conversationID) - userIDs, err := och.groupRpcClient.GetGroupMemberIDs(ctx, storageList[0].GroupID) - if err != nil { - log.ZError(ctx, "get group member ids error", err, "conversationID", conversationID) - } else { - if err := och.conversationRpcClient.GroupChatFirstCreateConversation(ctx, storageList[0].GroupID, userIDs); err != nil { - log.ZError(ctx, "single chat first create conversation error", err, "conversationID", conversationID) - } - } - } else { - if err := och.conversationRpcClient.SingleChatFirstCreateConversation(ctx, storageList[0].RecvID, storageList[0].SendID); err != nil { - log.ZError(ctx, "single chat first create conversation error", err, "conversationID", conversationID) - } - } - } - if err != nil && err != redis.Nil { - prome.Inc(prome.SeqGetFailedCounter) - log.ZError(ctx, "get max seq err", err, "conversationID", conversationID) - return - } - prome.Inc(prome.SeqGetSuccessCounter) - lastSeq, err := och.msgDatabase.BatchInsertChat2Cache(ctx, conversationID, storageList, currentMaxSeq) + + lastSeq, isNewConversation, err := och.msgDatabase.BatchInsertChat2Cache(ctx, conversationID, storageList) if err != nil && err != redis.Nil { log.ZError(ctx, "batch data insert to redis err", err, "storageMsgList", storageList) och.singleMsgFailedCountMutex.Lock() @@ -195,7 +171,25 @@ func (och *OnlineHistoryRedisConsumerHandler) handleMsg(ctx context.Context, con och.singleMsgFailedCountMutex.Unlock() return } - log.ZDebug(ctx, "success to next topic") + if isNewConversation { + if storageList[0].SessionType == constant.SuperGroupChatType { + log.ZInfo(ctx, "group chat first create conversation", "conversationID", conversationID) + userIDs, err := och.groupRpcClient.GetGroupMemberIDs(ctx, storageList[0].GroupID) + if err != nil { + log.ZWarn(ctx, "get group member ids error", err, "conversationID", conversationID) + } else { + if err := och.conversationRpcClient.GroupChatFirstCreateConversation(ctx, storageList[0].GroupID, userIDs); err != nil { + log.ZWarn(ctx, "single chat first create conversation error", err, "conversationID", conversationID) + } + } + } else { + if err := och.conversationRpcClient.SingleChatFirstCreateConversation(ctx, storageList[0].RecvID, storageList[0].SendID); err != nil { + log.ZWarn(ctx, "single chat first create conversation error", err, "conversationID", conversationID) + } + } + } + + log.ZDebug(ctx, "success incr to next topic") och.singleMsgSuccessCountMutex.Lock() och.singleMsgSuccessCount += uint64(len(storageList)) och.singleMsgSuccessCountMutex.Unlock() diff --git a/internal/msgtransfer/online_msg_to_mongo_handler.go b/internal/msgtransfer/online_msg_to_mongo_handler.go index 6de8dbf47..24c6b52f1 100644 --- a/internal/msgtransfer/online_msg_to_mongo_handler.go +++ b/internal/msgtransfer/online_msg_to_mongo_handler.go @@ -20,11 +20,11 @@ import ( type OnlineHistoryMongoConsumerHandler struct { historyConsumerGroup *kfk.MConsumerGroup - msgDatabase controller.MsgDatabase + msgDatabase controller.CommonMsgDatabase notificationDatabase controller.NotificationDatabase } -func NewOnlineHistoryMongoConsumerHandler(database controller.MsgDatabase, notificationDatabase controller.NotificationDatabase) *OnlineHistoryMongoConsumerHandler { +func NewOnlineHistoryMongoConsumerHandler(database controller.CommonMsgDatabase, notificationDatabase controller.NotificationDatabase) *OnlineHistoryMongoConsumerHandler { mc := &OnlineHistoryMongoConsumerHandler{ historyConsumerGroup: kfk.NewMConsumerGroup(&kfk.MConsumerGroupConfig{KafkaVersion: sarama.V2_0_0_0, OffsetsInitial: sarama.OffsetNewest, IsReturnErr: false}, []string{config.Config.Kafka.MsgToMongo.Topic}, diff --git a/internal/rpc/msg/delete.go b/internal/rpc/msg/delete.go index a3fd3f489..dbf2634d0 100644 --- a/internal/rpc/msg/delete.go +++ b/internal/rpc/msg/delete.go @@ -31,8 +31,10 @@ func (m *msgServer) ClearMsg(ctx context.Context, req *msg.ClearMsgReq) (*msg.Cl if err := tokenverify.CheckAccessV3(ctx, req.UserID); err != nil { return nil, err } - if err := m.MsgDatabase.CleanUpConversationMsgs(ctx, req.UserID); err != nil { + conversationIDs, err := m.Conversation.GetConversationIDs(ctx, req.UserID) + if err != nil { return nil, err } + m.MsgDatabase.CleanUpUserConversationsMsgs(ctx, req.UserID, conversationIDs) return resp, nil } diff --git a/internal/rpc/msg/send_pull.go b/internal/rpc/msg/send_pull.go index b547f1051..f9f565ffd 100644 --- a/internal/rpc/msg/send_pull.go +++ b/internal/rpc/msg/send_pull.go @@ -136,7 +136,7 @@ func (m *msgServer) sendMsgGroupChat(ctx context.Context, req *msg.SendMsgReq) ( for i := 0; i < len(memberUserIDList)/split; i++ { wg.Add(1) tmp := valueCopy(req) - go func() { + go func(i int) { err := m.sendMsgToGroupOptimization(ctx, memberUserIDList[i*split:(i+1)*split], tmp, &wg) if err != nil { mutex.Lock() @@ -144,7 +144,7 @@ func (m *msgServer) sendMsgGroupChat(ctx context.Context, req *msg.SendMsgReq) ( mutex.Unlock() } - }() + }(i) } if remain > 0 { wg.Add(1) diff --git a/internal/rpc/msg/server.go b/internal/rpc/msg/server.go index f3e3ff4c8..0aecb0943 100644 --- a/internal/rpc/msg/server.go +++ b/internal/rpc/msg/server.go @@ -24,7 +24,7 @@ import ( type MessageInterceptorChain []MessageInterceptorFunc type msgServer struct { RegisterCenter discoveryregistry.SvcDiscoveryRegistry - MsgDatabase controller.MsgDatabase + MsgDatabase controller.CommonMsgDatabase notificationDatabase controller.NotificationDatabase ExtendMsgDatabase controller.ExtendMsgDatabase Group *rpcclient.GroupClient @@ -64,7 +64,7 @@ func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e extendMsgModel := unrelation.NewExtendMsgSetMongoDriver(mongo.GetDatabase()) extendMsgCacheModel := cache.NewExtendMsgSetCacheRedis(rdb, extendMsgModel, cache.GetDefaultOpt()) extendMsgDatabase := controller.NewExtendMsgDatabase(extendMsgModel, extendMsgCacheModel, tx.NewMongo(mongo.GetClient())) - msgDatabase := controller.NewMsgDatabase(msgDocModel, cacheModel) + msgDatabase := controller.NewCommonMsgDatabase(msgDocModel, cacheModel) s := &msgServer{ Conversation: rpcclient.NewConversationClient(client), diff --git a/internal/tools/msg.go b/internal/tools/msg.go index 3b7192c18..c88b887db 100644 --- a/internal/tools/msg.go +++ b/internal/tools/msg.go @@ -20,14 +20,14 @@ import ( ) type MsgTool struct { - msgDatabase controller.MsgDatabase + msgDatabase controller.CommonMsgDatabase userDatabase controller.UserDatabase groupDatabase controller.GroupDatabase } var errSeq = errors.New("cache max seq and mongo max seq is diff > 10") -func NewMsgTool(msgDatabase controller.MsgDatabase, userDatabase controller.UserDatabase, groupDatabase controller.GroupDatabase) *MsgTool { +func NewMsgTool(msgDatabase controller.CommonMsgDatabase, userDatabase controller.UserDatabase, groupDatabase controller.GroupDatabase) *MsgTool { return &MsgTool{ msgDatabase: msgDatabase, userDatabase: userDatabase, @@ -49,7 +49,7 @@ func InitMsgTool() (*MsgTool, error) { return nil, err } userDB := relation.NewUserGorm(db) - msgDatabase := controller.InitMsgDatabase(rdb, mongo.GetDatabase()) + msgDatabase := controller.InitCommonMsgDatabase(rdb, mongo.GetDatabase()) userDatabase := controller.NewUserDatabase(userDB, cache.NewUserCacheRedis(rdb, relation.NewUserGorm(db), cache.GetDefaultOpt()), tx.NewGorm(db)) groupDatabase := controller.InitGroupDatabase(db, rdb, mongo.GetDatabase()) msgTool := NewMsgTool(msgDatabase, userDatabase, groupDatabase) diff --git a/pkg/a2r/api2rpc.go b/pkg/a2r/api2rpc.go index ebdbf11ce..7c21961e9 100644 --- a/pkg/a2r/api2rpc.go +++ b/pkg/a2r/api2rpc.go @@ -2,6 +2,7 @@ package a2r import ( "context" + "github.com/OpenIMSDK/Open-IM-Server/pkg/apiresp" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/log" "github.com/OpenIMSDK/Open-IM-Server/pkg/errs" @@ -11,7 +12,7 @@ import ( func Call[A, B, C any]( rpc func(client C, ctx context.Context, req *A, options ...grpc.CallOption) (*B, error), - client func() (C, error), + client func(ctx context.Context) (C, error), c *gin.Context, ) { var req A @@ -27,7 +28,7 @@ func Call[A, B, C any]( return } } - cli, err := client() + 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连接失败 diff --git a/pkg/common/db/cache/msg.go b/pkg/common/db/cache/msg.go index c8a5437c8..4b12413ba 100644 --- a/pkg/common/db/cache/msg.go +++ b/pkg/common/db/cache/msg.go @@ -59,7 +59,7 @@ type MsgModel interface { GetMessagesBySeq(ctx context.Context, conversationID string, seqList []int64) (seqMsg []*sdkws.MsgData, failedSeqList []int64, err error) SetMessageToCache(ctx context.Context, conversationID string, msgList []*sdkws.MsgData) (int, error) DeleteMessageFromCache(ctx context.Context, conversationID string, msgList []*sdkws.MsgData) error - CleanUpOneUserAllMsg(ctx context.Context, userID string) error + CleanUpOneConversationAllMsg(ctx context.Context, conversationID string) error HandleSignalInvite(ctx context.Context, msg *sdkws.MsgData, pushToUserID string) (isSend bool, err error) GetSignalInvitationInfoByClientMsgID(ctx context.Context, clientMsgID string) (invitationInfo *sdkws.SignalInviteReq, err error) GetAvailableSignalInvitationInfo(ctx context.Context, userID string) (invitationInfo *sdkws.SignalInviteReq, err error) @@ -316,8 +316,8 @@ func (c *msgCache) DeleteMessageFromCache(ctx context.Context, userID string, ms return errs.Wrap(err) } -func (c *msgCache) CleanUpOneUserAllMsg(ctx context.Context, userID string) error { - vals, err := c.rdb.Keys(ctx, c.allMessageCacheKey(userID)).Result() +func (c *msgCache) CleanUpOneConversationAllMsg(ctx context.Context, conversationID string) error { + vals, err := c.rdb.Keys(ctx, c.allMessageCacheKey(conversationID)).Result() if err == redis.Nil { return nil } diff --git a/pkg/common/db/controller/common_msg.go b/pkg/common/db/controller/common_msg.go index 58f4f0d81..385be4f8c 100644 --- a/pkg/common/db/controller/common_msg.go +++ b/pkg/common/db/controller/common_msg.go @@ -1,33 +1,800 @@ package controller import ( - "context" + "fmt" + "sort" + "sync" + "time" + "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/db/cache" + unRelationTb "github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/table/unrelation" + "github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/unrelation" + "github.com/OpenIMSDK/Open-IM-Server/pkg/common/kafka" + "github.com/OpenIMSDK/Open-IM-Server/pkg/common/log" + "github.com/OpenIMSDK/Open-IM-Server/pkg/common/prome" + "github.com/OpenIMSDK/Open-IM-Server/pkg/errs" + "github.com/gogo/protobuf/sortkeys" + + "context" + "errors" + + pbMsg "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" + "github.com/go-redis/redis/v8" + "go.mongodb.org/mongo-driver/mongo" + + "github.com/golang/protobuf/proto" ) -// conversationID 可以是通知也可以是conversation -type commonMsgDatabase interface { +type CommonMsgDatabase interface { + // 批量插入消息 BatchInsertChat2DB(ctx context.Context, conversationID string, msgs []*sdkws.MsgData, currentMaxSeq int64) error + // 刪除redis中消息缓存 DeleteMessageFromCache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) error - - GetMsgBySeqs(ctx context.Context, conversationID string, seqs []int64) (seqMsg []*sdkws.MsgData, err error) + // incrSeq然后批量插入缓存 + BatchInsertChat2Cache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) (seq int64, isNewConversation bool, err error) + // 删除消息 返回不存在的seqList + DelMsgBySeqs(ctx context.Context, conversationID string, seqs []int64) (totalUnExistSeqs []int64, err error) + // 通过seqList获取mongo中写扩散消息 GetMsgBySeqsRange(ctx context.Context, conversationID string, begin, end, num int64) (seqMsg []*sdkws.MsgData, err error) - CleanUpUserMsg(ctx context.Context, conversationID string) error - DelMsgsBySeqs(ctx context.Context, conversationID string, seqs []int64) (totalUnExistSeqs []int64, err error) - DelMsgsAndResetMinSeq(ctx context.Context, conversationID string, userIDs []string, remainTime int64) error - - GetMinMaxSeqInMongoAndCache(ctx context.Context, conversationID string) (minSeqMongo, maxSeqMongo, minSeqCache, maxSeqCache int64, err error) - - GetMaxSeq(ctx context.Context, conversationID string) (int64, error) - GetMinSeq(ctx context.Context, conversationID string) (int64, error) - SetMaxSeq(ctx context.Context, conversationID string, seq int64) error - SetMinSeq(ctx context.Context, conversationID string, seq int64) error + // 通过seqList获取大群在 mongo里面的消息 + GetMsgBySeqs(ctx context.Context, conversationID string, seqs []int64) (seqMsg []*sdkws.MsgData, err error) + // 删除会话消息重置最小seq, remainTime为消息保留的时间单位秒,超时消息删除, 传0删除所有消息(此方法不删除redis cache) + DeleteConversationMsgsAndSetMinSeq(ctx context.Context, conversationID string, remainTime int64) error + CleanUpUserConversationsMsgs(ctx context.Context, userID string, conversationIDs []string) + SetMaxSeq(ctx context.Context, conversationID string, maxSeq int64) error GetMaxSeqs(ctx context.Context, conversationIDs []string) (map[string]int64, error) + GetMaxSeq(ctx context.Context, conversationID string) (int64, error) + SetMinSeq(ctx context.Context, conversationID string, minSeq int64) error GetMinSeqs(ctx context.Context, conversationIDs []string) (map[string]int64, error) + GetMinSeq(ctx context.Context, conversationID string) (int64, error) + GetConversationUserMinSeq(ctx context.Context, conversationID string, userID string) (int64, error) + GetConversationUserMinSeqs(ctx context.Context, conversationID string, userIDs []string) (map[string]int64, error) + SetConversationUserMinSeq(ctx context.Context, conversationID string, userID string, minSeq int64) error + SetConversationUserMinSeqs(ctx context.Context, conversationID string, seqs map[string]int64) (err error) - MsgToMQ(ctx context.Context, conversationID string, msg2mq *sdkws.MsgData) error - MsgToModifyMQ(ctx context.Context, conversationID string, messages []*sdkws.MsgData) error + GetConversationMinMaxSeqInMongoAndCache(ctx context.Context, conversationID string) (minSeqMongo, maxSeqMongo, minSeqCache, maxSeqCache int64, err error) + SetSendMsgStatus(ctx context.Context, id string, status int32) error + GetSendMsgStatus(ctx context.Context, id string) (int32, error) + + // to mq + MsgToMQ(ctx context.Context, key string, msg2mq *sdkws.MsgData) error + MsgToModifyMQ(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) error MsgToPushMQ(ctx context.Context, conversationID string, msg2mq *sdkws.MsgData) (int32, int64, error) - MsgToMongoMQ(ctx context.Context, conversationID string, messages []*sdkws.MsgData, lastSeq int64) error + MsgToMongoMQ(ctx context.Context, conversationID string, msgs []*sdkws.MsgData, lastSeq int64) error + + // modify + JudgeMessageReactionExist(ctx context.Context, clientMsgID string, sessionType int32) (bool, error) + SetMessageTypeKeyValue(ctx context.Context, clientMsgID string, sessionType int32, typeKey, value string) error + SetMessageReactionExpire(ctx context.Context, clientMsgID string, sessionType int32, expiration time.Duration) (bool, error) + GetExtendMsg(ctx context.Context, conversationID string, sessionType int32, clientMsgID string, maxMsgUpdateTime int64) (*pbMsg.ExtendMsg, error) + InsertOrUpdateReactionExtendMsgSet(ctx context.Context, conversationID string, sessionType int32, clientMsgID string, msgFirstModifyTime int64, reactionExtensionList map[string]*sdkws.KeyValue) error + GetMessageTypeKeyValue(ctx context.Context, clientMsgID string, sessionType int32, typeKey string) (string, error) + GetOneMessageAllReactionList(ctx context.Context, clientMsgID string, sessionType int32) (map[string]string, error) + DeleteOneMessageKey(ctx context.Context, clientMsgID string, sessionType int32, subKey string) error + DeleteReactionExtendMsgSet(ctx context.Context, conversationID string, sessionType int32, clientMsgID string, msgFirstModifyTime int64, reactionExtensionList map[string]*sdkws.KeyValue) error +} + +func NewCommonMsgDatabase(msgDocModel unRelationTb.MsgDocModelInterface, cacheModel cache.MsgModel) CommonMsgDatabase { + return &commonMsgDatabase{ + msgDocDatabase: msgDocModel, + cache: cacheModel, + producer: kafka.NewKafkaProducer(config.Config.Kafka.Ws2mschat.Addr, config.Config.Kafka.Ws2mschat.Topic), + producerToMongo: kafka.NewKafkaProducer(config.Config.Kafka.MsgToMongo.Addr, config.Config.Kafka.MsgToMongo.Topic), + producerToPush: kafka.NewKafkaProducer(config.Config.Kafka.Ms2pschat.Addr, config.Config.Kafka.Ms2pschat.Topic), + producerToModify: kafka.NewKafkaProducer(config.Config.Kafka.MsgToModify.Addr, config.Config.Kafka.MsgToModify.Topic), + } +} + +func InitCommonMsgDatabase(rdb redis.UniversalClient, database *mongo.Database) CommonMsgDatabase { + cacheModel := cache.NewMsgCacheModel(rdb) + msgDocModel := unrelation.NewMsgMongoDriver(database) + CommonMsgDatabase := NewCommonMsgDatabase(msgDocModel, cacheModel) + return CommonMsgDatabase +} + +type commonMsgDatabase struct { + msgDocDatabase unRelationTb.MsgDocModelInterface + extendMsgDatabase unRelationTb.ExtendMsgSetModelInterface + extendMsgSetModel unRelationTb.ExtendMsgSetModel + cache cache.MsgModel + producer *kafka.Producer + producerToMongo *kafka.Producer + producerToModify *kafka.Producer + producerToPush *kafka.Producer + // model + msg unRelationTb.MsgDocModel +} + +func (db *commonMsgDatabase) MsgToMQ(ctx context.Context, key string, msg2mq *sdkws.MsgData) error { + _, _, err := db.producer.SendMessage(ctx, key, msg2mq) + return err +} + +func (db *commonMsgDatabase) MsgToModifyMQ(ctx context.Context, conversationID string, messages []*sdkws.MsgData) error { + if len(messages) > 0 { + _, _, err := db.producerToModify.SendMessage(ctx, conversationID, &pbMsg.MsgDataToModifyByMQ{ConversationID: conversationID, Messages: messages}) + return err + } + return nil +} + +func (db *commonMsgDatabase) MsgToPushMQ(ctx context.Context, conversationID string, msg2mq *sdkws.MsgData) (int32, int64, error) { + partition, offset, err := db.producerToPush.SendMessage(ctx, conversationID, &pbMsg.PushMsgDataToMQ{MsgData: msg2mq, ConversationID: conversationID}) + if err != nil { + log.ZError(ctx, "MsgToPushMQ", err, "key", conversationID, "msg2mq", msg2mq) + } + return partition, offset, err +} + +func (db *commonMsgDatabase) MsgToMongoMQ(ctx context.Context, conversationID string, messages []*sdkws.MsgData, lastSeq int64) error { + if len(messages) > 0 { + _, _, err := db.producerToModify.SendMessage(ctx, conversationID, &pbMsg.MsgDataToMongoByMQ{LastSeq: lastSeq, ConversationID: conversationID, MsgData: messages}) + return err + } + return nil +} + +func (db *commonMsgDatabase) BatchInsertChat2DB(ctx context.Context, conversationID string, msgList []*sdkws.MsgData, currentMaxSeq int64) error { + if int64(len(msgList)) > db.msg.GetSingleGocMsgNum() { + return errors.New("too large") + } + var remain int64 + blk0 := db.msg.GetSingleGocMsgNum() - 1 + //currentMaxSeq 4998 + if currentMaxSeq < db.msg.GetSingleGocMsgNum() { + remain = blk0 - currentMaxSeq //1 + } else { + excludeBlk0 := currentMaxSeq - blk0 //=1 + //(5000-1)%5000 == 4999 + remain = (db.msg.GetSingleGocMsgNum() - (excludeBlk0 % db.msg.GetSingleGocMsgNum())) % db.msg.GetSingleGocMsgNum() + } + //remain=1 + var insertCounter int64 + msgsToMongo := make([]unRelationTb.MsgInfoModel, 0) + msgsToMongoNext := make([]unRelationTb.MsgInfoModel, 0) + docID := "" + docIDNext := "" + var err error + for _, m := range msgList { + currentMaxSeq++ + sMsg := unRelationTb.MsgInfoModel{} + sMsg.SendTime = m.SendTime + m.Seq = currentMaxSeq + if sMsg.Msg, err = proto.Marshal(m); err != nil { + return utils.Wrap(err, "") + } + if insertCounter < remain { + msgsToMongo = append(msgsToMongo, sMsg) + insertCounter++ + docID = db.msg.GetDocID(conversationID, currentMaxSeq) + } else { + msgsToMongoNext = append(msgsToMongoNext, sMsg) + docIDNext = db.msg.GetDocID(conversationID, currentMaxSeq) + } + } + + if docID != "" { + err = db.msgDocDatabase.PushMsgsToDoc(ctx, docID, msgsToMongo) + if err != nil { + if err == mongo.ErrNoDocuments { + doc := &unRelationTb.MsgDocModel{} + doc.DocID = docID + doc.Msg = msgsToMongo + if err = db.msgDocDatabase.Create(ctx, doc); err != nil { + prome.Inc(prome.MsgInsertMongoFailedCounter) + return err + } + prome.Inc(prome.MsgInsertMongoSuccessCounter) + } else { + prome.Inc(prome.MsgInsertMongoFailedCounter) + return err + } + } else { + log.ZDebug(ctx, "PushMsgsToDoc success", "docID", docID, "len", len(msgsToMongo)) + prome.Inc(prome.MsgInsertMongoSuccessCounter) + } + } + if docIDNext != "" { + nextDoc := &unRelationTb.MsgDocModel{} + nextDoc.DocID = docIDNext + nextDoc.Msg = msgsToMongoNext + log.ZDebug(ctx, "create next doc", "docIDNext", docIDNext, "len", len(nextDoc.Msg)) + if err = db.msgDocDatabase.Create(ctx, nextDoc); err != nil { + prome.Inc(prome.MsgInsertMongoFailedCounter) + return utils.Wrap(err, "") + } + prome.Inc(prome.MsgInsertMongoSuccessCounter) + } + return nil +} + +func (db *commonMsgDatabase) DeleteMessageFromCache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) error { + return db.cache.DeleteMessageFromCache(ctx, conversationID, msgs) +} + +func (db *commonMsgDatabase) BatchInsertChat2Cache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) (seq int64, isNew bool, err error) { + currentMaxSeq, err := db.cache.GetMaxSeq(ctx, conversationID) + if err != nil && err != redis.Nil { + prome.Inc(prome.SeqGetFailedCounter) + return 0, false, err + } + prome.Inc(prome.SeqGetSuccessCounter) + lenList := len(msgs) + if int64(lenList) > db.msg.GetSingleGocMsgNum() { + return 0, false, errors.New("too large") + } + if lenList < 1 { + return 0, false, errors.New("too short as 0") + } + if err == redis.Nil { + isNew = true + } + lastMaxSeq := currentMaxSeq + for _, m := range msgs { + currentMaxSeq++ + m.Seq = currentMaxSeq + } + failedNum, err := db.cache.SetMessageToCache(ctx, conversationID, msgs) + if err != nil { + prome.Add(prome.MsgInsertRedisFailedCounter, failedNum) + log.ZError(ctx, "setMessageToCache error", err, "len", len(msgs), "conversationID", conversationID) + } else { + prome.Inc(prome.MsgInsertRedisSuccessCounter) + } + err = db.cache.SetMaxSeq(ctx, conversationID, currentMaxSeq) + if err != nil { + prome.Inc(prome.SeqSetFailedCounter) + } else { + prome.Inc(prome.SeqSetSuccessCounter) + } + return lastMaxSeq, isNew, utils.Wrap(err, "") +} + +func (db *commonMsgDatabase) DelMsgBySeqs(ctx context.Context, conversationID string, seqs []int64) (totalUnExistSeqs []int64, err error) { + sortkeys.Int64s(seqs) + docIDSeqsMap := db.msg.GetDocIDSeqsMap(conversationID, seqs) + lock := sync.Mutex{} + var wg sync.WaitGroup + wg.Add(len(docIDSeqsMap)) + for k, v := range docIDSeqsMap { + go func(docID string, seqs []int64) { + defer wg.Done() + unExistSeqList, err := db.DelMsgBySeqsInOneDoc(ctx, docID, seqs) + if err != nil { + return + } + lock.Lock() + totalUnExistSeqs = append(totalUnExistSeqs, unExistSeqList...) + lock.Unlock() + }(k, v) + } + return totalUnExistSeqs, nil +} + +func (db *commonMsgDatabase) DelMsgBySeqsInOneDoc(ctx context.Context, docID string, seqs []int64) (unExistSeqs []int64, err error) { + seqMsgs, indexes, unExistSeqs, err := db.GetMsgAndIndexBySeqsInOneDoc(ctx, docID, seqs) + if err != nil { + return nil, err + } + for i, v := range seqMsgs { + if err = db.msgDocDatabase.UpdateMsgStatusByIndexInOneDoc(ctx, docID, v, indexes[i], constant.MsgDeleted); err != nil { + return nil, err + } + } + return unExistSeqs, nil +} + +func (db *commonMsgDatabase) GetMsgAndIndexBySeqsInOneDoc(ctx context.Context, docID string, seqs []int64) (seqMsgs []*sdkws.MsgData, indexes []int, unExistSeqs []int64, err error) { + doc, err := db.msgDocDatabase.FindOneByDocID(ctx, docID) + if err != nil { + return nil, nil, nil, err + } + singleCount := 0 + var hasSeqList []int64 + for i := 0; i < len(doc.Msg); i++ { + msgPb, err := db.unmarshalMsg(&doc.Msg[i]) + if err != nil { + return nil, nil, nil, err + } + if utils.Contain(msgPb.Seq, seqs...) { + indexes = append(indexes, i) + seqMsgs = append(seqMsgs, msgPb) + hasSeqList = append(hasSeqList, msgPb.Seq) + singleCount++ + if singleCount == len(seqs) { + break + } + } + } + for _, i := range seqs { + if utils.Contain(i, hasSeqList...) { + continue + } + unExistSeqs = append(unExistSeqs, i) + } + return seqMsgs, indexes, unExistSeqs, nil +} + +func (db *commonMsgDatabase) GetNewestMsg(ctx context.Context, conversationID string) (msgPb *sdkws.MsgData, err error) { + msgInfo, err := db.msgDocDatabase.GetNewestMsg(ctx, conversationID) + if err != nil { + return nil, err + } + return db.unmarshalMsg(msgInfo) +} + +func (db *commonMsgDatabase) GetOldestMsg(ctx context.Context, conversationID string) (msgPb *sdkws.MsgData, err error) { + msgInfo, err := db.msgDocDatabase.GetOldestMsg(ctx, conversationID) + if err != nil { + return nil, err + } + return db.unmarshalMsg(msgInfo) +} + +func (db *commonMsgDatabase) unmarshalMsg(msgInfo *unRelationTb.MsgInfoModel) (msgPb *sdkws.MsgData, err error) { + msgPb = &sdkws.MsgData{} + err = proto.Unmarshal(msgInfo.Msg, msgPb) + if err != nil { + return nil, utils.Wrap(err, "") + } + return msgPb, nil +} + +func (db *commonMsgDatabase) getMsgBySeqs(ctx context.Context, conversationID string, seqs []int64) (seqMsgs []*sdkws.MsgData, err error) { + var hasSeqs []int64 + singleCount := 0 + m := db.msg.GetDocIDSeqsMap(conversationID, seqs) + for docID, value := range m { + doc, err := db.msgDocDatabase.FindOneByDocID(ctx, docID) + if err != nil { + log.ZError(ctx, "get message from mongo exception", err, "docID", docID) + continue + } + singleCount = 0 + for i := 0; i < len(doc.Msg); i++ { + msgPb, err := db.unmarshalMsg(&doc.Msg[i]) + if err != nil { + log.ZError(ctx, "unmarshal message exception", err, "docID", docID, "msg", &doc.Msg[i]) + return nil, err + } + if utils.Contain(msgPb.Seq, value...) { + seqMsgs = append(seqMsgs, msgPb) + hasSeqs = append(hasSeqs, msgPb.Seq) + singleCount++ + if singleCount == len(value) { + break + } + } + } + } + if len(hasSeqs) != len(seqs) { + var diff []int64 + var exceptionMsg []*sdkws.MsgData + diff = utils.Difference(hasSeqs, seqs) + exceptionMsg = db.msg.GenExceptionSuperGroupMessageBySeqs(diff, conversationID) + seqMsgs = append(seqMsgs, exceptionMsg...) + } + return seqMsgs, nil +} + +func (db *commonMsgDatabase) refetchDelSeqsMsgs(ctx context.Context, conversationID string, delNums, rangeBegin, begin int64) (seqMsgs []*sdkws.MsgData, err error) { + var reFetchSeqs []int64 + if delNums > 0 { + newBeginSeq := rangeBegin - delNums + if newBeginSeq >= begin { + newEndSeq := rangeBegin - 1 + for i := newBeginSeq; i <= newEndSeq; i++ { + reFetchSeqs = append(reFetchSeqs, i) + } + } + } + if len(reFetchSeqs) == 0 { + return + } + if len(reFetchSeqs) > 0 { + m := db.msg.GetDocIDSeqsMap(conversationID, reFetchSeqs) + for docID, seq := range m { + msgs, _, err := db.findMsgBySeq(ctx, docID, seq) + if err != nil { + return nil, err + } + for _, msg := range msgs { + if msg.Status != constant.MsgDeleted { + seqMsgs = append(seqMsgs, msg) + } + } + } + } + if len(seqMsgs) < int(delNums) { + seqMsgs2, err := db.refetchDelSeqsMsgs(ctx, conversationID, delNums-int64(len(seqMsgs)), rangeBegin-1, begin) + if err != nil { + return seqMsgs, err + } + seqMsgs = append(seqMsgs, seqMsgs2...) + } + return seqMsgs, nil +} + +func (db *commonMsgDatabase) findMsgBySeq(ctx context.Context, docID string, seqs []int64) (seqMsgs []*sdkws.MsgData, unExistSeqs []int64, err error) { + beginSeq, endSeq := db.msg.GetSeqsBeginEnd(seqs) + msgs, _, err := db.msgDocDatabase.GetMsgBySeqIndexIn1Doc(ctx, docID, beginSeq, endSeq) + if err != nil { + return nil, nil, err + } + for _, seq := range seqs { + for i, msg := range msgs { + if seq == msg.Seq { + seqMsgs = append(seqMsgs, msg) + continue + } + if i == len(msgs)-1 { + unExistSeqs = append(unExistSeqs, seq) + } + } + } + msgs, _, unExistSeqs, err = db.GetMsgAndIndexBySeqsInOneDoc(ctx, docID, seqs) + if err != nil { + return nil, nil, err + } + seqMsgs = append(seqMsgs, msgs...) + return seqMsgs, unExistSeqs, nil +} + +func (db *commonMsgDatabase) getMsgBySeqsRange(ctx context.Context, conversationID string, allSeqs []int64, begin, end, num int64) (seqMsgs []*sdkws.MsgData, err error) { + log.ZDebug(ctx, "getMsgBySeqsRange", "conversationID", conversationID, "allSeqs", allSeqs, "begin", begin, "end", end, "num", num) + m := db.msg.GetDocIDSeqsMap(conversationID, allSeqs) + var totalNotExistSeqs []int64 + // mongo index + for docID, seqs := range m { + msgs, notExistSeqs, err := db.findMsgBySeq(ctx, docID, seqs) + if err != nil { + return nil, err + } + log.ZDebug(ctx, "getMsgBySeqsRange", "docID", docID, "seqs", seqs, "unExistSeqs", notExistSeqs, "msgs", msgs) + seqMsgs = append(seqMsgs, msgs...) + totalNotExistSeqs = append(totalNotExistSeqs, notExistSeqs...) + } + log.ZDebug(ctx, "getMsgBySeqsRange", "totalNotExistSeqs", totalNotExistSeqs) + // find by next doc + if len(totalNotExistSeqs) > 0 { + m = db.msg.GetDocIDSeqsMap(conversationID, totalNotExistSeqs) + for docID, seqs := range m { + docID = db.msg.ToNextDoc(docID) + msgs, _, unExistSeqs, err := db.GetMsgAndIndexBySeqsInOneDoc(ctx, docID, seqs) + if err != nil { + log.ZError(ctx, "get message from mongo exception", err, "docID", docID, "seqs", seqs) + continue + } + seqMsgs = append(seqMsgs, msgs...) + if len(unExistSeqs) > 0 { + log.ZWarn(ctx, "some seqs lost in mongo", err, "docID", docID, "seqs", seqs, "unExistSeqs", unExistSeqs) + } + } + } + var delSeqs []int64 + for _, msg := range seqMsgs { + if msg.Status == constant.MsgDeleted { + delSeqs = append(delSeqs, msg.Seq) + } + } + if len(delSeqs) > 0 { + msgs, err := db.refetchDelSeqsMsgs(ctx, conversationID, int64(len(delSeqs)), allSeqs[0], begin) + if err != nil { + log.ZWarn(ctx, "refetchDelSeqsMsgs", err, "delSeqs", delSeqs, "begin", begin) + } + seqMsgs = append(seqMsgs, msgs...) + } + // sort by seq + if len(totalNotExistSeqs) > 0 || len(delSeqs) > 0 { + sort.Sort(utils.MsgBySeq(seqMsgs)) + } + // missSeqs为依然缺失的 + return seqMsgs, nil +} + +func (db *commonMsgDatabase) GetMsgBySeqsRange(ctx context.Context, conversationID string, begin, end, num int64) (seqMsg []*sdkws.MsgData, err error) { + var seqs []int64 + for i := end; i > end-num; i-- { + if i >= begin { + seqs = append(seqs, i) + } else { + break + } + } + successMsgs, failedSeqs, err := db.cache.GetMessagesBySeq(ctx, conversationID, seqs) + if err != nil { + if err != redis.Nil { + prome.Add(prome.MsgPullFromRedisFailedCounter, len(failedSeqs)) + log.ZError(ctx, "get message from redis exception", err, conversationID, seqs) + } + } + // get from cache or db + prome.Add(prome.MsgPullFromRedisSuccessCounter, len(successMsgs)) + if len(failedSeqs) > 0 { + mongoMsgs, err := db.getMsgBySeqsRange(ctx, conversationID, failedSeqs, begin, end, num-int64(len(successMsgs))) + if err != nil { + prome.Add(prome.MsgPullFromMongoFailedCounter, len(failedSeqs)) + return nil, err + } + prome.Add(prome.MsgPullFromMongoSuccessCounter, len(mongoMsgs)) + successMsgs = append(successMsgs, mongoMsgs...) + } + return successMsgs, nil +} + +func (db *commonMsgDatabase) GetMsgBySeqs(ctx context.Context, conversationID string, seqs []int64) (successMsgs []*sdkws.MsgData, err error) { + successMsgs, failedSeqs, err := db.cache.GetMessagesBySeq(ctx, conversationID, seqs) + if err != nil { + if err != redis.Nil { + prome.Add(prome.MsgPullFromRedisFailedCounter, len(failedSeqs)) + log.ZError(ctx, "get message from redis exception", err, "failedSeqs", failedSeqs, "conversationID", conversationID) + } + } + prome.Add(prome.MsgPullFromRedisSuccessCounter, len(successMsgs)) + if len(failedSeqs) > 0 { + mongoMsgs, err := db.getMsgBySeqs(ctx, conversationID, seqs) + if err != nil { + prome.Add(prome.MsgPullFromMongoFailedCounter, len(failedSeqs)) + return nil, err + } + prome.Add(prome.MsgPullFromMongoSuccessCounter, len(mongoMsgs)) + successMsgs = append(successMsgs, mongoMsgs...) + } + return successMsgs, nil +} + +func (db *commonMsgDatabase) DeleteConversationMsgsAndSetMinSeq(ctx context.Context, conversationID string, remainTime int64) error { + var delStruct delMsgRecursionStruct + minSeq, err := db.deleteMsgRecursion(ctx, conversationID, unRelationTb.OldestList, &delStruct, remainTime) + if err != nil { + return err + } + if minSeq == 0 { + return nil + } + if remainTime == 0 { + err = db.cache.CleanUpOneConversationAllMsg(ctx, conversationID) + if err != nil { + log.ZWarn(ctx, "CleanUpOneUserAllMsg", err, "conversationID", conversationID) + } + } + return db.cache.SetMinSeq(ctx, conversationID, minSeq) +} + +// this is struct for recursion +type delMsgRecursionStruct struct { + minSeq int64 + delDocIDs []string +} + +func (d *delMsgRecursionStruct) getSetMinSeq() int64 { + return d.minSeq +} + +// index 0....19(del) 20...69 +// seq 70 +// set minSeq 21 +// recursion 删除list并且返回设置的最小seq +func (db *commonMsgDatabase) deleteMsgRecursion(ctx context.Context, conversationID string, index int64, delStruct *delMsgRecursionStruct, remainTime int64) (int64, error) { + // find from oldest list + msgs, err := db.msgDocDatabase.GetMsgsByIndex(ctx, conversationID, index) + if err != nil || msgs.DocID == "" { + if err != nil { + if err == unrelation.ErrMsgListNotExist { + log.ZDebug(ctx, "deleteMsgRecursion ErrMsgListNotExist", "conversationID", conversationID, "index:", index) + } else { + log.ZError(ctx, "deleteMsgRecursion GetUserMsgListByIndex failed", err, "conversationID", conversationID, "index", index) + } + } + // 获取报错,或者获取不到了,物理删除并且返回seq delMongoMsgsPhysical(delStruct.delDocIDList), 结束递归 + err = db.msgDocDatabase.Delete(ctx, delStruct.delDocIDs) + if err != nil { + return 0, err + } + return delStruct.getSetMinSeq() + 1, nil + } + log.ZDebug(ctx, "conversationID", conversationID, "index:", index, "docID", msgs.DocID, "len", len(msgs.Msg)) + if int64(len(msgs.Msg)) > db.msg.GetSingleGocMsgNum() { + log.ZWarn(ctx, "msgs too large", nil, "lenth", len(msgs.Msg), "docID:", msgs.DocID) + } + if msgs.Msg[len(msgs.Msg)-1].SendTime+(remainTime*1000) < utils.GetCurrentTimestampByMill() && msgs.IsFull() { + delStruct.delDocIDs = append(delStruct.delDocIDs, msgs.DocID) + lastMsgPb := &sdkws.MsgData{} + err = proto.Unmarshal(msgs.Msg[len(msgs.Msg)-1].Msg, lastMsgPb) + if err != nil { + log.ZError(ctx, "proto.Unmarshal failed", err, "index", len(msgs.Msg)-1, "docID", msgs.DocID) + return 0, utils.Wrap(err, "proto.Unmarshal failed") + } + delStruct.minSeq = lastMsgPb.Seq + } else { + var hasMarkDelFlag bool + for i, msg := range msgs.Msg { + msgPb := &sdkws.MsgData{} + err = proto.Unmarshal(msg.Msg, msgPb) + if err != nil { + log.ZError(ctx, "proto.Unmarshal failed", err, "index", i, "docID", msgs.DocID) + return 0, utils.Wrap(err, "proto.Unmarshal failed") + } + if utils.GetCurrentTimestampByMill() > msg.SendTime+(remainTime*1000) { + msgPb.Status = constant.MsgDeleted + bytes, _ := proto.Marshal(msgPb) + msg.Msg = bytes + msg.SendTime = 0 + hasMarkDelFlag = true + } else { + // 到本条消息不需要删除, minSeq置为这条消息的seq + if err := db.msgDocDatabase.Delete(ctx, delStruct.delDocIDs); err != nil { + return 0, err + } + if hasMarkDelFlag { + if err := db.msgDocDatabase.UpdateOneDoc(ctx, msgs); err != nil { + return delStruct.getSetMinSeq(), utils.Wrap(err, "") + } + } + return msgPb.Seq, nil + } + } + } + // 继续递归 index+1 + seq, err := db.deleteMsgRecursion(ctx, conversationID, index+1, delStruct, remainTime) + return seq, err +} + +func (db *commonMsgDatabase) CleanUpUserConversationsMsgs(ctx context.Context, user string, conversationIDs []string) { + for _, conversationID := range conversationIDs { + maxSeq, err := db.cache.GetMaxSeq(ctx, conversationID) + if err != nil { + if err == redis.Nil { + log.ZInfo(ctx, "max seq is nil", "conversationID", conversationID) + } else { + log.ZError(ctx, "get max seq failed", err, "conversationID", conversationID) + } + continue + } + if err := db.cache.SetMinSeq(ctx, conversationID, maxSeq+1); err != nil { + log.ZError(ctx, "set min seq failed", err, "conversationID", conversationID, "minSeq", maxSeq+1) + } + } +} + +func (db *commonMsgDatabase) SetMaxSeq(ctx context.Context, conversationID string, maxSeq int64) error { + return db.cache.SetMaxSeq(ctx, conversationID, maxSeq) +} +func (db *commonMsgDatabase) GetMaxSeqs(ctx context.Context, conversationIDs []string) (map[string]int64, error) { + return db.cache.GetMaxSeqs(ctx, conversationIDs) +} +func (db *commonMsgDatabase) GetMaxSeq(ctx context.Context, conversationID string) (int64, error) { + return db.cache.GetMaxSeq(ctx, conversationID) +} +func (db *commonMsgDatabase) SetMinSeq(ctx context.Context, conversationID string, minSeq int64) error { + return db.cache.SetMinSeq(ctx, conversationID, minSeq) +} +func (db *commonMsgDatabase) GetMinSeqs(ctx context.Context, conversationIDs []string) (map[string]int64, error) { + return db.cache.GetMinSeqs(ctx, conversationIDs) +} +func (db *commonMsgDatabase) GetMinSeq(ctx context.Context, conversationID string) (int64, error) { + return db.cache.GetMinSeq(ctx, conversationID) +} +func (db *commonMsgDatabase) GetConversationUserMinSeq(ctx context.Context, conversationID string, userID string) (int64, error) { + return db.cache.GetConversationUserMinSeq(ctx, conversationID, userID) +} +func (db *commonMsgDatabase) GetConversationUserMinSeqs(ctx context.Context, conversationID string, userIDs []string) (map[string]int64, error) { + return db.cache.GetConversationUserMinSeqs(ctx, conversationID, userIDs) +} +func (db *commonMsgDatabase) SetConversationUserMinSeq(ctx context.Context, conversationID string, userID string, minSeq int64) error { + return db.cache.SetConversationUserMinSeq(ctx, conversationID, userID, minSeq) +} +func (db *commonMsgDatabase) SetConversationUserMinSeqs(ctx context.Context, conversationID string, seqs map[string]int64) (err error) { + return db.cache.SetConversationUserMinSeqs(ctx, conversationID, seqs) +} + +func (db *commonMsgDatabase) SetSendMsgStatus(ctx context.Context, id string, status int32) error { + return db.cache.SetSendMsgStatus(ctx, id, status) +} + +func (db *commonMsgDatabase) GetSendMsgStatus(ctx context.Context, id string) (int32, error) { + return db.cache.GetSendMsgStatus(ctx, id) +} + +func (db *commonMsgDatabase) GetConversationMinMaxSeqInMongoAndCache(ctx context.Context, conversationID string) (minSeqMongo, maxSeqMongo, minSeqCache, maxSeqCache int64, err error) { + minSeqMongo, maxSeqMongo, err = db.GetMinMaxSeqMongo(ctx, conversationID) + if err != nil { + return + } + // from cache + minSeqCache, err = db.cache.GetMinSeq(ctx, conversationID) + if err != nil { + return + } + maxSeqCache, err = db.cache.GetMaxSeq(ctx, conversationID) + if err != nil { + return + } + return +} + +func (db *commonMsgDatabase) GetMinMaxSeqMongo(ctx context.Context, conversationID string) (minSeqMongo, maxSeqMongo int64, err error) { + oldestMsgMongo, err := db.msgDocDatabase.GetOldestMsg(ctx, conversationID) + if err != nil { + return + } + msgPb, err := db.unmarshalMsg(oldestMsgMongo) + if err != nil { + return + } + minSeqMongo = msgPb.Seq + newestMsgMongo, err := db.msgDocDatabase.GetNewestMsg(ctx, conversationID) + if err != nil { + return + } + msgPb, err = db.unmarshalMsg(newestMsgMongo) + if err != nil { + return + } + maxSeqMongo = msgPb.Seq + return +} + +func (db *commonMsgDatabase) JudgeMessageReactionExist(ctx context.Context, clientMsgID string, sessionType int32) (bool, error) { + return db.cache.JudgeMessageReactionExist(ctx, clientMsgID, sessionType) +} + +func (db *commonMsgDatabase) SetMessageTypeKeyValue(ctx context.Context, clientMsgID string, sessionType int32, typeKey, value string) error { + return db.cache.SetMessageTypeKeyValue(ctx, clientMsgID, sessionType, typeKey, value) +} + +func (db *commonMsgDatabase) SetMessageReactionExpire(ctx context.Context, clientMsgID string, sessionType int32, expiration time.Duration) (bool, error) { + return db.cache.SetMessageReactionExpire(ctx, clientMsgID, sessionType, expiration) +} + +func (db *commonMsgDatabase) GetMessageTypeKeyValue(ctx context.Context, clientMsgID string, sessionType int32, typeKey string) (string, error) { + return db.cache.GetMessageTypeKeyValue(ctx, clientMsgID, sessionType, typeKey) +} + +func (db *commonMsgDatabase) GetOneMessageAllReactionList(ctx context.Context, clientMsgID string, sessionType int32) (map[string]string, error) { + return db.cache.GetOneMessageAllReactionList(ctx, clientMsgID, sessionType) +} + +func (db *commonMsgDatabase) DeleteOneMessageKey(ctx context.Context, clientMsgID string, sessionType int32, subKey string) error { + return db.cache.DeleteOneMessageKey(ctx, clientMsgID, sessionType, subKey) +} + +func (db *commonMsgDatabase) InsertOrUpdateReactionExtendMsgSet(ctx context.Context, conversationID string, sessionType int32, clientMsgID string, msgFirstModifyTime int64, reactionExtensions map[string]*sdkws.KeyValue) error { + return db.extendMsgDatabase.InsertOrUpdateReactionExtendMsgSet(ctx, conversationID, sessionType, clientMsgID, msgFirstModifyTime, db.extendMsgSetModel.Pb2Model(reactionExtensions)) +} + +func (db *commonMsgDatabase) GetExtendMsg(ctx context.Context, conversationID string, sessionType int32, clientMsgID string, maxMsgUpdateTime int64) (*pbMsg.ExtendMsg, error) { + extendMsgSet, err := db.extendMsgDatabase.GetExtendMsgSet(ctx, conversationID, sessionType, maxMsgUpdateTime) + if err != nil { + return nil, err + } + extendMsg, ok := extendMsgSet.ExtendMsgs[clientMsgID] + if !ok { + return nil, errs.ErrRecordNotFound.Wrap(fmt.Sprintf("cant find client msg id: %s", clientMsgID)) + } + reactionExtensionList := make(map[string]*pbMsg.KeyValueResp) + for key, model := range extendMsg.ReactionExtensionList { + reactionExtensionList[key] = &pbMsg.KeyValueResp{ + KeyValue: &sdkws.KeyValue{ + TypeKey: model.TypeKey, + Value: model.Value, + LatestUpdateTime: model.LatestUpdateTime, + }, + } + } + return &pbMsg.ExtendMsg{ + ReactionExtensions: reactionExtensionList, + ClientMsgID: extendMsg.ClientMsgID, + MsgFirstModifyTime: extendMsg.MsgFirstModifyTime, + AttachedInfo: extendMsg.AttachedInfo, + Ex: extendMsg.Ex, + }, nil +} + +func (db *commonMsgDatabase) DeleteReactionExtendMsgSet(ctx context.Context, conversationID string, sessionType int32, clientMsgID string, msgFirstModifyTime int64, reactionExtensions map[string]*sdkws.KeyValue) error { + return db.extendMsgDatabase.DeleteReactionExtendMsgSet(ctx, conversationID, sessionType, clientMsgID, msgFirstModifyTime, db.extendMsgSetModel.Pb2Model(reactionExtensions)) } diff --git a/pkg/common/db/controller/extend_msg.go b/pkg/common/db/controller/extend_msg.go index b342aa152..9717bd933 100644 --- a/pkg/common/db/controller/extend_msg.go +++ b/pkg/common/db/controller/extend_msg.go @@ -46,7 +46,6 @@ func (e *extendMsgDatabase) InsertExtendMsg(ctx context.Context, conversationID } func (e *extendMsgDatabase) InsertOrUpdateReactionExtendMsgSet(ctx context.Context, conversationID string, sessionType int32, clientMsgID string, msgFirstModifyTime int64, reactionExtensionList map[string]*unRelationTb.KeyValueModel) error { - e.cache.DelExtendMsg(clientMsgID).ExecDel(ctx) return e.database.InsertOrUpdateReactionExtendMsgSet(ctx, conversationID, sessionType, clientMsgID, msgFirstModifyTime, reactionExtensionList) } diff --git a/pkg/common/db/controller/msg.go b/pkg/common/db/controller/msg.go deleted file mode 100644 index 29a83d389..000000000 --- a/pkg/common/db/controller/msg.go +++ /dev/null @@ -1,827 +0,0 @@ -package controller - -import ( - "fmt" - "sort" - "sync" - "time" - - "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/db/cache" - unRelationTb "github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/table/unrelation" - "github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/unrelation" - "github.com/OpenIMSDK/Open-IM-Server/pkg/common/kafka" - "github.com/OpenIMSDK/Open-IM-Server/pkg/common/log" - "github.com/OpenIMSDK/Open-IM-Server/pkg/common/prome" - "github.com/OpenIMSDK/Open-IM-Server/pkg/errs" - "github.com/gogo/protobuf/sortkeys" - - "context" - "errors" - - pbMsg "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" - "github.com/go-redis/redis/v8" - "go.mongodb.org/mongo-driver/mongo" - - "github.com/golang/protobuf/proto" -) - -type MsgDatabase interface { - // 批量插入消息 - BatchInsertChat2DB(ctx context.Context, conversationID string, msgList []*sdkws.MsgData, currentMaxSeq int64) error - // 刪除redis中消息缓存 - DeleteMessageFromCache(ctx context.Context, conversationID string, msgList []*sdkws.MsgData) error - // incrSeq然后批量插入缓存 - BatchInsertChat2Cache(ctx context.Context, conversationID string, msgList []*sdkws.MsgData, currentMaxSeq int64) (int64, error) - // incrSeq通知seq然后批量插入缓存 - NotificationBatchInsertChat2Cache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) (int64, error) - // 删除消息 返回不存在的seqList - DelMsgBySeqs(ctx context.Context, conversationID string, seqs []int64) (totalUnExistSeqs []int64, err error) - // 通过seqList获取mongo中写扩散消息 - GetMsgBySeqsRange(ctx context.Context, conversationID string, begin, end, num int64) (seqMsg []*sdkws.MsgData, err error) - // 通过seqList获取大群在 mongo里面的消息 - GetMsgBySeqs(ctx context.Context, conversationID string, seqs []int64) (seqMsg []*sdkws.MsgData, err error) - // 删除用户所有消息/redis/mongo然后重置seq - CleanUpConversationMsgs(ctx context.Context, conversationID string) error - // 删除大群消息重置群成员最小群seq, remainTime为消息保留的时间单位秒,超时消息删除, 传0删除所有消息(此方法不删除 redis cache) - - // DeleteUserSuperGroupMsgsAndSetMinSeq(ctx context.Context, groupID string, userIDs []string, remainTime int64) error - - // 删除会话消息重置最小seq, remainTime为消息保留的时间单位秒,超时消息删除, 传0删除所有消息(此方法不删除redis cache) - DeleteConversationMsgsAndSetMinSeq(ctx context.Context, conversationID string, remainTime int64) error - - // 获取会话 seq mongo和redis - GetConversationMinMaxSeqInMongoAndCache(ctx context.Context, conversationID string) (minSeqMongo, maxSeqMongo, minSeqCache, maxSeqCache int64, err error) - - // msg modify - JudgeMessageReactionExist(ctx context.Context, clientMsgID string, sessionType int32) (bool, error) - SetMessageTypeKeyValue(ctx context.Context, clientMsgID string, sessionType int32, typeKey, value string) error - SetMessageReactionExpire(ctx context.Context, clientMsgID string, sessionType int32, expiration time.Duration) (bool, error) - GetExtendMsg(ctx context.Context, conversationID string, sessionType int32, clientMsgID string, maxMsgUpdateTime int64) (*pbMsg.ExtendMsg, error) - InsertOrUpdateReactionExtendMsgSet(ctx context.Context, conversationID string, sessionType int32, clientMsgID string, msgFirstModifyTime int64, reactionExtensionList map[string]*sdkws.KeyValue) error - GetMessageTypeKeyValue(ctx context.Context, clientMsgID string, sessionType int32, typeKey string) (string, error) - GetOneMessageAllReactionList(ctx context.Context, clientMsgID string, sessionType int32) (map[string]string, error) - DeleteOneMessageKey(ctx context.Context, clientMsgID string, sessionType int32, subKey string) error - DeleteReactionExtendMsgSet(ctx context.Context, conversationID string, sessionType int32, clientMsgID string, msgFirstModifyTime int64, reactionExtensionList map[string]*sdkws.KeyValue) error - // msg send status - SetSendMsgStatus(ctx context.Context, id string, status int32) error - GetSendMsgStatus(ctx context.Context, id string) (int32, error) - - SetMaxSeq(ctx context.Context, conversationID string, maxSeq int64) error - GetMaxSeqs(ctx context.Context, conversationIDs []string) (map[string]int64, error) - GetMaxSeq(ctx context.Context, conversationID string) (int64, error) - SetMinSeq(ctx context.Context, conversationID string, minSeq int64) error - GetMinSeqs(ctx context.Context, conversationIDs []string) (map[string]int64, error) - GetMinSeq(ctx context.Context, conversationID string) (int64, error) - GetConversationUserMinSeq(ctx context.Context, conversationID string, userID string) (int64, error) - GetConversationUserMinSeqs(ctx context.Context, conversationID string, userIDs []string) (map[string]int64, error) - SetConversationUserMinSeq(ctx context.Context, conversationID string, userID string, minSeq int64) error - SetConversationUserMinSeqs(ctx context.Context, conversationID string, seqs map[string]int64) (err error) - - // to mq - MsgToMQ(ctx context.Context, key string, msg2mq *sdkws.MsgData) error - MsgToModifyMQ(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) error - MsgToPushMQ(ctx context.Context, conversationID string, msg2mq *sdkws.MsgData) (int32, int64, error) - MsgToMongoMQ(ctx context.Context, conversationID string, msgs []*sdkws.MsgData, lastSeq int64) error -} - -func NewMsgDatabase(msgDocModel unRelationTb.MsgDocModelInterface, cacheModel cache.MsgModel) MsgDatabase { - return &msgDatabase{ - msgDocDatabase: msgDocModel, - cache: cacheModel, - producer: kafka.NewKafkaProducer(config.Config.Kafka.Ws2mschat.Addr, config.Config.Kafka.Ws2mschat.Topic), - producerToMongo: kafka.NewKafkaProducer(config.Config.Kafka.MsgToMongo.Addr, config.Config.Kafka.MsgToMongo.Topic), - producerToPush: kafka.NewKafkaProducer(config.Config.Kafka.Ms2pschat.Addr, config.Config.Kafka.Ms2pschat.Topic), - producerToModify: kafka.NewKafkaProducer(config.Config.Kafka.MsgToModify.Addr, config.Config.Kafka.MsgToModify.Topic), - } -} - -func InitMsgDatabase(rdb redis.UniversalClient, database *mongo.Database) MsgDatabase { - cacheModel := cache.NewMsgCacheModel(rdb) - msgDocModel := unrelation.NewMsgMongoDriver(database) - msgDatabase := NewMsgDatabase(msgDocModel, cacheModel) - return msgDatabase -} - -type msgDatabase struct { - msgDocDatabase unRelationTb.MsgDocModelInterface - extendMsgDatabase unRelationTb.ExtendMsgSetModelInterface - cache cache.MsgModel - producer *kafka.Producer - producerToMongo *kafka.Producer - producerToModify *kafka.Producer - producerToPush *kafka.Producer - // model - msg unRelationTb.MsgDocModel - extendMsgSetModel unRelationTb.ExtendMsgSetModel -} - -func (db *msgDatabase) JudgeMessageReactionExist(ctx context.Context, clientMsgID string, sessionType int32) (bool, error) { - return db.cache.JudgeMessageReactionExist(ctx, clientMsgID, sessionType) -} - -func (db *msgDatabase) SetMessageTypeKeyValue(ctx context.Context, clientMsgID string, sessionType int32, typeKey, value string) error { - return db.cache.SetMessageTypeKeyValue(ctx, clientMsgID, sessionType, typeKey, value) -} - -func (db *msgDatabase) SetMessageReactionExpire(ctx context.Context, clientMsgID string, sessionType int32, expiration time.Duration) (bool, error) { - return db.cache.SetMessageReactionExpire(ctx, clientMsgID, sessionType, expiration) -} - -func (db *msgDatabase) GetMessageTypeKeyValue(ctx context.Context, clientMsgID string, sessionType int32, typeKey string) (string, error) { - return db.cache.GetMessageTypeKeyValue(ctx, clientMsgID, sessionType, typeKey) -} - -func (db *msgDatabase) GetOneMessageAllReactionList(ctx context.Context, clientMsgID string, sessionType int32) (map[string]string, error) { - return db.cache.GetOneMessageAllReactionList(ctx, clientMsgID, sessionType) -} - -func (db *msgDatabase) DeleteOneMessageKey(ctx context.Context, clientMsgID string, sessionType int32, subKey string) error { - return db.cache.DeleteOneMessageKey(ctx, clientMsgID, sessionType, subKey) -} - -func (db *msgDatabase) InsertOrUpdateReactionExtendMsgSet(ctx context.Context, conversationID string, sessionType int32, clientMsgID string, msgFirstModifyTime int64, reactionExtensions map[string]*sdkws.KeyValue) error { - return db.extendMsgDatabase.InsertOrUpdateReactionExtendMsgSet(ctx, conversationID, sessionType, clientMsgID, msgFirstModifyTime, db.extendMsgSetModel.Pb2Model(reactionExtensions)) -} - -func (db *msgDatabase) GetExtendMsg(ctx context.Context, conversationID string, sessionType int32, clientMsgID string, maxMsgUpdateTime int64) (*pbMsg.ExtendMsg, error) { - extendMsgSet, err := db.extendMsgDatabase.GetExtendMsgSet(ctx, conversationID, sessionType, maxMsgUpdateTime) - if err != nil { - return nil, err - } - extendMsg, ok := extendMsgSet.ExtendMsgs[clientMsgID] - if !ok { - return nil, errs.ErrRecordNotFound.Wrap(fmt.Sprintf("cant find client msg id: %s", clientMsgID)) - } - reactionExtensionList := make(map[string]*pbMsg.KeyValueResp) - for key, model := range extendMsg.ReactionExtensionList { - reactionExtensionList[key] = &pbMsg.KeyValueResp{ - KeyValue: &sdkws.KeyValue{ - TypeKey: model.TypeKey, - Value: model.Value, - LatestUpdateTime: model.LatestUpdateTime, - }, - } - } - return &pbMsg.ExtendMsg{ - ReactionExtensions: reactionExtensionList, - ClientMsgID: extendMsg.ClientMsgID, - MsgFirstModifyTime: extendMsg.MsgFirstModifyTime, - AttachedInfo: extendMsg.AttachedInfo, - Ex: extendMsg.Ex, - }, nil -} - -func (db *msgDatabase) DeleteReactionExtendMsgSet(ctx context.Context, conversationID string, sessionType int32, clientMsgID string, msgFirstModifyTime int64, reactionExtensions map[string]*sdkws.KeyValue) error { - return db.extendMsgDatabase.DeleteReactionExtendMsgSet(ctx, conversationID, sessionType, clientMsgID, msgFirstModifyTime, db.extendMsgSetModel.Pb2Model(reactionExtensions)) -} - -func (db *msgDatabase) SetSendMsgStatus(ctx context.Context, id string, status int32) error { - return db.cache.SetSendMsgStatus(ctx, id, status) -} - -func (db *msgDatabase) GetSendMsgStatus(ctx context.Context, id string) (int32, error) { - return db.cache.GetSendMsgStatus(ctx, id) -} - -func (db *msgDatabase) MsgToMQ(ctx context.Context, key string, msg2mq *sdkws.MsgData) error { - _, _, err := db.producer.SendMessage(ctx, key, msg2mq) - return err -} - -func (db *msgDatabase) MsgToModifyMQ(ctx context.Context, conversationID string, messages []*sdkws.MsgData) error { - if len(messages) > 0 { - _, _, err := db.producerToModify.SendMessage(ctx, conversationID, &pbMsg.MsgDataToModifyByMQ{ConversationID: conversationID, Messages: messages}) - return err - } - return nil -} - -func (db *msgDatabase) MsgToPushMQ(ctx context.Context, conversationID string, msg2mq *sdkws.MsgData) (int32, int64, error) { - mqPushMsg := pbMsg.PushMsgDataToMQ{MsgData: msg2mq, ConversationID: conversationID} - partition, offset, err := db.producerToPush.SendMessage(ctx, conversationID, &mqPushMsg) - if err != nil { - log.ZError(ctx, "MsgToPushMQ", err, "key", conversationID, "msg2mq", msg2mq) - } - return partition, offset, err -} - -func (db *msgDatabase) MsgToMongoMQ(ctx context.Context, conversationID string, messages []*sdkws.MsgData, lastSeq int64) error { - if len(messages) > 0 { - _, _, err := db.producerToModify.SendMessage(ctx, conversationID, &pbMsg.MsgDataToMongoByMQ{LastSeq: lastSeq, ConversationID: conversationID, MsgData: messages}) - return err - } - return nil -} - -func (db *msgDatabase) BatchInsertChat2DB(ctx context.Context, conversationID string, msgList []*sdkws.MsgData, currentMaxSeq int64) error { - if int64(len(msgList)) > db.msg.GetSingleGocMsgNum() { - return errors.New("too large") - } - var remain int64 - blk0 := db.msg.GetSingleGocMsgNum() - 1 - //currentMaxSeq 4998 - if currentMaxSeq < db.msg.GetSingleGocMsgNum() { - remain = blk0 - currentMaxSeq //1 - } else { - excludeBlk0 := currentMaxSeq - blk0 //=1 - //(5000-1)%5000 == 4999 - remain = (db.msg.GetSingleGocMsgNum() - (excludeBlk0 % db.msg.GetSingleGocMsgNum())) % db.msg.GetSingleGocMsgNum() - } - //remain=1 - var insertCounter int64 - msgsToMongo := make([]unRelationTb.MsgInfoModel, 0) - msgsToMongoNext := make([]unRelationTb.MsgInfoModel, 0) - docID := "" - docIDNext := "" - var err error - for _, m := range msgList { - //log.Debug(operationID, "msg node ", m.String(), m.MsgData.ClientMsgID) - currentMaxSeq++ - sMsg := unRelationTb.MsgInfoModel{} - sMsg.SendTime = m.SendTime - m.Seq = currentMaxSeq - if sMsg.Msg, err = proto.Marshal(m); err != nil { - return utils.Wrap(err, "") - } - if insertCounter < remain { - msgsToMongo = append(msgsToMongo, sMsg) - insertCounter++ - docID = db.msg.GetDocID(conversationID, currentMaxSeq) - //log.Debug(operationID, "msgListToMongo ", seqUid, m.MsgData.Seq, m.MsgData.ClientMsgID, insertCounter, remain, "userID: ", userID) - } else { - msgsToMongoNext = append(msgsToMongoNext, sMsg) - docIDNext = db.msg.GetDocID(conversationID, currentMaxSeq) - //log.Debug(operationID, "msgListToMongoNext ", seqUidNext, m.MsgData.Seq, m.MsgData.ClientMsgID, insertCounter, remain, "userID: ", userID) - } - } - - if docID != "" { - //filter := bson.M{"uid": seqUid} - //log.NewDebug(operationID, "filter ", seqUid, "list ", msgListToMongo, "userID: ", userID) - //err := c.FindOneAndUpdate(ctx, filter, bson.M{"$push": bson.M{"msg": bson.M{"$each": msgsToMongo}}}).Err() - err = db.msgDocDatabase.PushMsgsToDoc(ctx, docID, msgsToMongo) - if err != nil { - if err == mongo.ErrNoDocuments { - doc := &unRelationTb.MsgDocModel{} - doc.DocID = docID - doc.Msg = msgsToMongo - if err = db.msgDocDatabase.Create(ctx, doc); err != nil { - prome.Inc(prome.MsgInsertMongoFailedCounter) - //log.NewError(operationID, "InsertOne failed", filter, err.Error(), sChat) - return utils.Wrap(err, "") - } - prome.Inc(prome.MsgInsertMongoSuccessCounter) - } else { - prome.Inc(prome.MsgInsertMongoFailedCounter) - //log.Error(operationID, "FindOneAndUpdate failed ", err.Error(), filter) - return utils.Wrap(err, "") - } - } else { - prome.Inc(prome.MsgInsertMongoSuccessCounter) - } - } - if docIDNext != "" { - nextDoc := &unRelationTb.MsgDocModel{} - nextDoc.DocID = docIDNext - nextDoc.Msg = msgsToMongoNext - //log.NewDebug(operationID, "filter ", seqUidNext, "list ", msgListToMongoNext, "userID: ", userID) - if err = db.msgDocDatabase.Create(ctx, nextDoc); err != nil { - prome.Inc(prome.MsgInsertMongoFailedCounter) - //log.NewError(operationID, "InsertOne failed", filter, err.Error(), sChat) - return utils.Wrap(err, "") - } - prome.Inc(prome.MsgInsertMongoSuccessCounter) - } - return nil -} - -func (db *msgDatabase) DeleteMessageFromCache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) error { - return db.cache.DeleteMessageFromCache(ctx, conversationID, msgs) -} - -func (db *msgDatabase) NotificationBatchInsertChat2Cache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) (int64, error) { - return 0, nil -} - -func (db *msgDatabase) BatchInsertChat2Cache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData, currentMaxSeq int64) (int64, error) { - lenList := len(msgs) - if int64(lenList) > db.msg.GetSingleGocMsgNum() { - return 0, errors.New("too large") - } - if lenList < 1 { - return 0, errors.New("too short as 0") - } - lastMaxSeq := currentMaxSeq - for _, m := range msgs { - currentMaxSeq++ - m.Seq = currentMaxSeq - } - failedNum, err := db.cache.SetMessageToCache(ctx, conversationID, msgs) - if err != nil { - prome.Add(prome.MsgInsertRedisFailedCounter, failedNum) - log.ZError(ctx, "setMessageToCache error", err, "len", len(msgs), "conversationID", conversationID) - } else { - prome.Inc(prome.MsgInsertRedisSuccessCounter) - } - err = db.cache.SetMaxSeq(ctx, conversationID, currentMaxSeq) - if err != nil { - prome.Inc(prome.SeqSetFailedCounter) - } else { - prome.Inc(prome.SeqSetSuccessCounter) - } - return lastMaxSeq, utils.Wrap(err, "") -} - -func (db *msgDatabase) DelMsgBySeqs(ctx context.Context, conversationID string, seqs []int64) (totalUnExistSeqs []int64, err error) { - sortkeys.Int64s(seqs) - docIDSeqsMap := db.msg.GetDocIDSeqsMap(conversationID, seqs) - lock := sync.Mutex{} - var wg sync.WaitGroup - wg.Add(len(docIDSeqsMap)) - for k, v := range docIDSeqsMap { - go func(docID string, seqs []int64) { - defer wg.Done() - unExistSeqList, err := db.DelMsgBySeqsInOneDoc(ctx, docID, seqs) - if err != nil { - return - } - lock.Lock() - totalUnExistSeqs = append(totalUnExistSeqs, unExistSeqList...) - lock.Unlock() - }(k, v) - } - return totalUnExistSeqs, nil -} - -func (db *msgDatabase) DelMsgBySeqsInOneDoc(ctx context.Context, docID string, seqs []int64) (unExistSeqs []int64, err error) { - seqMsgs, indexes, unExistSeqs, err := db.GetMsgAndIndexBySeqsInOneDoc(ctx, docID, seqs) - if err != nil { - return nil, err - } - for i, v := range seqMsgs { - if err = db.msgDocDatabase.UpdateMsgStatusByIndexInOneDoc(ctx, docID, v, indexes[i], constant.MsgDeleted); err != nil { - return nil, err - } - } - return unExistSeqs, nil -} - -func (db *msgDatabase) GetMsgAndIndexBySeqsInOneDoc(ctx context.Context, docID string, seqs []int64) (seqMsgs []*sdkws.MsgData, indexes []int, unExistSeqs []int64, err error) { - doc, err := db.msgDocDatabase.FindOneByDocID(ctx, docID) - if err != nil { - return nil, nil, nil, err - } - singleCount := 0 - var hasSeqList []int64 - for i := 0; i < len(doc.Msg); i++ { - msgPb, err := db.unmarshalMsg(&doc.Msg[i]) - if err != nil { - return nil, nil, nil, err - } - if utils.Contain(msgPb.Seq, seqs...) { - indexes = append(indexes, i) - seqMsgs = append(seqMsgs, msgPb) - hasSeqList = append(hasSeqList, msgPb.Seq) - singleCount++ - if singleCount == len(seqs) { - break - } - } - } - for _, i := range seqs { - if utils.Contain(i, hasSeqList...) { - continue - } - unExistSeqs = append(unExistSeqs, i) - } - return seqMsgs, indexes, unExistSeqs, nil -} - -func (db *msgDatabase) GetNewestMsg(ctx context.Context, conversationID string) (msgPb *sdkws.MsgData, err error) { - msgInfo, err := db.msgDocDatabase.GetNewestMsg(ctx, conversationID) - if err != nil { - return nil, err - } - return db.unmarshalMsg(msgInfo) -} - -func (db *msgDatabase) GetOldestMsg(ctx context.Context, conversationID string) (msgPb *sdkws.MsgData, err error) { - msgInfo, err := db.msgDocDatabase.GetOldestMsg(ctx, conversationID) - if err != nil { - return nil, err - } - return db.unmarshalMsg(msgInfo) -} - -func (db *msgDatabase) unmarshalMsg(msgInfo *unRelationTb.MsgInfoModel) (msgPb *sdkws.MsgData, err error) { - msgPb = &sdkws.MsgData{} - err = proto.Unmarshal(msgInfo.Msg, msgPb) - if err != nil { - return nil, utils.Wrap(err, "") - } - return msgPb, nil -} - -func (db *msgDatabase) getMsgBySeqs(ctx context.Context, conversationID string, seqs []int64) (seqMsgs []*sdkws.MsgData, err error) { - var hasSeqs []int64 - singleCount := 0 - m := db.msg.GetDocIDSeqsMap(conversationID, seqs) - for docID, value := range m { - doc, err := db.msgDocDatabase.FindOneByDocID(ctx, docID) - if err != nil { - log.ZError(ctx, "get message from mongo exception", err, "docID", docID) - continue - } - singleCount = 0 - for i := 0; i < len(doc.Msg); i++ { - msgPb, err := db.unmarshalMsg(&doc.Msg[i]) - if err != nil { - log.ZError(ctx, "unmarshal message exception", err, "docID", docID, "msg", &doc.Msg[i]) - return nil, err - } - if utils.Contain(msgPb.Seq, value...) { - seqMsgs = append(seqMsgs, msgPb) - hasSeqs = append(hasSeqs, msgPb.Seq) - singleCount++ - if singleCount == len(value) { - break - } - } - } - } - if len(hasSeqs) != len(seqs) { - var diff []int64 - var exceptionMsg []*sdkws.MsgData - diff = utils.Difference(hasSeqs, seqs) - exceptionMsg = db.msg.GenExceptionSuperGroupMessageBySeqs(diff, conversationID) - seqMsgs = append(seqMsgs, exceptionMsg...) - } - return seqMsgs, nil -} - -func (db *msgDatabase) refetchDelSeqsMsgs(ctx context.Context, conversationID string, delNums, rangeBegin, begin int64) (seqMsgs []*sdkws.MsgData, err error) { - var reFetchSeqs []int64 - if delNums > 0 { - newBeginSeq := rangeBegin - delNums - if newBeginSeq >= begin { - newEndSeq := rangeBegin - 1 - for i := newBeginSeq; i <= newEndSeq; i++ { - reFetchSeqs = append(reFetchSeqs, i) - } - } - } - if len(reFetchSeqs) == 0 { - return - } - if len(reFetchSeqs) > 0 { - m := db.msg.GetDocIDSeqsMap(conversationID, reFetchSeqs) - for docID, seq := range m { - msgs, _, err := db.findMsgBySeq(ctx, docID, seq) - if err != nil { - return nil, err - } - for _, msg := range msgs { - if msg.Status != constant.MsgDeleted { - seqMsgs = append(seqMsgs, msg) - } - } - } - } - if len(seqMsgs) < int(delNums) { - seqMsgs2, err := db.refetchDelSeqsMsgs(ctx, conversationID, delNums-int64(len(seqMsgs)), rangeBegin-1, begin) - if err != nil { - return seqMsgs, err - } - seqMsgs = append(seqMsgs, seqMsgs2...) - } - return seqMsgs, nil -} - -func (db *msgDatabase) findMsgBySeq(ctx context.Context, docID string, seqs []int64) (seqMsgs []*sdkws.MsgData, unExistSeqs []int64, err error) { - beginSeq, endSeq := db.msg.GetSeqsBeginEnd(seqs) - msgs, _, err := db.msgDocDatabase.GetMsgBySeqIndexIn1Doc(ctx, docID, beginSeq, endSeq) - if err != nil { - return nil, nil, err - } - for _, seq := range seqs { - for i, msg := range msgs { - if seq == msg.Seq { - seqMsgs = append(seqMsgs, msg) - continue - } - if i == len(msgs)-1 { - unExistSeqs = append(unExistSeqs, seq) - } - } - } - msgs, _, unExistSeqs, err = db.GetMsgAndIndexBySeqsInOneDoc(ctx, docID, seqs) - if err != nil { - return nil, nil, err - } - seqMsgs = append(seqMsgs, msgs...) - return seqMsgs, unExistSeqs, nil -} - -func (db *msgDatabase) getMsgBySeqsRange(ctx context.Context, conversationID string, allSeqs []int64, begin, end, num int64) (seqMsgs []*sdkws.MsgData, err error) { - log.ZDebug(ctx, "getMsgBySeqsRange", "conversationID", conversationID, "allSeqs", allSeqs, "begin", begin, "end", end, "num", num) - m := db.msg.GetDocIDSeqsMap(conversationID, allSeqs) - var totalNotExistSeqs []int64 - // mongo index - for docID, seqs := range m { - msgs, notExistSeqs, err := db.findMsgBySeq(ctx, docID, seqs) - if err != nil { - return nil, err - } - log.ZDebug(ctx, "getMsgBySeqsRange", "docID", docID, "seqs", seqs, "unExistSeqs", notExistSeqs, "msgs", msgs) - seqMsgs = append(seqMsgs, msgs...) - totalNotExistSeqs = append(totalNotExistSeqs, notExistSeqs...) - } - log.ZDebug(ctx, "getMsgBySeqsRange", "totalNotExistSeqs", totalNotExistSeqs) - // find by next doc - if len(totalNotExistSeqs) > 0 { - m = db.msg.GetDocIDSeqsMap(conversationID, totalNotExistSeqs) - for docID, seqs := range m { - docID = db.msg.ToNextDoc(docID) - msgs, _, unExistSeqs, err := db.GetMsgAndIndexBySeqsInOneDoc(ctx, docID, seqs) - if err != nil { - log.ZError(ctx, "get message from mongo exception", err, "docID", docID, "seqs", seqs) - continue - } - seqMsgs = append(seqMsgs, msgs...) - if len(unExistSeqs) > 0 { - log.ZWarn(ctx, "some seqs lost in mongo", err, "docID", docID, "seqs", seqs, "unExistSeqs", unExistSeqs) - } - } - } - var delSeqs []int64 - for _, msg := range seqMsgs { - if msg.Status == constant.MsgDeleted { - delSeqs = append(delSeqs, msg.Seq) - } - } - if len(delSeqs) > 0 { - msgs, err := db.refetchDelSeqsMsgs(ctx, conversationID, int64(len(delSeqs)), allSeqs[0], begin) - if err != nil { - log.ZWarn(ctx, "refetchDelSeqsMsgs", err, "delSeqs", delSeqs, "begin", begin) - } - seqMsgs = append(seqMsgs, msgs...) - } - // sort by seq - if len(totalNotExistSeqs) > 0 || len(delSeqs) > 0 { - sort.Sort(utils.MsgBySeq(seqMsgs)) - } - // missSeqs为依然缺失的 - return seqMsgs, nil -} - -func (db *msgDatabase) GetMsgBySeqsRange(ctx context.Context, conversationID string, begin, end, num int64) (seqMsg []*sdkws.MsgData, err error) { - var seqs []int64 - for i := end; i > end-num; i-- { - if i >= begin { - seqs = append(seqs, i) - } else { - break - } - } - successMsgs, failedSeqs, err := db.cache.GetMessagesBySeq(ctx, conversationID, seqs) - if err != nil { - if err != redis.Nil { - prome.Add(prome.MsgPullFromRedisFailedCounter, len(failedSeqs)) - log.ZError(ctx, "get message from redis exception", err, conversationID, seqs) - } - } - // get from cache or db - prome.Add(prome.MsgPullFromRedisSuccessCounter, len(successMsgs)) - if len(failedSeqs) > 0 { - mongoMsgs, err := db.getMsgBySeqsRange(ctx, conversationID, failedSeqs, begin, end, num-int64(len(successMsgs))) - if err != nil { - prome.Add(prome.MsgPullFromMongoFailedCounter, len(failedSeqs)) - return nil, err - } - prome.Add(prome.MsgPullFromMongoSuccessCounter, len(mongoMsgs)) - successMsgs = append(successMsgs, mongoMsgs...) - } - return successMsgs, nil -} - -func (db *msgDatabase) GetMsgBySeqs(ctx context.Context, conversationID string, seqs []int64) (successMsgs []*sdkws.MsgData, err error) { - successMsgs, failedSeqs, err := db.cache.GetMessagesBySeq(ctx, conversationID, seqs) - if err != nil { - if err != redis.Nil { - prome.Add(prome.MsgPullFromRedisFailedCounter, len(failedSeqs)) - log.ZError(ctx, "get message from redis exception", err, "failedSeqs", failedSeqs, "conversationID", conversationID) - } - } - prome.Add(prome.MsgPullFromRedisSuccessCounter, len(successMsgs)) - if len(failedSeqs) > 0 { - mongoMsgs, err := db.getMsgBySeqs(ctx, conversationID, seqs) - if err != nil { - prome.Add(prome.MsgPullFromMongoFailedCounter, len(failedSeqs)) - return nil, err - } - prome.Add(prome.MsgPullFromMongoSuccessCounter, len(mongoMsgs)) - successMsgs = append(successMsgs, mongoMsgs...) - } - return successMsgs, nil -} - -func (db *msgDatabase) CleanUpConversationMsgs(ctx context.Context, conversationID string) error { - err := db.DeleteConversationMsgsAndSetMinSeq(ctx, conversationID, 0) - if err != nil { - return err - } - return db.cache.CleanUpOneUserAllMsg(ctx, conversationID) -} - -// func (db *msgDatabase) DeleteUserSuperGroupMsgsAndSetMinSeq(ctx context.Context, groupID string, userIDs []string, remainTime int64) error { -// var delStruct delMsgRecursionStruct -// minSeq, err := db.deleteMsgRecursion(ctx, groupID, unRelationTb.OldestList, &delStruct, remainTime) -// if err != nil { -// log.ZError(ctx, "deleteMsgRecursion failed", err) -// } -// if minSeq == 0 { -// return nil -// } -// //log.NewDebug(operationID, utils.GetSelfFuncName(), "delMsgIDList:", delStruct, "minSeq", minSeq) -// for _, userID := range userIDs { -// userMinSeq, err := db.cache.GetGroupUserMinSeq(ctx, groupID, userID) -// if err != nil && err != redis.Nil { -// //log.NewError(operationID, utils.GetSelfFuncName(), "GetGroupUserMinSeq failed", groupID, userID, err.Error()) -// continue -// } -// if userMinSeq > minSeq { -// err = db.cache.SetGroupUserMinSeq(ctx, groupID, userID, userMinSeq) -// } else { -// err = db.cache.SetGroupUserMinSeq(ctx, groupID, userID, minSeq) -// } -// if err != nil { -// //log.NewError(operationID, utils.GetSelfFuncName(), err.Error(), groupID, userID, userMinSeq, minSeq) -// } -// } -// return nil -// } - -func (db *msgDatabase) DeleteConversationMsgsAndSetMinSeq(ctx context.Context, conversationID string, remainTime int64) error { - var delStruct delMsgRecursionStruct - minSeq, err := db.deleteMsgRecursion(ctx, conversationID, unRelationTb.OldestList, &delStruct, remainTime) - if err != nil { - return err - } - if minSeq == 0 { - return nil - } - return db.cache.SetMinSeq(ctx, conversationID, minSeq) -} - -// this is struct for recursion -type delMsgRecursionStruct struct { - minSeq int64 - delDocIDs []string -} - -func (d *delMsgRecursionStruct) getSetMinSeq() int64 { - return d.minSeq -} - -// index 0....19(del) 20...69 -// seq 70 -// set minSeq 21 -// recursion 删除list并且返回设置的最小seq -func (db *msgDatabase) deleteMsgRecursion(ctx context.Context, conversationID string, index int64, delStruct *delMsgRecursionStruct, remainTime int64) (int64, error) { - // find from oldest list - msgs, err := db.msgDocDatabase.GetMsgsByIndex(ctx, conversationID, index) - if err != nil || msgs.DocID == "" { - if err != nil { - if err == unrelation.ErrMsgListNotExist { - log.ZDebug(ctx, "deleteMsgRecursion ErrMsgListNotExist", "conversationID", conversationID, "index:", index) - } else { - log.ZError(ctx, "deleteMsgRecursion GetUserMsgListByIndex failed", err, "conversationID", conversationID, "index", index) - } - } - // 获取报错,或者获取不到了,物理删除并且返回seq delMongoMsgsPhysical(delStruct.delDocIDList), 结束递归 - err = db.msgDocDatabase.Delete(ctx, delStruct.delDocIDs) - if err != nil { - return 0, err - } - return delStruct.getSetMinSeq() + 1, nil - } - log.ZDebug(ctx, "conversationID", conversationID, "index:", index, "docID", msgs.DocID, "len", len(msgs.Msg)) - if int64(len(msgs.Msg)) > db.msg.GetSingleGocMsgNum() { - log.ZWarn(ctx, "msgs too large", nil, "lenth", len(msgs.Msg), "docID:", msgs.DocID) - } - if msgs.Msg[len(msgs.Msg)-1].SendTime+(remainTime*1000) < utils.GetCurrentTimestampByMill() && msgs.IsFull() { - delStruct.delDocIDs = append(delStruct.delDocIDs, msgs.DocID) - lastMsgPb := &sdkws.MsgData{} - err = proto.Unmarshal(msgs.Msg[len(msgs.Msg)-1].Msg, lastMsgPb) - if err != nil { - log.ZError(ctx, "proto.Unmarshal failed", err, "index", len(msgs.Msg)-1, "docID", msgs.DocID) - return 0, utils.Wrap(err, "proto.Unmarshal failed") - } - delStruct.minSeq = lastMsgPb.Seq - } else { - var hasMarkDelFlag bool - for i, msg := range msgs.Msg { - msgPb := &sdkws.MsgData{} - err = proto.Unmarshal(msg.Msg, msgPb) - if err != nil { - log.ZError(ctx, "proto.Unmarshal failed", err, "index", i, "docID", msgs.DocID) - return 0, utils.Wrap(err, "proto.Unmarshal failed") - } - if utils.GetCurrentTimestampByMill() > msg.SendTime+(remainTime*1000) { - msgPb.Status = constant.MsgDeleted - bytes, _ := proto.Marshal(msgPb) - msg.Msg = bytes - msg.SendTime = 0 - hasMarkDelFlag = true - } else { - // 到本条消息不需要删除, minSeq置为这条消息的seq - if err := db.msgDocDatabase.Delete(ctx, delStruct.delDocIDs); err != nil { - return 0, err - } - if hasMarkDelFlag { - if err := db.msgDocDatabase.UpdateOneDoc(ctx, msgs); err != nil { - return delStruct.getSetMinSeq(), utils.Wrap(err, "") - } - } - return msgPb.Seq, nil - } - } - } - // 继续递归 index+1 - seq, err := db.deleteMsgRecursion(ctx, conversationID, index+1, delStruct, remainTime) - return seq, utils.Wrap(err, "deleteMsg failed") -} - -func (db *msgDatabase) GetConversationMinMaxSeqInMongoAndCache(ctx context.Context, conversationID string) (minSeqMongo, maxSeqMongo, minSeqCache, maxSeqCache int64, err error) { - minSeqMongo, maxSeqMongo, err = db.GetMinMaxSeqMongo(ctx, conversationID) - if err != nil { - return - } - // from cache - minSeqCache, err = db.cache.GetMinSeq(ctx, conversationID) - if err != nil { - return - } - maxSeqCache, err = db.cache.GetMaxSeq(ctx, conversationID) - if err != nil { - return - } - return -} - -func (db *msgDatabase) GetMinMaxSeqMongo(ctx context.Context, conversationID string) (minSeqMongo, maxSeqMongo int64, err error) { - oldestMsgMongo, err := db.msgDocDatabase.GetOldestMsg(ctx, conversationID) - if err != nil { - return - } - msgPb, err := db.unmarshalMsg(oldestMsgMongo) - if err != nil { - return - } - minSeqMongo = msgPb.Seq - newestMsgMongo, err := db.msgDocDatabase.GetNewestMsg(ctx, conversationID) - if err != nil { - return - } - msgPb, err = db.unmarshalMsg(newestMsgMongo) - if err != nil { - return - } - maxSeqMongo = msgPb.Seq - return -} - -func (db *msgDatabase) SetMaxSeq(ctx context.Context, conversationID string, maxSeq int64) error { - return db.cache.SetMaxSeq(ctx, conversationID, maxSeq) -} -func (db *msgDatabase) GetMaxSeqs(ctx context.Context, conversationIDs []string) (map[string]int64, error) { - return db.cache.GetMaxSeqs(ctx, conversationIDs) -} -func (db *msgDatabase) GetMaxSeq(ctx context.Context, conversationID string) (int64, error) { - return db.cache.GetMaxSeq(ctx, conversationID) -} -func (db *msgDatabase) SetMinSeq(ctx context.Context, conversationID string, minSeq int64) error { - return db.cache.SetMinSeq(ctx, conversationID, minSeq) -} -func (db *msgDatabase) GetMinSeqs(ctx context.Context, conversationIDs []string) (map[string]int64, error) { - return db.cache.GetMinSeqs(ctx, conversationIDs) -} -func (db *msgDatabase) GetMinSeq(ctx context.Context, conversationID string) (int64, error) { - return db.cache.GetMinSeq(ctx, conversationID) -} -func (db *msgDatabase) GetConversationUserMinSeq(ctx context.Context, conversationID string, userID string) (int64, error) { - return db.cache.GetConversationUserMinSeq(ctx, conversationID, userID) -} -func (db *msgDatabase) GetConversationUserMinSeqs(ctx context.Context, conversationID string, userIDs []string) (map[string]int64, error) { - return db.cache.GetConversationUserMinSeqs(ctx, conversationID, userIDs) -} -func (db *msgDatabase) SetConversationUserMinSeq(ctx context.Context, conversationID string, userID string, minSeq int64) error { - return db.cache.SetConversationUserMinSeq(ctx, conversationID, userID, minSeq) -} -func (db *msgDatabase) SetConversationUserMinSeqs(ctx context.Context, conversationID string, seqs map[string]int64) (err error) { - return db.cache.SetConversationUserMinSeqs(ctx, conversationID, seqs) -} diff --git a/pkg/common/db/controller/notification.go b/pkg/common/db/controller/notification.go index 2230a24fc..3e70103df 100644 --- a/pkg/common/db/controller/notification.go +++ b/pkg/common/db/controller/notification.go @@ -35,8 +35,6 @@ type NotificationDatabase interface { DeleteMessageFromCache(ctx context.Context, conversationID string, msgList []*sdkws.MsgData) error // incrSeq然后批量插入缓存 BatchInsertChat2Cache(ctx context.Context, conversationID string, msgList []*sdkws.MsgData) (int64, error) - // incrSeq通知seq然后批量插入缓存 - NotificationBatchInsertChat2Cache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) (int64, error) // 删除消息 返回不存在的seqList DelMsgBySeqs(ctx context.Context, userID string, seqs []int64) (totalUnExistSeqs []int64, err error) // 获取群ID或者UserID最新一条在mongo里面的消息 @@ -96,10 +94,10 @@ func NewNotificationDatabase(msgDocModel unRelationTb.NotificationDocModelInterf } } -func InitNotificationDatabase(rdb redis.UniversalClient, database *mongo.Database) MsgDatabase { +func InitNotificationDatabase(rdb redis.UniversalClient, database *mongo.Database) CommonMsgDatabase { cacheModel := cache.NewMsgCacheModel(rdb) msgDocModel := unrelation.NewMsgMongoDriver(database) - msgDatabase := NewMsgDatabase(msgDocModel, cacheModel) + msgDatabase := NewCommonMsgDatabase(msgDocModel, cacheModel) return msgDatabase } @@ -318,10 +316,6 @@ func (db *notificationDatabase) DeleteMessageFromCache(ctx context.Context, user return db.cache.DeleteMessageFromCache(ctx, userID, msgs) } -func (db *notificationDatabase) NotificationBatchInsertChat2Cache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) (int64, error) { - return 0, nil -} - func (db *notificationDatabase) BatchInsertChat2Cache(ctx context.Context, conversationID string, msgList []*sdkws.MsgData) (int64, error) { //newTime := utils.GetCurrentTimestampByMill() lenList := len(msgList) diff --git a/pkg/common/db/localcache/conversation.go b/pkg/common/db/localcache/conversation.go index f6b07ac38..d991fa5a0 100644 --- a/pkg/common/db/localcache/conversation.go +++ b/pkg/common/db/localcache/conversation.go @@ -2,10 +2,11 @@ package localcache import ( "context" + "sync" + "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" - "sync" ) type ConversationLocalCacheInterface interface { @@ -26,7 +27,7 @@ func NewConversationLocalCache(client discoveryregistry.SvcDiscoveryRegistry) *C } func (g *ConversationLocalCache) GetRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error) { - conn, err := g.client.GetConn(config.Config.RpcRegisterName.OpenImConversationName) + conn, err := g.client.GetConn(ctx, config.Config.RpcRegisterName.OpenImConversationName) if err != nil { return nil, err } diff --git a/pkg/common/db/localcache/group.go b/pkg/common/db/localcache/group.go index 215fbd9ea..38cead1a6 100644 --- a/pkg/common/db/localcache/group.go +++ b/pkg/common/db/localcache/group.go @@ -2,11 +2,12 @@ package localcache import ( "context" + "sync" + "github.com/OpenIMSDK/Open-IM-Server/pkg/common/config" "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" - "sync" ) type GroupLocalCacheInterface interface { @@ -34,7 +35,7 @@ func NewGroupLocalCache(client discoveryregistry.SvcDiscoveryRegistry) *GroupLoc func (g *GroupLocalCache) GetGroupMemberIDs(ctx context.Context, groupID string) ([]string, error) { g.lock.Lock() defer g.lock.Unlock() - conn, err := g.client.GetConn(config.Config.RpcRegisterName.OpenImGroupName) + conn, err := g.client.GetConn(ctx, config.Config.RpcRegisterName.OpenImGroupName) if err != nil { return nil, err } diff --git a/pkg/discoveryregistry/discovery_register.go b/pkg/discoveryregistry/discovery_register.go index aba974697..31eae9ead 100644 --- a/pkg/discoveryregistry/discovery_register.go +++ b/pkg/discoveryregistry/discovery_register.go @@ -1,12 +1,14 @@ package discoveryregistry import ( + "context" + "google.golang.org/grpc" ) type Conn interface { - GetConns(serviceName string, opts ...grpc.DialOption) ([]*grpc.ClientConn, error) - GetConn(serviceName string, opts ...grpc.DialOption) (*grpc.ClientConn, error) + GetConns(ctx context.Context, serviceName string, opts ...grpc.DialOption) ([]*grpc.ClientConn, error) + GetConn(ctx context.Context, serviceName string, opts ...grpc.DialOption) (*grpc.ClientConn, error) AddOption(opts ...grpc.DialOption) } diff --git a/pkg/discoveryregistry/dns.go b/pkg/discoveryregistry/dns.go index 9f2af3d3f..adb45c7d9 100644 --- a/pkg/discoveryregistry/dns.go +++ b/pkg/discoveryregistry/dns.go @@ -15,7 +15,7 @@ import ( type DnsDiscoveryRegistry struct { opts []grpc.DialOption namespace string - config *rest.Config + clientset *kubernetes.Clientset } func NewDnsDiscoveryRegistry(namespace string, opts []grpc.DialOption) (*DnsDiscoveryRegistry, error) { @@ -23,19 +23,19 @@ func NewDnsDiscoveryRegistry(namespace string, opts []grpc.DialOption) (*DnsDisc if err != nil { return nil, err } + clientset, err := kubernetes.NewForConfig(config) + if err != nil { + return nil, err + } return &DnsDiscoveryRegistry{ - config: config, + clientset: clientset, namespace: namespace, opts: opts, }, nil } -func (d DnsDiscoveryRegistry) GetConns(serviceName string, opts ...grpc.DialOption) ([]*grpc.ClientConn, error) { - clientset, err := kubernetes.NewForConfig(d.config) - if err != nil { - return nil, err - } - endpoints, err := clientset.CoreV1().Endpoints(d.namespace).Get(context.TODO(), serviceName, metav1.GetOptions{}) +func (d DnsDiscoveryRegistry) GetConns(ctx context.Context, serviceName string, opts ...grpc.DialOption) ([]*grpc.ClientConn, error) { + endpoints, err := d.clientset.CoreV1().Endpoints(d.namespace).Get(context.TODO(), serviceName, metav1.GetOptions{}) if err != nil { return nil, err } @@ -43,7 +43,7 @@ func (d DnsDiscoveryRegistry) GetConns(serviceName string, opts ...grpc.DialOpti for _, subset := range endpoints.Subsets { for _, address := range subset.Addresses { for _, port := range subset.Ports { - conn, err := grpc.Dial(net.JoinHostPort(address.IP, string(port.Port)), append(d.opts, opts...)...) + conn, err := grpc.DialContext(ctx, net.JoinHostPort(address.IP, string(port.Port)), append(d.opts, opts...)...) if err != nil { return nil, err } @@ -54,8 +54,8 @@ func (d DnsDiscoveryRegistry) GetConns(serviceName string, opts ...grpc.DialOpti return conns, nil } -func (d DnsDiscoveryRegistry) GetConn(serviceName string, opts ...grpc.DialOption) (*grpc.ClientConn, error) { - return grpc.Dial(fmt.Sprintf("%s.%s.svc.cluster.local", serviceName, d.namespace), append(d.opts, opts...)...) +func (d DnsDiscoveryRegistry) GetConn(ctx context.Context, serviceName string, opts ...grpc.DialOption) (*grpc.ClientConn, error) { + return grpc.DialContext(ctx, fmt.Sprintf("%s.%s.svc.cluster.local", serviceName, d.namespace), append(d.opts, opts...)...) } func (d *DnsDiscoveryRegistry) AddOption(opts ...grpc.DialOption) { diff --git a/pkg/rpcclient/black.go b/pkg/rpcclient/black.go index e8a81fd12..161adb40c 100644 --- a/pkg/rpcclient/black.go +++ b/pkg/rpcclient/black.go @@ -18,7 +18,7 @@ func NewBlackClient(zk discoveryRegistry.SvcDiscoveryRegistry) *BlackClient { // possibleBlackUserID是否被userID拉黑,也就是是否在userID的黑名单中 func (b *BlackClient) IsBlocked(ctx context.Context, possibleBlackUserID, userID string) (bool, error) { - cc, err := b.getConn() + cc, err := b.getConn(ctx) if err != nil { return false, err } diff --git a/pkg/rpcclient/conversation.go b/pkg/rpcclient/conversation.go index ecd7c0912..05141e576 100644 --- a/pkg/rpcclient/conversation.go +++ b/pkg/rpcclient/conversation.go @@ -18,7 +18,7 @@ func NewConversationClient(zk discoveryRegistry.SvcDiscoveryRegistry) *Conversat } func (c *ConversationClient) ModifyConversationField(ctx context.Context, req *pbConversation.ModifyConversationFieldReq) error { - cc, err := c.getConn() + cc, err := c.getConn(ctx) if err != nil { return err } @@ -27,7 +27,7 @@ func (c *ConversationClient) ModifyConversationField(ctx context.Context, req *p } func (c *ConversationClient) GetSingleConversationRecvMsgOpt(ctx context.Context, userID, conversationID string) (int32, error) { - cc, err := c.getConn() + cc, err := c.getConn(ctx) if err != nil { return 0, err } @@ -42,7 +42,7 @@ func (c *ConversationClient) GetSingleConversationRecvMsgOpt(ctx context.Context } func (c *ConversationClient) SingleChatFirstCreateConversation(ctx context.Context, recvID, sendID string) error { - cc, err := c.getConn() + cc, err := c.getConn(ctx) if err != nil { return err } @@ -51,7 +51,7 @@ func (c *ConversationClient) SingleChatFirstCreateConversation(ctx context.Conte } func (c *ConversationClient) GroupChatFirstCreateConversation(ctx context.Context, groupID string, userIDs []string) error { - cc, err := c.getConn() + cc, err := c.getConn(ctx) if err != nil { return err } @@ -60,7 +60,7 @@ func (c *ConversationClient) GroupChatFirstCreateConversation(ctx context.Contex } func (c *ConversationClient) DelGroupChatConversations(ctx context.Context, ownerUserIDs []string, groupID string, maxSeq int64) error { - cc, err := c.getConn() + cc, err := c.getConn(ctx) if err != nil { return err } @@ -69,7 +69,7 @@ func (c *ConversationClient) DelGroupChatConversations(ctx context.Context, owne } func (c *ConversationClient) GetConversationIDs(ctx context.Context, ownerUserID string) ([]string, error) { - cc, err := c.getConn() + cc, err := c.getConn(ctx) if err != nil { return nil, err } diff --git a/pkg/rpcclient/friend.go b/pkg/rpcclient/friend.go index 6625a19f5..44745e4c2 100644 --- a/pkg/rpcclient/friend.go +++ b/pkg/rpcclient/friend.go @@ -18,7 +18,7 @@ func NewFriendClient(zk discoveryRegistry.SvcDiscoveryRegistry) *FriendClient { } func (f *FriendClient) GetFriendsInfo(ctx context.Context, ownerUserID, friendUserID string) (resp *sdkws.FriendInfo, err error) { - cc, err := f.getConn() + cc, err := f.getConn(ctx) if err != nil { return nil, err } @@ -32,7 +32,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() + cc, err := f.getConn(ctx) if err != nil { return false, err } @@ -45,7 +45,7 @@ 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() + cc, err := f.getConn(ctx) if err != nil { return nil, err } diff --git a/pkg/rpcclient/group.go b/pkg/rpcclient/group.go index 6d961d892..ed8387ad6 100644 --- a/pkg/rpcclient/group.go +++ b/pkg/rpcclient/group.go @@ -27,7 +27,7 @@ func NewGroupClient(client discoveryregistry.SvcDiscoveryRegistry) *GroupClient } func (g *GroupClient) GetGroupInfos(ctx context.Context, groupIDs []string, complete bool) ([]*sdkws.GroupInfo, error) { - cc, err := g.getConn() + cc, err := g.getConn(ctx) if err != nil { return nil, err } @@ -66,7 +66,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() + cc, err := g.getConn(ctx) if err != nil { return nil, err } @@ -106,7 +106,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() + cc, err := g.getConn(ctx) if err != nil { return nil, err } @@ -118,7 +118,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() + cc, err := g.getConn(ctx) if err != nil { return nil, err } @@ -130,7 +130,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() + cc, err := g.getConn(ctx) if err != nil { return nil, err } diff --git a/pkg/rpcclient/meta.go b/pkg/rpcclient/meta.go index f6c81f76a..51b195a48 100644 --- a/pkg/rpcclient/meta.go +++ b/pkg/rpcclient/meta.go @@ -74,8 +74,8 @@ func (m *MetaClient) getFaceURLAndName(userID string) (faceURL, nickname string, return users[0].GetFaceURL(), users[0].GetNickname(), nil } -func (m *MetaClient) getConn() (*grpc.ClientConn, error) { - return m.client.GetConn(m.rpcRegisterName) +func (m *MetaClient) getConn(ctx context.Context) (*grpc.ClientConn, error) { + return m.client.GetConn(ctx, m.rpcRegisterName) } type CommonUser interface { diff --git a/pkg/rpcclient/msg.go b/pkg/rpcclient/msg.go index b5cdaafff..3160235a4 100644 --- a/pkg/rpcclient/msg.go +++ b/pkg/rpcclient/msg.go @@ -108,7 +108,7 @@ func NewMsgClient(zk discoveryregistry.SvcDiscoveryRegistry) *MsgClient { } func (m *MsgClient) SendMsg(ctx context.Context, req *msg.SendMsgReq) (*msg.SendMsgResp, error) { - cc, err := m.getConn() + cc, err := m.getConn(ctx) if err != nil { return nil, err } @@ -117,7 +117,7 @@ func (m *MsgClient) SendMsg(ctx context.Context, req *msg.SendMsgReq) (*msg.Send } func (m *MsgClient) GetMaxSeq(ctx context.Context, req *sdkws.GetMaxSeqReq) (*sdkws.GetMaxSeqResp, error) { - cc, err := m.getConn() + cc, err := m.getConn(ctx) if err != nil { return nil, err } @@ -126,7 +126,7 @@ func (m *MsgClient) GetMaxSeq(ctx context.Context, req *sdkws.GetMaxSeqReq) (*sd } func (m *MsgClient) PullMessageBySeqList(ctx context.Context, req *sdkws.PullMessageBySeqsReq) (*sdkws.PullMessageBySeqsResp, error) { - cc, err := m.getConn() + cc, err := m.getConn(ctx) if err != nil { return nil, err } diff --git a/pkg/rpcclient/user.go b/pkg/rpcclient/user.go index d2465f82f..6324edd47 100644 --- a/pkg/rpcclient/user.go +++ b/pkg/rpcclient/user.go @@ -27,7 +27,7 @@ func NewUserClient(client discoveryregistry.SvcDiscoveryRegistry) *UserClient { } func (u *UserClient) GetUsersInfo(ctx context.Context, userIDs []string) ([]*sdkws.UserInfo, error) { - cc, err := u.getConn() + cc, err := u.getConn(ctx) if err != nil { return nil, err } @@ -97,7 +97,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() + cc, err := u.getConn(ctx) if err != nil { return 0, err } diff --git a/pkg/startrpc/start.go b/pkg/startrpc/start.go index c5a1d2564..f65164b6f 100644 --- a/pkg/startrpc/start.go +++ b/pkg/startrpc/start.go @@ -4,6 +4,7 @@ import ( "fmt" "net" "strconv" + "time" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/config" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/constant" @@ -28,7 +29,9 @@ func Start(rpcPort int, rpcRegisterName string, prometheusPort int, rpcFn func(c } defer listener.Close() fmt.Println(config.Config.Zookeeper.ZkAddr, config.Config.Zookeeper.Schema, rpcRegisterName) - zkClient, err := openKeeper.NewClient(config.Config.Zookeeper.ZkAddr, config.Config.Zookeeper.Schema, 10, "", "") + zkClient, err := openKeeper.NewClient(config.Config.Zookeeper.ZkAddr, config.Config.Zookeeper.Schema, + openKeeper.WithFreq(time.Hour), openKeeper.WithUserNameAndPassword(config.Config.Zookeeper.UserName, + config.Config.Zookeeper.Password), openKeeper.WithRoundRobin(), openKeeper.WithTimeout(10)) if err != nil { return utils.Wrap1(err) }