From e50b8bd8f1656d56dfdcffc54649220cf799a1f1 Mon Sep 17 00:00:00 2001
From: Xinwei Xiong <86140903+cubxxw@users.noreply.github.com>
Date: Mon, 3 Jul 2023 12:16:34 +0800
Subject: [PATCH 1/6] feat: adding actions (#461)

---
 .github/sync.yml                 | 26 +++++------
 .github/workflows/e2e-test.yml   |  1 -
 .github/workflows/link-pr.yml    | 78 ++++++++++++++------------------
 .github/workflows/opencommit.yml |  5 +-
 Makefile                         |  6 ---
 scripts/make-rules/golang.mk     |  2 +-
 6 files changed, 50 insertions(+), 68 deletions(-)

diff --git a/.github/sync.yml b/.github/sync.yml
index f543b2d39..859096c6f 100644
--- a/.github/sync.yml
+++ b/.github/sync.yml
@@ -6,12 +6,6 @@ OpenIMSDK/.github:
   - source: scripts/LICENSE/
     dest: scripts/LICENSE/
     replace: false
-  - source: .github/
-    dest: .github/
-    replace: false
-    exclude: |
-      workflows/
-      sync.yml
 
 OpenIMSDK/community:
   - source: LICENSE
@@ -21,14 +15,6 @@ OpenIMSDK/community:
     replace: false
   - source: .github/workflows/
     dest: .github/workflows/
-    exclude:
-      - e2e-test.yml
-      - sync.yml
-  - source: .github/
-    dest: .github/
-    replace: false
-    exclude: |
-      sync.yml
 
 OpenIMSDK/openim-sdk-core:
   - source: LICENSE
@@ -53,6 +39,18 @@ OpenIMSDK/OpenIM-Docs:
     dest: scripts/githooks/
     replace: true
 
+OpenIMSDK/OpenKF:
+  - source: LICENSE
+    dest: LICENSE
+  - source: scripts/LICENSE/
+    dest: scripts/LICENSE/
+    replace: false
+  - source: .github/workflows/issue-robot.yml
+    dest: .github/workflows/issue-robot.yml
+    replace: false
+  - source: .github/workflows/stale.yml
+    dest: .github/workflows/stale.yml
+    replace: false
 
 group:
   # first group:common to all warehouses
diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml
index 4e768b56d..e69de29bb 100644
--- a/.github/workflows/e2e-test.yml
+++ b/.github/workflows/e2e-test.yml
@@ -1 +0,0 @@
-# 
\ No newline at end of file
diff --git a/.github/workflows/link-pr.yml b/.github/workflows/link-pr.yml
index 844dd5fde..a3e0ee2de 100644
--- a/.github/workflows/link-pr.yml
+++ b/.github/workflows/link-pr.yml
@@ -1,47 +1,39 @@
-# name: Github Rebot for Link check error
+name: Github Rebot for Link check error
 
-# on:
-#   pull_request:
-#     branches: [ main ]
-#     paths:
-#       - '**.md'
-#       - 'docs/**'
-#       - '.lycheeignore'
-#   push:
-#     branches: [ main ]
-  
-#   schedule: 
-#     - cron:  '0 11 * * *'
+# Every Monday at 12:30 p.m
+on:
+  schedule:
+    - cron: '30 12 * * 1'
 
-# jobs:
-#   linkChecker:
-#     runs-on: ubuntu-latest
-#     steps:
-#       - uses: actions/checkout@v3
+jobs:
+  linkChecker:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
 
-#       - name: Link Checker
-#         id: lychee
-#         uses: lycheeverse/lychee-action@v1.7.0
-#         with:
-#             # For parameter description, see https://github.com/lycheeverse/lychee#commandline-parameters
-#             # Actions Link address -> https://github.com/lycheeverse/lychee-action
-#             # -E, --exclude-all-private    Exclude all private IPs from checking.
-#             # -i, --insecure               Proceed for server connections considered insecure (invalid TLS)
-#             # -n, --no-progress            Do not show progress bar.
-#             # -t, --timeout <timeout>      Website timeout in seconds from connect to response finished [default:20]
-#             # --max-concurrency <max-concurrency>    Maximum number of concurrent network requests [default: 128]
-#             # -a --accept <accept>                      Comma-separated list of accepted status codes for valid links
-#             # docs/.vitepress/dist the site directory to check
-#             # ./*.md all markdown files in the root directory
-#           args: --verbose  -E -i --no-progress --exclude-path './CHANGELOG' './**/*.md'
-#         env:
-#           GITHUB_TOKEN: ${{secrets.GH_PAT}}
+      - name: Link Checker
+        id: lychee
+        uses: lycheeverse/lychee-action@v1.7.0
+        with:
+            # For parameter description, see https://github.com/lycheeverse/lychee#commandline-parameters
+            # Actions Link address -> https://github.com/lycheeverse/lychee-action
+            # -E, --exclude-all-private    Exclude all private IPs from checking.
+            # -i, --insecure               Proceed for server connections considered insecure (invalid TLS)
+            # -n, --no-progress            Do not show progress bar.
+            # -t, --timeout <timeout>      Website timeout in seconds from connect to response finished [default:20]
+            # --max-concurrency <max-concurrency>    Maximum number of concurrent network requests [default: 128]
+            # -a --accept <accept>                      Comma-separated list of accepted status codes for valid links
+            # docs/.vitepress/dist the site directory to check
+            # ./*.md all markdown files in the root directory
+          args: --verbose  -E -i --no-progress --exclude-path './CHANGELOG' './**/*.md'
+        env:
+          GITHUB_TOKEN: ${{secrets.GH_PAT}}
 
-#       - name: Create Issue From File
-#         if: env.lychee_exit_code != 0
-#         uses: peter-evans/create-issue-from-file@v4
-#         with:
-#           title: Bug reports for links in OpenIM docs
-#           content-filepath: ./lychee/out.md
-#           labels: kind/documentation, triage/unresolved, report
-#           token: ${{ secrets.BOT_GITHUB_TOKEN }}
+      - name: Create Issue From File
+        if: env.lychee_exit_code != 0
+        uses: peter-evans/create-issue-from-file@v4
+        with:
+          title: Bug reports for links in OpenIM docs
+          content-filepath: ./lychee/out.md
+          labels: kind/documentation, triage/unresolved, report
+          token: ${{ secrets.BOT_GITHUB_TOKEN }}
diff --git a/.github/workflows/opencommit.yml b/.github/workflows/opencommit.yml
index d3d52508d..80fc9e302 100644
--- a/.github/workflows/opencommit.yml
+++ b/.github/workflows/opencommit.yml
@@ -2,9 +2,8 @@ name: 'OpenCommit Action'
 
 on:
   push:
-    # this list of branches is often enough,
-    # but you may still ignore other public branches
-    branches-ignore: [main master dev development release]
+    branches:
+      - main
 
 jobs:
   opencommit:
diff --git a/Makefile b/Makefile
index 5d7ac6bd3..2dd10fdbd 100644
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,3 @@
-
-# TODO: 参考我对 horizon 的 Makefile 设计: 
-# TODO: https://github.com/horizoncd/horizon/pull/141
-# TODO: 设计稿:代写~
-# TODO:请在 issue 关闭之前不要使用 Makefile 中的 targe(尤其是重构前)
-
 # ==============================================================================
 # define the default goal
 #
diff --git a/scripts/make-rules/golang.mk b/scripts/make-rules/golang.mk
index 336fead4a..1b70f09da 100644
--- a/scripts/make-rules/golang.mk
+++ b/scripts/make-rules/golang.mk
@@ -17,7 +17,7 @@
 #
 
 GO := go
-GO_SUPPORTED_VERSIONS ?= |1.15|1.16|1.17|1.18|1.19|1.20|
+GO_SUPPORTED_VERSIONS ?= 1.18|1.19|1.20
 
 GO_LDFLAGS += -X $(VERSION_PACKAGE).gitVersion=$(GIT_TAG) \
 	-X $(VERSION_PACKAGE).gitCommit=$(GIT_COMMIT) \

From 12dd42c60d39a4cbd30d5b9b3ea04b3a0817b038 Mon Sep 17 00:00:00 2001
From: withchao <993506633@qq.com>
Date: Mon, 3 Jul 2023 15:09:39 +0800
Subject: [PATCH 2/6] minio init

---
 pkg/common/db/obj/minio.go | 34 ++++++++++++++++++++--------------
 1 file changed, 20 insertions(+), 14 deletions(-)

diff --git a/pkg/common/db/obj/minio.go b/pkg/common/db/obj/minio.go
index d8d9ff70e..8e28896bd 100644
--- a/pkg/common/db/obj/minio.go
+++ b/pkg/common/db/obj/minio.go
@@ -33,21 +33,27 @@ func NewMinioInterface() (Interface, error) {
 	}
 	ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
 	defer cancel()
-	for _, bucket := range utils.Distinct([]string{conf.TempBucket, conf.DataBucket}) {
-		exists, err := client.BucketExists(ctx, bucket)
-		if err != nil {
-			return nil, fmt.Errorf("minio bucket %s exists %w", bucket, err)
-		}
-		if exists {
-			continue
-		}
-		opt := minio.MakeBucketOptions{
-			Region:        conf.Location,
-			ObjectLocking: conf.IsDistributedMod,
-		}
-		if err := client.MakeBucket(ctx, bucket, opt); err != nil {
-			return nil, fmt.Errorf("minio make bucket %s %w", bucket, err)
+	initBucket := func(ctx context.Context) error {
+		for _, bucket := range utils.Distinct([]string{conf.TempBucket, conf.DataBucket}) {
+			exists, err := client.BucketExists(ctx, bucket)
+			if err != nil {
+				return fmt.Errorf("minio bucket %s exists %w", bucket, err)
+			}
+			if exists {
+				continue
+			}
+			opt := minio.MakeBucketOptions{
+				Region:        conf.Location,
+				ObjectLocking: conf.IsDistributedMod,
+			}
+			if err := client.MakeBucket(ctx, bucket, opt); err != nil {
+				return fmt.Errorf("minio make bucket %s %w", bucket, err)
+			}
 		}
+		return nil
+	}
+	if err := initBucket(ctx); err != nil {
+		fmt.Println("minio init error:", err)
 	}
 	return &minioImpl{
 		client:     client,

From 941c1f954e88187e630465beef11cc3865597265 Mon Sep 17 00:00:00 2001
From: WangchuXiao <wangchuxiao97@outlook.com>
Date: Mon, 3 Jul 2023 15:21:17 +0800
Subject: [PATCH 3/6] V3dev (#463)

* statistics user register

* refactor: router change

* minio init

---------

Co-authored-by: withchao <993506633@qq.com>
Co-authored-by: Gordon <1432970085@qq.com>
---
 internal/api/route.go                | 17 +++++++-------
 pkg/common/db/obj/minio.go           | 34 ++++++++++++++++------------
 pkg/common/db/relation/user_model.go |  6 ++---
 3 files changed, 32 insertions(+), 25 deletions(-)

diff --git a/internal/api/route.go b/internal/api/route.go
index 84df97bb0..fb8c2d9a0 100644
--- a/internal/api/route.go
+++ b/internal/api/route.go
@@ -34,15 +34,16 @@ func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.Unive
 		r.GET("/metrics", prome.PrometheusHandler())
 	}
 	ParseToken := mw.GinParseToken(rdb)
-	userRouterGroup := r.Group("/user", ParseToken)
+	userRouterGroup := r.Group("/user")
 	{
-		userRouterGroup.POST("/update_user_info", u.UpdateUserInfo)
-		userRouterGroup.POST("/set_global_msg_recv_opt", u.SetGlobalRecvMessageOpt)
-		userRouterGroup.POST("/get_users_info", u.GetUsersPublicInfo)
-		userRouterGroup.POST("/get_all_users_uid", u.GetAllUsersID)
-		userRouterGroup.POST("/account_check", u.AccountCheck)
-		userRouterGroup.POST("/get_users", u.GetUsers)
-		userRouterGroup.POST("/get_users_online_status", u.GetUsersOnlineStatus)
+		userRouterGroup.POST("/user_register", u.UserRegister)
+		userRouterGroup.POST("/update_user_info", ParseToken, u.UpdateUserInfo)
+		userRouterGroup.POST("/set_global_msg_recv_opt", ParseToken, u.SetGlobalRecvMessageOpt)
+		userRouterGroup.POST("/get_users_info", ParseToken, u.GetUsersPublicInfo)
+		userRouterGroup.POST("/get_all_users_uid", ParseToken, u.GetAllUsersID)
+		userRouterGroup.POST("/account_check", ParseToken, u.AccountCheck)
+		userRouterGroup.POST("/get_users", ParseToken, u.GetUsers)
+		userRouterGroup.POST("/get_users_online_status", ParseToken, u.GetUsersOnlineStatus)
 	}
 	//friend routing group
 	friendRouterGroup := r.Group("/friend", ParseToken)
diff --git a/pkg/common/db/obj/minio.go b/pkg/common/db/obj/minio.go
index d8d9ff70e..8e28896bd 100644
--- a/pkg/common/db/obj/minio.go
+++ b/pkg/common/db/obj/minio.go
@@ -33,21 +33,27 @@ func NewMinioInterface() (Interface, error) {
 	}
 	ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
 	defer cancel()
-	for _, bucket := range utils.Distinct([]string{conf.TempBucket, conf.DataBucket}) {
-		exists, err := client.BucketExists(ctx, bucket)
-		if err != nil {
-			return nil, fmt.Errorf("minio bucket %s exists %w", bucket, err)
-		}
-		if exists {
-			continue
-		}
-		opt := minio.MakeBucketOptions{
-			Region:        conf.Location,
-			ObjectLocking: conf.IsDistributedMod,
-		}
-		if err := client.MakeBucket(ctx, bucket, opt); err != nil {
-			return nil, fmt.Errorf("minio make bucket %s %w", bucket, err)
+	initBucket := func(ctx context.Context) error {
+		for _, bucket := range utils.Distinct([]string{conf.TempBucket, conf.DataBucket}) {
+			exists, err := client.BucketExists(ctx, bucket)
+			if err != nil {
+				return fmt.Errorf("minio bucket %s exists %w", bucket, err)
+			}
+			if exists {
+				continue
+			}
+			opt := minio.MakeBucketOptions{
+				Region:        conf.Location,
+				ObjectLocking: conf.IsDistributedMod,
+			}
+			if err := client.MakeBucket(ctx, bucket, opt); err != nil {
+				return fmt.Errorf("minio make bucket %s %w", bucket, err)
+			}
 		}
+		return nil
+	}
+	if err := initBucket(ctx); err != nil {
+		fmt.Println("minio init error:", err)
 	}
 	return &minioImpl{
 		client:     client,
diff --git a/pkg/common/db/relation/user_model.go b/pkg/common/db/relation/user_model.go
index 385e65809..3390f7d3b 100644
--- a/pkg/common/db/relation/user_model.go
+++ b/pkg/common/db/relation/user_model.go
@@ -74,8 +74,8 @@ func (u *UserGorm) CountTotal(ctx context.Context) (count int64, err error) {
 
 func (u *UserGorm) CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) {
 	var res []struct {
-		Date  string `gorm:"column:date"`
-		Count int64  `gorm:"column:count"`
+		Date  time.Time `gorm:"column:date"`
+		Count int64     `gorm:"column:count"`
 	}
 	err := u.db(ctx).Model(&relation.UserModel{}).Select("DATE(create_time) AS date, count(1) AS count").Where("create_time >= ? and create_time < ?", start, end).Group("date").Find(&res).Error
 	if err != nil {
@@ -83,7 +83,7 @@ func (u *UserGorm) CountRangeEverydayTotal(ctx context.Context, start time.Time,
 	}
 	v := make(map[string]int64)
 	for _, r := range res {
-		v[r.Date] = r.Count
+		v[r.Date.Format("2006-01-02")] = r.Count
 	}
 	return v, nil
 }

From 3de21d13bdf600b02bf1a47ff382134b37a3e4bd Mon Sep 17 00:00:00 2001
From: withchao <993506633@qq.com>
Date: Mon, 3 Jul 2023 15:59:42 +0800
Subject: [PATCH 4/6] UserRegisterCount

---
 internal/rpc/user/statistics.go      |  11 +-
 pkg/common/db/controller/user.go     |   6 +-
 pkg/common/db/relation/user_model.go |  12 ++-
 pkg/common/db/table/relation/user.go |   2 +-
 pkg/proto/user/user.pb.go            | 152 ++++++++++++++-------------
 pkg/proto/user/user.proto            |   3 +-
 6 files changed, 104 insertions(+), 82 deletions(-)

diff --git a/internal/rpc/user/statistics.go b/internal/rpc/user/statistics.go
index 036b09687..742d79f3a 100644
--- a/internal/rpc/user/statistics.go
+++ b/internal/rpc/user/statistics.go
@@ -11,13 +11,18 @@ func (s *userServer) UserRegisterCount(ctx context.Context, req *pbuser.UserRegi
 	if req.Start > req.End {
 		return nil, errs.ErrArgs.Wrap("start > end")
 	}
-	total, err := s.CountTotal(ctx)
+	total, err := s.CountTotal(ctx, nil)
 	if err != nil {
 		return nil, err
 	}
-	count, err := s.CountRangeEverydayTotal(ctx, time.UnixMilli(req.Start), time.UnixMilli(req.End))
+	start := time.UnixMilli(req.Start)
+	before, err := s.CountTotal(ctx, &start)
 	if err != nil {
 		return nil, err
 	}
-	return &pbuser.UserRegisterCountResp{Total: total, Count: count}, nil
+	count, err := s.CountRangeEverydayTotal(ctx, start, time.UnixMilli(req.End))
+	if err != nil {
+		return nil, err
+	}
+	return &pbuser.UserRegisterCountResp{Total: total, Before: before, Count: count}, nil
 }
diff --git a/pkg/common/db/controller/user.go b/pkg/common/db/controller/user.go
index d1346d311..0ed9290f0 100644
--- a/pkg/common/db/controller/user.go
+++ b/pkg/common/db/controller/user.go
@@ -31,7 +31,7 @@ type UserDatabase interface {
 	//函数内部先查询db中是否存在,存在则什么都不做;不存在则插入
 	InitOnce(ctx context.Context, users []*relation.UserModel) (err error)
 	// 获取用户总数
-	CountTotal(ctx context.Context) (int64, error)
+	CountTotal(ctx context.Context, before *time.Time) (int64, error)
 	// 获取范围内用户增量
 	CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error)
 }
@@ -134,8 +134,8 @@ func (u *userDatabase) GetAllUserID(ctx context.Context) (userIDs []string, err
 	return u.userDB.GetAllUserID(ctx)
 }
 
-func (u *userDatabase) CountTotal(ctx context.Context) (count int64, err error) {
-	return u.userDB.CountTotal(ctx)
+func (u *userDatabase) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
+	return u.userDB.CountTotal(ctx, before)
 }
 
 func (u *userDatabase) CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) {
diff --git a/pkg/common/db/relation/user_model.go b/pkg/common/db/relation/user_model.go
index 3390f7d3b..da62ffff8 100644
--- a/pkg/common/db/relation/user_model.go
+++ b/pkg/common/db/relation/user_model.go
@@ -67,9 +67,15 @@ func (u *UserGorm) GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (
 	return opt, err
 }
 
-func (u *UserGorm) CountTotal(ctx context.Context) (count int64, err error) {
-	err = u.db(ctx).Model(&relation.UserModel{}).Count(&count).Error
-	return count, errs.Wrap(err)
+func (u *UserGorm) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
+	db := u.db(ctx).Model(&relation.UserModel{})
+	if before != nil {
+		db = db.Where("create_time < ?", before)
+	}
+	if err := db.Count(&count).Error; err != nil {
+		return 0, err
+	}
+	return count, nil
 }
 
 func (u *UserGorm) CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) {
diff --git a/pkg/common/db/table/relation/user.go b/pkg/common/db/table/relation/user.go
index 35b52602f..86d53e279 100644
--- a/pkg/common/db/table/relation/user.go
+++ b/pkg/common/db/table/relation/user.go
@@ -52,7 +52,7 @@ type UserModelInterface interface {
 	GetAllUserID(ctx context.Context) (userIDs []string, err error)
 	GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error)
 	// 获取用户总数
-	CountTotal(ctx context.Context) (count int64, err error)
+	CountTotal(ctx context.Context, before *time.Time) (count int64, err error)
 	// 获取范围内用户增量
 	CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error)
 }
diff --git a/pkg/proto/user/user.pb.go b/pkg/proto/user/user.pb.go
index f0db26e04..50fba3398 100644
--- a/pkg/proto/user/user.pb.go
+++ b/pkg/proto/user/user.pb.go
@@ -1509,8 +1509,9 @@ type UserRegisterCountResp struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Total int64            `protobuf:"varint,1,opt,name=total,proto3" json:"total"`
-	Count map[string]int64 `protobuf:"bytes,2,rep,name=count,proto3" json:"count" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
+	Total  int64            `protobuf:"varint,1,opt,name=total,proto3" json:"total"`
+	Before int64            `protobuf:"varint,2,opt,name=before,proto3" json:"before"`
+	Count  map[string]int64 `protobuf:"bytes,3,rep,name=count,proto3" json:"count" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
 }
 
 func (x *UserRegisterCountResp) Reset() {
@@ -1552,6 +1553,13 @@ func (x *UserRegisterCountResp) GetTotal() int64 {
 	return 0
 }
 
+func (x *UserRegisterCountResp) GetBefore() int64 {
+	if x != nil {
+		return x.Before
+	}
+	return 0
+}
+
 func (x *UserRegisterCountResp) GetCount() map[string]int64 {
 	if x != nil {
 		return x.Count
@@ -1788,80 +1796,82 @@ var file_user_user_proto_rawDesc = []byte{
 	0x73, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74,
 	0x52, 0x65, 0x71, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01,
 	0x28, 0x03, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64,
-	0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0xb2, 0x01, 0x0a, 0x15,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0xca, 0x01, 0x0a, 0x15,
 	0x75, 0x73, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e,
 	0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x49, 0x0a, 0x05, 0x63,
-	0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x4f, 0x70, 0x65,
-	0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x75,
-	0x73, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74,
-	0x52, 0x65, 0x73, 0x70, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52,
-	0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x1a, 0x38, 0x0a, 0x0a, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x45,
-	0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01,
-	0x32, 0x9f, 0x07, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x66, 0x0a, 0x11, 0x67, 0x65, 0x74,
-	0x44, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x27,
-	0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x75, 0x73,
-	0x65, 0x72, 0x2e, 0x67, 0x65, 0x74, 0x44, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x65, 0x55,
-	0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x28, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d,
-	0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x67, 0x65, 0x74, 0x44,
-	0x65, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73,
-	0x70, 0x12, 0x5d, 0x0a, 0x0e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x49,
-	0x6e, 0x66, 0x6f, 0x12, 0x24, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76,
-	0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73,
-	0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x1a, 0x25, 0x2e, 0x4f, 0x70, 0x65, 0x6e,
-	0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x75, 0x70,
-	0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70,
-	0x12, 0x78, 0x0a, 0x17, 0x73, 0x65, 0x74, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x52, 0x65, 0x63,
-	0x76, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x12, 0x2d, 0x2e, 0x4f, 0x70,
+	0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x62,
+	0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x62, 0x65, 0x66,
+	0x6f, 0x72, 0x65, 0x12, 0x49, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x03,
+	0x28, 0x0b, 0x32, 0x33, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65,
+	0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73,
+	0x74, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x2e, 0x43, 0x6f, 0x75,
+	0x6e, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x1a, 0x38,
+	0x0a, 0x0a, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03,
+	0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14,
+	0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76,
+	0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x32, 0x9f, 0x07, 0x0a, 0x04, 0x75, 0x73, 0x65,
+	0x72, 0x12, 0x66, 0x0a, 0x11, 0x67, 0x65, 0x74, 0x44, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74,
+	0x65, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x27, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53,
+	0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x67, 0x65, 0x74, 0x44, 0x65,
+	0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x1a,
+	0x28, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x75,
+	0x73, 0x65, 0x72, 0x2e, 0x67, 0x65, 0x74, 0x44, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x65,
+	0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x5d, 0x0a, 0x0e, 0x75, 0x70, 0x64,
+	0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x24, 0x2e, 0x4f, 0x70,
 	0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e,
-	0x73, 0x65, 0x74, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x76, 0x4d, 0x65, 0x73,
-	0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x2e, 0x2e, 0x4f, 0x70, 0x65,
-	0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x73,
-	0x65, 0x74, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x76, 0x4d, 0x65, 0x73, 0x73,
-	0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x78, 0x0a, 0x17, 0x67, 0x65,
-	0x74, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x76, 0x4d, 0x65, 0x73, 0x73, 0x61,
-	0x67, 0x65, 0x4f, 0x70, 0x74, 0x12, 0x2d, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65,
-	0x72, 0x76, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x67, 0x65, 0x74, 0x47, 0x6c, 0x6f,
-	0x62, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x76, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70,
-	0x74, 0x52, 0x65, 0x71, 0x1a, 0x2e, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72,
-	0x76, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x67, 0x65, 0x74, 0x47, 0x6c, 0x6f, 0x62,
-	0x61, 0x6c, 0x52, 0x65, 0x63, 0x76, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74,
-	0x52, 0x65, 0x73, 0x70, 0x12, 0x57, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43,
-	0x68, 0x65, 0x63, 0x6b, 0x12, 0x22, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72,
-	0x76, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74,
-	0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x1a, 0x23, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49,
-	0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x61, 0x63, 0x63,
-	0x6f, 0x75, 0x6e, 0x74, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x12, 0x69, 0x0a,
-	0x12, 0x67, 0x65, 0x74, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x73,
-	0x65, 0x72, 0x73, 0x12, 0x28, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76,
-	0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x67, 0x65, 0x74, 0x50, 0x61, 0x67, 0x69, 0x6e,
-	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x29, 0x2e,
+	0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65,
+	0x71, 0x1a, 0x25, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
+	0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72,
+	0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x12, 0x78, 0x0a, 0x17, 0x73, 0x65, 0x74, 0x47,
+	0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x76, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+	0x4f, 0x70, 0x74, 0x12, 0x2d, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76,
+	0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x73, 0x65, 0x74, 0x47, 0x6c, 0x6f, 0x62, 0x61,
+	0x6c, 0x52, 0x65, 0x63, 0x76, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x52,
+	0x65, 0x71, 0x1a, 0x2e, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65,
+	0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x73, 0x65, 0x74, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c,
+	0x52, 0x65, 0x63, 0x76, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x52, 0x65,
+	0x73, 0x70, 0x12, 0x78, 0x0a, 0x17, 0x67, 0x65, 0x74, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x52,
+	0x65, 0x63, 0x76, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x12, 0x2d, 0x2e,
 	0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65,
-	0x72, 0x2e, 0x67, 0x65, 0x74, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55,
-	0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x57, 0x0a, 0x0c, 0x75, 0x73, 0x65, 0x72,
-	0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x22, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49,
-	0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65,
-	0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x23, 0x2e, 0x4f,
+	0x72, 0x2e, 0x67, 0x65, 0x74, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x76, 0x4d,
+	0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x2e, 0x2e, 0x4f,
 	0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72,
-	0x2e, 0x75, 0x73, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73,
-	0x70, 0x12, 0x57, 0x0a, 0x0c, 0x67, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x49,
-	0x44, 0x12, 0x22, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
-	0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x67, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x55, 0x73, 0x65, 0x72,
-	0x49, 0x44, 0x52, 0x65, 0x71, 0x1a, 0x23, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65,
-	0x72, 0x76, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x67, 0x65, 0x74, 0x41, 0x6c, 0x6c,
-	0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x12, 0x66, 0x0a, 0x11, 0x75, 0x73,
-	0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12,
-	0x27, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x75,
-	0x73, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
-	0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x28, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49,
-	0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65,
-	0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65,
-	0x73, 0x70, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
-	0x2f, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x44, 0x4b, 0x2f, 0x4f, 0x70, 0x65, 0x6e, 0x2d,
-	0x49, 0x4d, 0x2d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72,
-	0x6f, 0x74, 0x6f, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x2e, 0x67, 0x65, 0x74, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x52, 0x65, 0x63, 0x76, 0x4d, 0x65,
+	0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x57, 0x0a, 0x0c,
+	0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x22, 0x2e, 0x4f,
+	0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72,
+	0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71,
+	0x1a, 0x23, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e,
+	0x75, 0x73, 0x65, 0x72, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x68, 0x65, 0x63,
+	0x6b, 0x52, 0x65, 0x73, 0x70, 0x12, 0x69, 0x0a, 0x12, 0x67, 0x65, 0x74, 0x50, 0x61, 0x67, 0x69,
+	0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x28, 0x2e, 0x4f, 0x70,
+	0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e,
+	0x67, 0x65, 0x74, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x73, 0x65,
+	0x72, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x29, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65,
+	0x72, 0x76, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x67, 0x65, 0x74, 0x50, 0x61, 0x67,
+	0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70,
+	0x12, 0x57, 0x0a, 0x0c, 0x75, 0x73, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
+	0x12, 0x22, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e,
+	0x75, 0x73, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
+	0x72, 0x52, 0x65, 0x71, 0x1a, 0x23, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72,
+	0x76, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x52, 0x65, 0x67,
+	0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x57, 0x0a, 0x0c, 0x67, 0x65, 0x74,
+	0x41, 0x6c, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x12, 0x22, 0x2e, 0x4f, 0x70, 0x65, 0x6e,
+	0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x67, 0x65,
+	0x74, 0x41, 0x6c, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x52, 0x65, 0x71, 0x1a, 0x23, 0x2e,
+	0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65,
+	0x72, 0x2e, 0x67, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x52, 0x65,
+	0x73, 0x70, 0x12, 0x66, 0x0a, 0x11, 0x75, 0x73, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74,
+	0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x27, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d,
+	0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72,
+	0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71,
+	0x1a, 0x28, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e,
+	0x75, 0x73, 0x65, 0x72, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
+	0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x69,
+	0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x4f, 0x70, 0x65, 0x6e, 0x49, 0x4d, 0x53,
+	0x44, 0x4b, 0x2f, 0x4f, 0x70, 0x65, 0x6e, 0x2d, 0x49, 0x4d, 0x2d, 0x53, 0x65, 0x72, 0x76, 0x65,
+	0x72, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x75, 0x73, 0x65, 0x72,
+	0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
diff --git a/pkg/proto/user/user.proto b/pkg/proto/user/user.proto
index 6cdbf53d9..117eb3a5f 100644
--- a/pkg/proto/user/user.proto
+++ b/pkg/proto/user/user.proto
@@ -141,7 +141,8 @@ message userRegisterCountReq {
 
 message userRegisterCountResp {
   int64 total = 1;
-  map<string, int64> count = 2;
+  int64 before = 2;
+  map<string, int64> count = 3;
 }
 
 service user {

From 01d3fefd5da30264a7baa7ec2a540f54f4f29cfa Mon Sep 17 00:00:00 2001
From: wangchuxiao <wangchuxiao97@outlook.com>
Date: Mon, 3 Jul 2023 16:36:52 +0800
Subject: [PATCH 5/6] push use local conn

---
 .idea/Open-IM-Server.iml                    |  9 +++
 .idea/dataSources.xml                       | 14 ++++
 .idea/misc.xml                              |  6 ++
 .idea/modules.xml                           |  8 +++
 .idea/vcs.xml                               |  6 ++
 pkg/discoveryregistry/discovery_register.go |  3 +-
 pkg/discoveryregistry/zookeeper/discover.go | 32 +++++----
 pkg/discoveryregistry/zookeeper/register.go |  3 +-
 pkg/discoveryregistry/zookeeper/zk.go       |  9 +--
 test/mongo/cmd/main.go                      | 59 -----------------
 test/mongo/mongo_utils.go                   | 73 ---------------------
 test/mysql/cmd/main.go                      | 23 -------
 test/mysql/importuser.go                    | 70 --------------------
 13 files changed, 65 insertions(+), 250 deletions(-)
 create mode 100644 .idea/Open-IM-Server.iml
 create mode 100644 .idea/dataSources.xml
 create mode 100644 .idea/misc.xml
 create mode 100644 .idea/modules.xml
 create mode 100644 .idea/vcs.xml
 delete mode 100644 test/mongo/cmd/main.go
 delete mode 100644 test/mongo/mongo_utils.go
 delete mode 100644 test/mysql/cmd/main.go
 delete mode 100644 test/mysql/importuser.go

diff --git a/.idea/Open-IM-Server.iml b/.idea/Open-IM-Server.iml
new file mode 100644
index 000000000..5e764c4f0
--- /dev/null
+++ b/.idea/Open-IM-Server.iml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="WEB_MODULE" version="4">
+  <component name="Go" enabled="true" />
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml
new file mode 100644
index 000000000..589964a46
--- /dev/null
+++ b/.idea/dataSources.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="DataSourceManagerImpl" format="xml" multifile-model="true">
+    <data-source source="LOCAL" name="grafana" uuid="95aae14a-3593-4ff7-ab49-5e4316cbecd1">
+      <driver-ref>sqlite.xerial</driver-ref>
+      <synchronize>true</synchronize>
+      <jdbc-driver>org.sqlite.JDBC</jdbc-driver>
+      <jdbc-url>jdbc:sqlite:C:\Users\Administrator\Desktop\Open-IM-Server\docker-compose_cfg\grafana.db</jdbc-url>
+      <driver-properties>
+        <property name="enable_load_extension" value="true" />
+      </driver-properties>
+    </data-source>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 000000000..28a804d89
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="JavaScriptSettings">
+    <option name="languageLevel" value="ES6" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 000000000..d9805dbb6
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/Open-IM-Server.iml" filepath="$PROJECT_DIR$/.idea/Open-IM-Server.iml" />
+    </modules>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 000000000..94a25f7f4
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/pkg/discoveryregistry/discovery_register.go b/pkg/discoveryregistry/discovery_register.go
index 01ed88d5b..d7ea00c47 100644
--- a/pkg/discoveryregistry/discovery_register.go
+++ b/pkg/discoveryregistry/discovery_register.go
@@ -4,7 +4,6 @@ import (
 	"context"
 
 	"google.golang.org/grpc"
-	"google.golang.org/grpc/resolver"
 )
 
 type Conn interface {
@@ -13,7 +12,7 @@ type Conn interface {
 	AddOption(opts ...grpc.DialOption)
 	CloseConn(conn grpc.ClientConnInterface)
 	// do not use this method for call rpc
-	GetClientLocalConns() map[string][]resolver.Address
+	GetClientLocalConns() map[string][]grpc.ClientConnInterface
 }
 
 type SvcDiscoveryRegistry interface {
diff --git a/pkg/discoveryregistry/zookeeper/discover.go b/pkg/discoveryregistry/zookeeper/discover.go
index 65dacd397..a9848ee32 100644
--- a/pkg/discoveryregistry/zookeeper/discover.go
+++ b/pkg/discoveryregistry/zookeeper/discover.go
@@ -7,6 +7,7 @@ import (
 	"strings"
 
 	"github.com/OpenIMSDK/Open-IM-Server/pkg/common/log"
+	"github.com/OpenIMSDK/Open-IM-Server/pkg/errs"
 	"github.com/pkg/errors"
 
 	"github.com/go-zookeeper/zk"
@@ -61,7 +62,7 @@ func (s *ZkClient) GetConnsRemote(serviceName string) (conns []resolver.Address,
 				}
 				return nil, errors.Wrap(err, "get children error")
 			}
-			log.ZDebug(context.Background(), "get conns from remote", "conn", string(data))
+			log.ZDebug(context.Background(), "get addrs from remote", "conn", string(data))
 			conns = append(conns, resolver.Address{Addr: string(data), ServerName: serviceName})
 		}
 	}
@@ -70,34 +71,31 @@ func (s *ZkClient) GetConnsRemote(serviceName string) (conns []resolver.Address,
 
 func (s *ZkClient) GetConns(ctx context.Context, serviceName string, opts ...grpc.DialOption) ([]grpc.ClientConnInterface, error) {
 	s.logger.Printf("get conns from client, serviceName: %s", serviceName)
-	s.lock.Lock()
 	opts = append(s.options, opts...)
+	s.lock.Lock()
+	defer s.lock.Unlock()
 	conns := s.localConns[serviceName]
 	if len(conns) == 0 {
 		var err error
 		s.logger.Printf("get conns from zk remote, serviceName: %s", serviceName)
-		conns, err = s.GetConnsRemote(serviceName)
+		addrs, err := s.GetConnsRemote(serviceName)
 		if err != nil {
-			s.lock.Unlock()
 			return nil, err
 		}
-		if len(conns) == 0 {
+		if len(addrs) == 0 {
 			return nil, fmt.Errorf("no conn for service %s, grpc server may not exist, local conn is %v, please check zookeeper server %v, path: %s", serviceName, s.localConns, s.zkServers, s.zkRoot)
 		}
+		for _, addr := range addrs {
+			cc, err := grpc.DialContext(ctx, addr.Addr, append(s.options, opts...)...)
+			if err != nil {
+				log.ZError(context.Background(), "dialContext failed", err, "addr", addr.Addr, "opts", append(s.options, opts...))
+				return nil, errs.Wrap(err)
+			}
+			conns = append(conns, cc)
+		}
 		s.localConns[serviceName] = conns
 	}
-	s.lock.Unlock()
-	var ret []grpc.ClientConnInterface
-	s.logger.Printf("get conns from zk success, serviceName: %s", serviceName)
-	for _, conn := range conns {
-		cc, err := grpc.DialContext(ctx, conn.Addr, append(s.options, opts...)...)
-		if err != nil {
-			return nil, errors.Wrap(err, fmt.Sprintf("conns dialContext error, conn: %s", conn.Addr))
-		}
-		ret = append(ret, cc)
-	}
-	s.logger.Printf("dial ctx success, serviceName: %s", serviceName)
-	return ret, nil
+	return conns, nil
 }
 
 func (s *ZkClient) GetConn(ctx context.Context, serviceName string, opts ...grpc.DialOption) (grpc.ClientConnInterface, error) {
diff --git a/pkg/discoveryregistry/zookeeper/register.go b/pkg/discoveryregistry/zookeeper/register.go
index 8f38f6d8d..bd7572c92 100644
--- a/pkg/discoveryregistry/zookeeper/register.go
+++ b/pkg/discoveryregistry/zookeeper/register.go
@@ -5,7 +5,6 @@ import (
 
 	"github.com/go-zookeeper/zk"
 	"google.golang.org/grpc"
-	"google.golang.org/grpc/resolver"
 )
 
 func (s *ZkClient) CreateRpcRootNodes(serviceNames []string) error {
@@ -43,7 +42,7 @@ func (s *ZkClient) UnRegister() error {
 	}
 	time.Sleep(time.Second)
 	s.node = ""
-	s.localConns = make(map[string][]resolver.Address)
+	s.localConns = make(map[string][]grpc.ClientConnInterface)
 	s.resolvers = make(map[string]*Resolver)
 	return nil
 }
diff --git a/pkg/discoveryregistry/zookeeper/zk.go b/pkg/discoveryregistry/zookeeper/zk.go
index be0fb5bb0..3fab2402e 100644
--- a/pkg/discoveryregistry/zookeeper/zk.go
+++ b/pkg/discoveryregistry/zookeeper/zk.go
@@ -37,8 +37,9 @@ type ZkClient struct {
 	lock    sync.Locker
 	options []grpc.DialOption
 
-	resolvers    map[string]*Resolver
-	localConns   map[string][]resolver.Address
+	resolvers  map[string]*Resolver
+	localConns map[string][]grpc.ClientConnInterface
+
 	balancerName string
 
 	logger Logger
@@ -89,7 +90,7 @@ func NewClient(zkServers []string, zkRoot string, options ...ZkOption) (*ZkClien
 		zkRoot:     "/",
 		scheme:     zkRoot,
 		timeout:    timeout,
-		localConns: make(map[string][]resolver.Address),
+		localConns: make(map[string][]grpc.ClientConnInterface),
 		resolvers:  make(map[string]*Resolver),
 		lock:       &sync.Mutex{},
 	}
@@ -197,6 +198,6 @@ func (s *ZkClient) AddOption(opts ...grpc.DialOption) {
 	s.options = append(s.options, opts...)
 }
 
-func (s *ZkClient) GetClientLocalConns() map[string][]resolver.Address {
+func (s *ZkClient) GetClientLocalConns() map[string][]grpc.ClientConnInterface {
 	return s.localConns
 }
diff --git a/test/mongo/cmd/main.go b/test/mongo/cmd/main.go
deleted file mode 100644
index 9b4f315f8..000000000
--- a/test/mongo/cmd/main.go
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright © 2023 OpenIM. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
-	"Open_IM/pkg/common/config"
-	mongo2 "Open_IM/test/mongo"
-	"context"
-	"flag"
-	"fmt"
-	"go.mongodb.org/mongo-driver/mongo"
-	"go.mongodb.org/mongo-driver/mongo/options"
-)
-
-func init() {
-	uri := "mongodb://sample.host:27017/?maxPoolSize=20&w=majority"
-	if config.Config.Mongo.DBUri != "" {
-		// example: mongodb://$user:$password@mongo1.mongo:27017,mongo2.mongo:27017,mongo3.mongo:27017/$DBDatabase/?replicaSet=rs0&readPreference=secondary&authSource=admin&maxPoolSize=$DBMaxPoolSize
-		uri = config.Config.Mongo.DBUri
-	} else {
-		if config.Config.Mongo.DBPassword != "" && config.Config.Mongo.DBUserName != "" {
-			uri = fmt.Sprintf("mongodb://%s:%s@%s/%s?maxPoolSize=%d", config.Config.Mongo.DBUserName, config.Config.Mongo.DBPassword, config.Config.Mongo.DBAddress[0],
-				config.Config.Mongo.DBDatabase, config.Config.Mongo.DBMaxPoolSize)
-		} else {
-			uri = fmt.Sprintf("mongodb://%s/%s/?maxPoolSize=%d",
-				config.Config.Mongo.DBAddress[0], config.Config.Mongo.DBDatabase,
-				config.Config.Mongo.DBMaxPoolSize)
-		}
-	}
-	var err error
-	mongo2.Client, err = mongo.Connect(context.TODO(), options.Client().ApplyURI(uri))
-	if err != nil {
-		panic(err)
-	}
-	err = mongo2.Client.Ping(context.TODO(), nil)
-	if err != nil {
-		panic(err)
-	}
-	fmt.Println("Connected to MongoDB!")
-}
-
-func main() {
-	userID := flag.String("userID", "", "userID")
-	flag.Parse()
-	fmt.Println("userID:", *userID)
-	mongo2.GetUserAllChat(*userID)
-}
diff --git a/test/mongo/mongo_utils.go b/test/mongo/mongo_utils.go
deleted file mode 100644
index 50d000f99..000000000
--- a/test/mongo/mongo_utils.go
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright © 2023 OpenIM. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mongo
-
-import (
-	"Open_IM/pkg/common/config"
-	server_api_params "Open_IM/pkg/proto/sdk_ws"
-	"context"
-	"fmt"
-	"github.com/golang/protobuf/proto"
-	"go.mongodb.org/mongo-driver/mongo"
-	"gopkg.in/mgo.v2/bson"
-	"time"
-)
-
-var (
-	Client *mongo.Client
-)
-
-type MsgInfo struct {
-	SendTime int64
-	Msg      []byte
-}
-
-type UserChat struct {
-	UID string
-	Msg []MsgInfo
-}
-
-func GetUserAllChat(uid string) {
-	ctx, _ := context.WithTimeout(context.Background(), time.Duration(config.Config.Mongo.DBTimeout)*time.Second)
-	collection := Client.Database(config.Config.Mongo.DBDatabase).Collection("msg")
-	var userChatList []UserChat
-	uid = uid + ":"
-	filter := bson.M{"uid": bson.M{"$regex": uid}}
-	//filter := bson.M{"uid": "17726378428:0"}
-	result, err := collection.Find(context.Background(), filter)
-	if err != nil {
-		fmt.Println("find error", err.Error())
-		return
-	}
-	if err := result.All(ctx, &userChatList); err != nil {
-		fmt.Println(err.Error())
-	}
-	for _, userChat := range userChatList {
-		for _, msg := range userChat.Msg {
-			msgData := &server_api_params.MsgData{}
-			err := proto.Unmarshal(msg.Msg, msgData)
-			if err != nil {
-				fmt.Println(err.Error(), msg)
-				continue
-			}
-			fmt.Println("seq: ", msgData.Seq, "status: ", msgData.Status,
-				"sendID: ", msgData.SendID, "recvID: ", msgData.RecvID,
-				"sendTime: ", msgData.SendTime,
-				"clientMsgID: ", msgData.ClientMsgID,
-				"serverMsgID: ", msgData.ServerMsgID,
-				"content: ", string(msgData.Content))
-		}
-	}
-}
diff --git a/test/mysql/cmd/main.go b/test/mysql/cmd/main.go
deleted file mode 100644
index b3d73b8db..000000000
--- a/test/mysql/cmd/main.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright © 2023 OpenIM. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
-	"Open_IM/test/mysql"
-)
-
-func main() {
-	mysql.ImportUserToSuperGroup()
-}
diff --git a/test/mysql/importuser.go b/test/mysql/importuser.go
deleted file mode 100644
index 07d97340d..000000000
--- a/test/mysql/importuser.go
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright © 2023 OpenIM. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package mysql
-
-import (
-	"Open_IM/pkg/common/db"
-	"Open_IM/pkg/common/db/mysql_model/im_mysql_model"
-	"Open_IM/pkg/common/log"
-	"strconv"
-	"time"
-)
-
-func ImportUserToSuperGroup() {
-	for i := 18000000700; i <= 18000000800; i++ {
-		user := db.User{
-			UserID:           strconv.Itoa(i),
-			Nickname:         strconv.Itoa(i),
-			FaceURL:          "",
-			Gender:           0,
-			PhoneNumber:      strconv.Itoa(i),
-			Birth:            time.Time{},
-			Email:            "",
-			Ex:               "",
-			CreateTime:       time.Time{},
-			AppMangerLevel:   0,
-			GlobalRecvMsgOpt: 0,
-		}
-		err := im_mysql_model.UserRegister(user)
-		if err != nil {
-			log.NewError("", err.Error(), user)
-			continue
-		}
-
-		groupMember := db.GroupMember{
-			GroupID:        "3907826375",
-			UserID:         strconv.Itoa(i),
-			Nickname:       strconv.Itoa(i),
-			FaceURL:        "",
-			RoleLevel:      0,
-			JoinTime:       time.Time{},
-			JoinSource:     0,
-			InviterUserID:  "openIMAdmin",
-			OperatorUserID: "openIMAdmin",
-			MuteEndTime:    time.Time{},
-			Ex:             "",
-		}
-
-		err = im_mysql_model.InsertIntoGroupMember(groupMember)
-		if err != nil {
-			log.NewError("", err.Error(), user)
-			continue
-		}
-
-		log.NewInfo("success", i)
-
-	}
-
-}

From 1ac62795693d14c3e84b8d30153e2949df36aa29 Mon Sep 17 00:00:00 2001
From: wangchuxiao <wangchuxiao97@outlook.com>
Date: Mon, 3 Jul 2023 17:02:42 +0800
Subject: [PATCH 6/6] remove online push close grpc conn

---
 internal/push/push_to_client.go | 1 -
 1 file changed, 1 deletion(-)

diff --git a/internal/push/push_to_client.go b/internal/push/push_to_client.go
index 7f08ee0aa..607d862e1 100644
--- a/internal/push/push_to_client.go
+++ b/internal/push/push_to_client.go
@@ -244,7 +244,6 @@ func (p *Pusher) GetConnsAndOnlinePush(ctx context.Context, msg *sdkws.MsgData,
 	for _, v := range conns {
 		msgClient := msggateway.NewMsgGatewayClient(v)
 		reply, err := msgClient.SuperGroupOnlineBatchPushOneMsg(ctx, &msggateway.OnlineBatchPushOneMsgReq{MsgData: msg, PushToUserIDs: pushToUserIDs})
-		p.discov.CloseConn(v)
 		if err != nil {
 			continue
 		}