Compare commits

..

2 Commits

Author SHA1 Message Date
Xinwei Xiong(cubxxw-openim) 6922520545 feat: add test
Signed-off-by: Xinwei Xiong(cubxxw-openim) <3293172751nss@gmail.com>
2023-07-27 21:30:04 +08:00
Xinwei Xiong(cubxxw-openim) 246a1f0314 feat: add test
Signed-off-by: Xinwei Xiong(cubxxw-openim) <3293172751nss@gmail.com>
2023-07-27 21:08:59 +08:00
24 changed files with 105 additions and 460 deletions
+2 -2
View File
@@ -1,5 +1,5 @@
USER=root
PASSWORD=openIM123
MINIO_ENDPOINT=http://127.0.0.1:10005
API_URL=http://127.0.0.1:10002/object/
MINIO_ENDPOINT=http://113.99.98.99:10005
API_URL=http://113.99.98.99:10002/object/
DATA_DIR=./
+36
View File
@@ -98,3 +98,39 @@ jobs:
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta3.outputs.tags }}
labels: ${{ steps.meta3.outputs.labels }}
# name: OpenIM Build Docker Images
# on:
# push:
# tags:
# - v*
# jobs:
# build:
# runs-on: ubuntu-latest
# strategy:
# matrix:
# bin:
# - openim-server
# steps:
# - name: Checkout
# uses: actions/checkout@v3
# - name: Setup Docker Buildx
# uses: docker/setup-buildx-action@v2
# - name: Login to GitHub Container Registry
# uses: docker/login-action@v2
# with:
# registry: ghcr.io
# username: ${{ github.repository_owner }}
# password: ${{ secrets.GITHUB_TOKEN }}
# - name: Docker metadata
# id: metadata
# uses: docker/metadata-action@v4
# with:
# images: ghcr.io/${{ github.repository_owner }}/openim-${{ matrix.bin }}
# - name: Build and release Docker images
# uses: docker/build-push-action@v3
# with:
# platforms: linux/386,linux/amd64,linux/arm64/v8
# target: ${{ matrix.bin }}
# tags: ${{ steps.metadata.outputs.tags }}
# push: true
-3
View File
@@ -480,9 +480,6 @@ checksum:
release:
footer: |
## Welcome to the {{ .Tag }} release of [chat](https://github.com/OpenIMSDK/chat)!🎉🎉!
**Full Changelog**: https://github.com/OpenIMSDK/Open-IM-Server/compare/{{ .PreviousTag }}...{{ .Tag }}
## Helping out
+2 -3
View File
@@ -22,8 +22,7 @@ RUN /bin/sh -c "make build"
# Production Stage
FROM alpine
RUN echo "https://mirrors.aliyun.com/alpine/v3.4/main" > /etc/apk/repositories && \
apk --no-cache add tzdata ca-certificates bash
RUN apk --no-cache add tzdata
# Set directory to map logs, config files, scripts, and SDK
VOLUME ["/Open-IM-Server/logs", "/Open-IM-Server/config", "/Open-IM-Server/scripts", "/Open-IM-Server/db/sdk"]
@@ -34,4 +33,4 @@ COPY --from=builder /Open-IM-Server/_output/bin/platforms/linux/amd64 /Open-IM-S
WORKDIR /Open-IM-Server/scripts
CMD ["./docker_start_all.sh"]
CMD ["docker_start_all.sh"]
+1
View File
@@ -8,6 +8,7 @@
⭐️ Open source Instant Messaging Server ⭐️ <br>
<h3>
<p align=center>
<a href="https://goreportcard.com/report/github.com/OpenIMSDK/Open-IM-Server"><img src="https://goreportcard.com/badge/github.com/OpenIMSDK/Open-IM-Server" alt="A+"></a>
<a href="https://github.com/OpenIMSDK/Open-IM-Server/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22good+first+issue%22"><img src="https://img.shields.io/github/issues/OpenIMSDK/Open-IM-Server/good%20first%20issue?logo=%22github%22" alt="good first"></a>
+3 -3
View File
@@ -126,10 +126,10 @@ api:
# Configuration for Aliyun OSS
object:
enable: "minio"
apiURL: http://127.0.0.1:10002/object/
apiURL: http://113.99.98.99:10002/object/
minio:
bucket: "openim"
endpoint: http://127.0.0.1:10005
endpoint: http://113.99.98.99:10005
accessKeyID: root
secretAccessKey: openIM123
sessionToken: ""
@@ -371,4 +371,4 @@ prometheus:
conversationPrometheusPort: [ 20230 ]
rtcPrometheusPort: [ 21300 ]
thirdPrometheusPort: [ 21301 ]
messageTransferPrometheusPort: [ 21400, 21401, 21402, 21403 ]
messageTransferPrometheusPort: [ 21400, 21401, 21402, 21403 ]
+2 -2
View File
@@ -100,7 +100,7 @@ services:
openim_server:
image: ghcr.io/openimsdk/openim-server:release-v3.1
image: ghcr.io/openimsdk/openim-server:v3.0
container_name: openim-server
volumes:
- ./logs:/Open-IM-Server/logs
@@ -124,7 +124,7 @@ services:
max-file: "2"
openim_chat:
image: ghcr.io/openimsdk/openim-chat:v1.1.1
image: ghcr.io/openimsdk/openim-chat:v1.0.0
container_name: openim_chat
restart: always
depends_on:
+1 -1
View File
@@ -37,7 +37,7 @@ require (
require github.com/google/uuid v1.3.0
require (
github.com/OpenIMSDK/protocol v0.0.2
github.com/OpenIMSDK/protocol v0.0.1
github.com/OpenIMSDK/tools v0.0.5
github.com/aliyun/aliyun-oss-go-sdk v2.2.7+incompatible
github.com/go-redis/redis v6.15.9+incompatible
+2 -2
View File
@@ -16,8 +16,8 @@ cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5og
firebase.google.com/go v3.13.0+incompatible h1:3TdYC3DDi6aHn20qoRkxwGqNgdjtblwVAyRLQwGn/+4=
firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIwjt8toICdV5Wh9ptHs=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/OpenIMSDK/protocol v0.0.2 h1:O53/WiqLCHF9aWPLI32GPF82hn7suM8PkhrtL89Klrw=
github.com/OpenIMSDK/protocol v0.0.2/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
github.com/OpenIMSDK/protocol v0.0.1 h1:Q6J1jCU00dfqmguxw2XI+IGcVfBAkb5Tz8LgvyeNkk0=
github.com/OpenIMSDK/protocol v0.0.1/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y=
github.com/OpenIMSDK/tools v0.0.5 h1:yBVHJ3EpIDcp8VFKPjuGr6MQvFa3t4JByZ+vmeC06/Q=
github.com/OpenIMSDK/tools v0.0.5/go.mod h1:eg+q4A34Qmu73xkY0mt37FHGMCMfC6CtmOnm0kFEGFI=
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
-4
View File
@@ -79,10 +79,6 @@ func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.Unive
userRouterGroup.POST("/get_users", ParseToken, u.GetUsers)
userRouterGroup.POST("/get_users_online_status", ParseToken, u.GetUsersOnlineStatus)
userRouterGroup.POST("/get_users_online_token_detail", ParseToken, u.GetUsersOnlineTokenDetail)
userRouterGroup.POST("/subscribe_users_status", ParseToken, u.UnSubscriberStatus)
userRouterGroup.POST("/unsubscribe_users_status", ParseToken, u.UnSubscriberStatus)
userRouterGroup.POST("/get_users_status", ParseToken, u.GetUserStatus)
}
// friend routing group
friendRouterGroup := r.Group("/friend", ParseToken)
+3 -19
View File
@@ -62,7 +62,6 @@ func (u *UserApi) GetUsers(c *gin.Context) {
a2r.Call(user.UserClient.GetPaginationUsers, u.Client, c)
}
// GetUsersOnlineStatus Get user online status.
func (u *UserApi) GetUsersOnlineStatus(c *gin.Context) {
var req msggateway.GetUsersOnlineStatusReq
if err := c.BindJSON(&req); err != nil {
@@ -96,13 +95,13 @@ func (u *UserApi) GetUsersOnlineStatus(c *gin.Context) {
wsResult = append(wsResult, reply.SuccessResult...)
}
}
// Traversing the userIDs in the api request body
// 遍历 api 请求体中的 userIDs
for _, v1 := range req.UserIDs {
flag = false
res := new(msggateway.GetUsersOnlineStatusResp_SuccessResult)
// Iterate through the online results fetched from various gateways
// 遍历从各个网关中获取的在线结果
for _, v2 := range wsResult {
// If matches the above description on the line, and vice versa
// 如果匹配上说明在线,反之
if v2.UserID == v1 {
flag = true
res.UserID = v1
@@ -124,7 +123,6 @@ func (u *UserApi) UserRegisterCount(c *gin.Context) {
a2r.Call(user.UserClient.UserRegisterCount, u.Client, c)
}
// GetUsersOnlineTokenDetail Get user online token details.
func (u *UserApi) GetUsersOnlineTokenDetail(c *gin.Context) {
var wsResult []*msggateway.GetUsersOnlineStatusResp_SuccessResult
var respResult []*msggateway.SingleDetail
@@ -184,17 +182,3 @@ func (u *UserApi) GetUsersOnlineTokenDetail(c *gin.Context) {
apiresp.GinSuccess(c, respResult)
}
// SubscriberStatus Presence status of subscribed users.
func (u *UserApi) SubscriberStatus(c *gin.Context) {
a2r.Call(user.UserClient.SubscribeOrCancelUsersStatus, u.Client, c)
}
// UnSubscriberStatus Unsubscribe a user's presence.
func (u *UserApi) UnSubscriberStatus(c *gin.Context) {
a2r.Call(user.UserClient.SubscribeOrCancelUsersStatus, u.Client, c)
}
func (u *UserApi) GetUserStatus(c *gin.Context) {
a2r.Call(user.UserClient.GetUserStatus, u.Client, c)
}
+1 -13
View File
@@ -39,13 +39,7 @@ type Req struct {
}
func (r *Req) String() string {
var tReq Req
tReq.ReqIdentifier = r.ReqIdentifier
tReq.Token = r.Token
tReq.SendID = r.SendID
tReq.OperationID = r.OperationID
tReq.MsgIncr = r.MsgIncr
return utils.StructToJsonString(tReq)
return utils.StructToJsonString(r)
}
type Resp struct {
@@ -58,12 +52,6 @@ type Resp struct {
}
func (r *Resp) String() string {
var tResp Resp
tResp.ReqIdentifier = r.ReqIdentifier
tResp.MsgIncr = r.MsgIncr
tResp.OperationID = r.OperationID
tResp.ErrCode = r.ErrCode
tResp.ErrMsg = r.ErrMsg
return utils.StructToJsonString(r)
}
+1 -1
View File
@@ -1040,7 +1040,7 @@ func (s *groupServer) GetUserReqApplicationList(ctx context.Context, req *pbGrou
groupIDs := utils.Distinct(utils.Slice(requests, func(e *relationTb.GroupRequestModel) string {
return e.GroupID
}))
groups, err := s.GroupDatabase.FindNotDismissedGroup(ctx, groupIDs)
groups, err := s.GroupDatabase.FindGroup(ctx, groupIDs)
if err != nil {
return nil, err
}
+6 -36
View File
@@ -17,12 +17,13 @@ package user
import (
"context"
"errors"
"github.com/OpenIMSDK/Open-IM-Server/pkg/authverify"
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/unrelation"
"github.com/OpenIMSDK/tools/log"
"strings"
"time"
"github.com/OpenIMSDK/Open-IM-Server/pkg/authverify"
"github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/config"
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/convert"
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/cache"
@@ -59,10 +60,6 @@ func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
if err != nil {
return err
}
mongo, err := unrelation.NewMongo()
if err != nil {
return err
}
if err := db.AutoMigrate(&tablerelation.UserModel{}); err != nil {
return err
}
@@ -75,8 +72,7 @@ func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
}
userDB := relation.NewUserGorm(db)
cache := cache.NewUserCacheRedis(rdb, userDB, cache.GetDefaultOpt())
userMongoDB := unrelation.NewUserMongoDriver(mongo.GetDatabase())
database := controller.NewUserDatabase(userDB, cache, tx.NewGorm(db), userMongoDB)
database := controller.NewUserDatabase(userDB, cache, tx.NewGorm(db))
friendRpcClient := rpcclient.NewFriendRpcClient(client)
msgRpcClient := rpcclient.NewMessageRpcClient(client)
u := &userServer{
@@ -239,7 +235,6 @@ func (s *userServer) GetGlobalRecvMessageOpt(ctx context.Context, req *pbuser.Ge
return &pbuser.GetGlobalRecvMessageOptResp{GlobalRecvMsgOpt: user[0].GlobalRecvMsgOpt}, nil
}
// GetAllUserID Get user account by page.
func (s *userServer) GetAllUserID(ctx context.Context, req *pbuser.GetAllUserIDReq) (resp *pbuser.GetAllUserIDResp, err error) {
userIDs, err := s.UserDatabase.GetAllUserID(ctx, req.Pagination.PageNumber, req.Pagination.ShowNumber)
if err != nil {
@@ -248,31 +243,6 @@ func (s *userServer) GetAllUserID(ctx context.Context, req *pbuser.GetAllUserIDR
return &pbuser.GetAllUserIDResp{UserIDs: userIDs}, nil
}
// SubscribeOrCancelUsersStatus Subscribe online or cancel online users.
func (s *userServer) SubscribeOrCancelUsersStatus(ctx context.Context, req *pbuser.SubscribeOrCancelUsersStatusReq) (resp *pbuser.SubscribeOrCancelUsersStatusResp, err error) {
err = s.UserDatabase.SubscribeOrCancelUsersStatus(ctx, req.UserID, req.UserIDs, req.Genre)
if err != nil {
return nil, err
}
//var status map[string][]string
//TODO 获取用户在线列表,返回订阅的用户的在线列表
return &pbuser.SubscribeOrCancelUsersStatusResp{}, nil
}
func (s *userServer) GetUserStatus(ctx context.Context, req *pbuser.GetUserStatusReq) (resp *pbuser.GetUserStatusResp, err error) {
//TODO 是否加一个参数校验-判断req.userID的数量,每一个获取加一个限制,一次请求限制500?
onlineStatusList, err := s.UserDatabase.GetUserStatus(ctx, req.UserIDs)
if err != nil {
return nil, err
}
return &pbuser.GetUserStatusResp{StatusList: onlineStatusList}, nil
}
func (s *userServer) SetUserStatus(ctx context.Context, req *pbuser.SetUserStatusReq) (resp *pbuser.SetUserStatusResp, err error) {
err = s.UserDatabase.SetUserStatus(ctx, req.StatusList)
if err != nil {
return nil, err
}
return &pbuser.SetUserStatusResp{}, nil
panic("implement me")
}
-2
View File
@@ -82,12 +82,10 @@ func InitMsgTool() (*MsgTool, error) {
discov.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()))
userDB := relation.NewUserGorm(db)
msgDatabase := controller.InitCommonMsgDatabase(rdb, mongo.GetDatabase())
userMongoDB := unrelation.NewUserMongoDriver(mongo.GetDatabase())
userDatabase := controller.NewUserDatabase(
userDB,
cache.NewUserCacheRedis(rdb, relation.NewUserGorm(db), cache.GetDefaultOpt()),
tx.NewGorm(db),
userMongoDB,
)
groupDatabase := controller.InitGroupDatabase(db, rdb, mongo.GetDatabase())
conversationDatabase := controller.NewConversationDatabase(
+3 -82
View File
@@ -16,9 +16,6 @@ package cache
import (
"context"
"encoding/json"
"github.com/OpenIMSDK/protocol/user"
"strconv"
"time"
"github.com/dtm-labs/rockscache"
@@ -28,12 +25,9 @@ import (
)
const (
userExpireTime = time.Second * 60 * 60 * 12
userInfoKey = "USER_INFO:"
userGlobalRecvMsgOptKey = "USER_GLOBAL_RECV_MSG_OPT_KEY:"
olineStatusKey = "ONLINE_STATUS:"
userOlineStatusExpireTime = time.Second * 60 * 60 * 24
statusMod = 500
userExpireTime = time.Second * 60 * 60 * 12
userInfoKey = "USER_INFO:"
userGlobalRecvMsgOptKey = "USER_GLOBAL_RECV_MSG_OPT_KEY:"
)
type UserCache interface {
@@ -44,13 +38,10 @@ type UserCache interface {
DelUsersInfo(userIDs ...string) UserCache
GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error)
DelUsersGlobalRecvMsgOpt(userIDs ...string) UserCache
GetUserStatus(ctx context.Context, userIDs []string) ([]*user.OnlineStatus, error)
SetUserStatus(ctx context.Context, list []*user.OnlineStatus) error
}
type UserCacheRedis struct {
metaCache
rdb redis.UniversalClient
userDB relationTb.UserModelInterface
expireTime time.Duration
rcClient *rockscache.Client
@@ -63,7 +54,6 @@ func NewUserCacheRedis(
) UserCache {
rcClient := rockscache.NewClient(rdb, options)
return &UserCacheRedis{
rdb: rdb,
metaCache: NewMetaCacheRedis(rcClient),
userDB: userDB,
expireTime: userExpireTime,
@@ -73,7 +63,6 @@ func NewUserCacheRedis(
func (u *UserCacheRedis) NewCache() UserCache {
return &UserCacheRedis{
rdb: u.rdb,
metaCache: NewMetaCacheRedis(u.rcClient, u.metaCache.GetPreDelKeys()...),
userDB: u.userDB,
expireTime: u.expireTime,
@@ -156,71 +145,3 @@ func (u *UserCacheRedis) DelUsersGlobalRecvMsgOpt(userIDs ...string) UserCache {
cache.AddKeys(keys...)
return cache
}
func (u *UserCacheRedis) getOnlineStatusKey(userID string) string {
return olineStatusKey + userID
}
// GetUserStatus get user status
func (u *UserCacheRedis) GetUserStatus(ctx context.Context, userIDs []string) ([]*user.OnlineStatus, error) {
var res []*user.OnlineStatus
for _, userID := range userIDs {
UserIDNum, err := strconv.Atoi(userID)
if err != nil {
return nil, err
}
var modKey = strconv.Itoa(UserIDNum % statusMod)
var onlineStatus user.OnlineStatus
key := olineStatusKey + modKey
result, err := u.rdb.HGet(ctx, key, userID).Result()
if err != nil {
if err == redis.Nil {
// key or field does not exist
res = append(res, &user.OnlineStatus{
UserID: userID,
Status: 0,
PlatformID: -1,
})
continue
} else {
return nil, err
}
}
err = json.Unmarshal([]byte(result), &onlineStatus)
if err != nil {
return nil, err
}
onlineStatus.UserID = userID
res = append(res, &onlineStatus)
}
return res, nil
}
// SetUserStatus Set the user status and save it in redis
func (u *UserCacheRedis) SetUserStatus(ctx context.Context, list []*user.OnlineStatus) error {
for _, status := range list {
var isNewKey int64
UserIDNum, err := strconv.Atoi(status.UserID)
if err != nil {
return err
}
var modKey = strconv.Itoa(UserIDNum % statusMod)
key := olineStatusKey + modKey
jsonData, err := json.Marshal(status)
if err != nil {
return err
}
isNewKey, err = u.rdb.Exists(ctx, key).Result()
if err != nil {
return err
}
_, err = u.rdb.HSet(ctx, key, status.UserID, string(jsonData)).Result()
if err != nil {
return err
}
if isNewKey > 0 {
u.rdb.Expire(ctx, key, userOlineStatusExpireTime)
}
}
return nil
}
-5
View File
@@ -39,7 +39,6 @@ type GroupDatabase interface {
CreateGroup(ctx context.Context, groups []*relationTb.GroupModel, groupMembers []*relationTb.GroupMemberModel) error
TakeGroup(ctx context.Context, groupID string) (group *relationTb.GroupModel, err error)
FindGroup(ctx context.Context, groupIDs []string) (groups []*relationTb.GroupModel, err error)
FindNotDismissedGroup(ctx context.Context, groupIDs []string) (groups []*relationTb.GroupModel, err error)
SearchGroup(
ctx context.Context,
keyword string,
@@ -582,7 +581,3 @@ func (g *groupDatabase) CountRangeEverydayTotal(ctx context.Context, start time.
func (g *groupDatabase) FindGroupRequests(ctx context.Context, groupID string, userIDs []string) (int64, []*relationTb.GroupRequestModel, error) {
return g.groupRequestDB.FindGroupRequests(ctx, groupID, userIDs)
}
func (g *groupDatabase) FindNotDismissedGroup(ctx context.Context, groupIDs []string) (groups []*relationTb.GroupModel, err error) {
return g.groupDB.FindNotDismissedGroup(ctx, groupIDs)
}
+28 -77
View File
@@ -16,9 +16,6 @@ package controller
import (
"context"
unRelationTb "github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/table/unrelation"
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/protocol/user"
"time"
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/cache"
@@ -29,49 +26,38 @@ import (
)
type UserDatabase interface {
// FindWithError Get the information of the specified user. If the userID is not found, it will also return an error
// 获取指定用户的信息 如有userID未找到 也返回错误
FindWithError(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error)
// Find Get the information of the specified user If the userID is not found, no error will be returned
// 获取指定用户的信息 如有userID未找到 不返回错误
Find(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error)
// Create Insert multiple external guarantees that the userID is not repeated and does not exist in the db
// 插入多条 外部保证userID 不重复 且在db中不存在
Create(ctx context.Context, users []*relation.UserModel) (err error)
// Update update (non-zero value) external guarantee userID exists
// 更新(非零值) 外部保证userID存在
Update(ctx context.Context, user *relation.UserModel) (err error)
// UpdateByMap update (zero value) external guarantee userID exists
// 更新(零值) 外部保证userID存在
UpdateByMap(ctx context.Context, userID string, args map[string]interface{}) (err error)
// Page If not found, no error is returned
// 如果没找到,不返回错误
Page(ctx context.Context, pageNumber, showNumber int32) (users []*relation.UserModel, count int64, err error)
// IsExist true as long as one exists
// 只要有一个存在就为true
IsExist(ctx context.Context, userIDs []string) (exist bool, err error)
// GetAllUserID Get all user IDs
// 获取所有用户ID
GetAllUserID(ctx context.Context, pageNumber, showNumber int32) ([]string, error)
// InitOnce Inside the function, first query whether it exists in the db, if it exists, do nothing; if it does not exist, insert it
// 函数内部先查询db中是否存在,存在则什么都不做;不存在则插入
InitOnce(ctx context.Context, users []*relation.UserModel) (err error)
// CountTotal Get the total number of users
// 获取用户总数
CountTotal(ctx context.Context, before *time.Time) (int64, error)
// CountRangeEverydayTotal Get the user increment in the range
// 获取范围内用户增量
CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error)
//SubscribeOrCancelUsersStatus Subscribe or unsubscribe a user's presence status
SubscribeOrCancelUsersStatus(ctx context.Context, userID string, userIDs []string, genre int32) error
// GetAllSubscribeList Get a list of all subscriptions
GetAllSubscribeList(ctx context.Context, userID string) ([]string, error)
// GetSubscribedList Get all subscribed lists
GetSubscribedList(ctx context.Context, userID string) ([]string, error)
// GetUserStatus Get the online status of the user
GetUserStatus(ctx context.Context, userIDs []string) ([]*user.OnlineStatus, error)
// SetUserStatus Set the user status and store the user status in redis
SetUserStatus(ctx context.Context, list []*user.OnlineStatus) error
}
type userDatabase struct {
userDB relation.UserModelInterface
cache cache.UserCache
tx tx.Tx
mongoDB unRelationTb.UserModelInterface
userDB relation.UserModelInterface
cache cache.UserCache
tx tx.Tx
}
func NewUserDatabase(userDB relation.UserModelInterface, cache cache.UserCache, tx tx.Tx, mongoDB unRelationTb.UserModelInterface) UserDatabase {
return &userDatabase{userDB: userDB, cache: cache, tx: tx, mongoDB: mongoDB}
func NewUserDatabase(userDB relation.UserModelInterface, cache cache.UserCache, tx tx.Tx) UserDatabase {
return &userDatabase{userDB: userDB, cache: cache, tx: tx}
}
func (u *userDatabase) InitOnce(ctx context.Context, users []*relation.UserModel) (err error) {
@@ -89,7 +75,7 @@ func (u *userDatabase) InitOnce(ctx context.Context, users []*relation.UserModel
return nil
}
// FindWithError Get the information of the specified user and return an error if the userID is not found.
// 获取指定用户的信息 如有userID未找到 也返回错误.
func (u *userDatabase) FindWithError(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error) {
users, err = u.cache.GetUsersInfo(ctx, userIDs)
if err != nil {
@@ -101,13 +87,13 @@ func (u *userDatabase) FindWithError(ctx context.Context, userIDs []string) (use
return
}
// Find Get the information of the specified user. If the userID is not found, no error will be returned.
// 获取指定用户的信息 如有userID未找到 不返回错误.
func (u *userDatabase) Find(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error) {
users, err = u.cache.GetUsersInfo(ctx, userIDs)
return
}
// Create Insert multiple external guarantees that the userID is not repeated and does not exist in the db.
// 插入多条 外部保证userID 不重复 且在db中不存在.
func (u *userDatabase) Create(ctx context.Context, users []*relation.UserModel) (err error) {
if err := u.tx.Transaction(func(tx any) error {
err = u.userDB.Create(ctx, users)
@@ -125,7 +111,7 @@ func (u *userDatabase) Create(ctx context.Context, users []*relation.UserModel)
return u.cache.DelUsersInfo(userIDs...).ExecDel(ctx)
}
// Update (non-zero value) externally guarantees that userID exists.
// 更新(非零值) 外部保证userID存在.
func (u *userDatabase) Update(ctx context.Context, user *relation.UserModel) (err error) {
if err := u.userDB.Update(ctx, user); err != nil {
return err
@@ -133,7 +119,7 @@ func (u *userDatabase) Update(ctx context.Context, user *relation.UserModel) (er
return u.cache.DelUsersInfo(user.UserID).ExecDel(ctx)
}
// UpdateByMap update (zero value) externally guarantees that userID exists.
// 更新(零值) 外部保证userID存在.
func (u *userDatabase) UpdateByMap(ctx context.Context, userID string, args map[string]interface{}) (err error) {
if err := u.userDB.UpdateByMap(ctx, userID, args); err != nil {
return err
@@ -141,7 +127,7 @@ func (u *userDatabase) UpdateByMap(ctx context.Context, userID string, args map[
return u.cache.DelUsersInfo(userID).ExecDel(ctx)
}
// Page Gets, returns no error if not found.
// 获取,如果没找到,不返回错误.
func (u *userDatabase) Page(
ctx context.Context,
pageNumber, showNumber int32,
@@ -149,7 +135,7 @@ func (u *userDatabase) Page(
return u.userDB.Page(ctx, pageNumber, showNumber)
}
// IsExist Does userIDs exist? As long as there is one, it will be true.
// userIDs是否存在 只要有一个存在就为true.
func (u *userDatabase) IsExist(ctx context.Context, userIDs []string) (exist bool, err error) {
users, err := u.userDB.Find(ctx, userIDs)
if err != nil {
@@ -161,53 +147,18 @@ func (u *userDatabase) IsExist(ctx context.Context, userIDs []string) (exist boo
return false, nil
}
// GetAllUserID Get all user IDs
func (u *userDatabase) GetAllUserID(ctx context.Context, pageNumber, showNumber int32) (userIDs []string, err error) {
return u.userDB.GetAllUserID(ctx, pageNumber, showNumber)
}
// CountTotal Get the total number of users
func (u *userDatabase) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
return u.userDB.CountTotal(ctx, before)
}
// CountRangeEverydayTotal Get the user increment in the range
func (u *userDatabase) CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) {
func (u *userDatabase) CountRangeEverydayTotal(
ctx context.Context,
start time.Time,
end time.Time,
) (map[string]int64, error) {
return u.userDB.CountRangeEverydayTotal(ctx, start, end)
}
//SubscribeOrCancelUsersStatus Subscribe or unsubscribe a user's presence status
func (u *userDatabase) SubscribeOrCancelUsersStatus(ctx context.Context, userID string, userIDs []string, genre int32) error {
var err error
if genre == constant.SubscriberUser {
err = u.mongoDB.AddSubscriptionList(ctx, userID, userIDs)
} else if genre == constant.Unsubscribe {
err = u.mongoDB.UnsubscriptionList(ctx, userID, userIDs)
}
return err
}
// GetAllSubscribeList Get a list of all subscriptions.
func (u *userDatabase) GetAllSubscribeList(ctx context.Context, userID string) ([]string, error) {
//TODO 获取所有订阅
return nil, nil
}
// GetSubscribedList Get all subscribed lists
func (u *userDatabase) GetSubscribedList(ctx context.Context, userID string) ([]string, error) {
//TODO 获取所有被订阅
return nil, nil
}
// GetUserStatus get user status
func (u *userDatabase) GetUserStatus(ctx context.Context, userIDs []string) ([]*user.OnlineStatus, error) {
onlineStatusList, err := u.cache.GetUserStatus(ctx, userIDs)
return onlineStatusList, err
}
// SetUserStatus Set the user status and save it in redis
func (u *userDatabase) SetUserStatus(ctx context.Context, list []*user.OnlineStatus) error {
return u.cache.SetUserStatus(ctx, list)
}
-4
View File
@@ -99,7 +99,3 @@ func (g *GroupGorm) CountRangeEverydayTotal(ctx context.Context, start time.Time
}
return v, nil
}
func (g *GroupGorm) FindNotDismissedGroup(ctx context.Context, groupIDs []string) (groups []*relation.GroupModel, err error) {
return groups, utils.Wrap(g.DB.Where("group_id in (?) and status != ?", groupIDs, constant.GroupStatusDismissed).Find(&groups).Error, "")
}
-1
View File
@@ -51,7 +51,6 @@ type GroupModelInterface interface {
UpdateMap(ctx context.Context, groupID string, args map[string]interface{}) (err error)
UpdateStatus(ctx context.Context, groupID string, status int32) (err error)
Find(ctx context.Context, groupIDs []string) (groups []*GroupModel, err error)
FindNotDismissedGroup(ctx context.Context, groupIDs []string) (groups []*GroupModel, err error)
Take(ctx context.Context, groupID string) (group *GroupModel, err error)
Search(
ctx context.Context,
-42
View File
@@ -1,42 +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 unrelation
import "context"
// SubscribeUser collection constant.
const (
SubscribeUser = "subscribe_user"
)
// UserModel collection structure.
type UserModel struct {
UserID string `bson:"user_id" json:"userID"`
UserIDList []string `bson:"user_id_list" json:"userIDList"`
}
func (UserModel) TableName() string {
return SubscribeUser
}
// UserModelInterface Operation interface of user mongodb.
type UserModelInterface interface {
// AddSubscriptionList Subscriber's handling of thresholds.
AddSubscriptionList(ctx context.Context, userID string, userIDList []string) error
// UnsubscriptionList Handling of unsubscribe.
UnsubscriptionList(ctx context.Context, userID string, userIDList []string) error
// RemoveSubscribedListFromUser Among the unsubscribed users, delete the user from the subscribed list.
RemoveSubscribedListFromUser(ctx context.Context, userID string, userIDList []string) error
}
-141
View File
@@ -1,141 +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 unrelation
import (
"context"
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/table/unrelation"
"github.com/OpenIMSDK/tools/utils"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"log"
)
// prefixes and suffixes.
const (
SubscriptionPrefix = "subscription_prefix"
SubscribedPrefix = "subscribed_prefix"
)
// MaximumSubscription Maximum number of subscriptions.
const (
MaximumSubscription = 3000
)
func NewUserMongoDriver(database *mongo.Database) unrelation.UserModelInterface {
return &UserMongoDriver{
userCollection: database.Collection(unrelation.SubscribeUser),
}
}
type UserMongoDriver struct {
userCollection *mongo.Collection
}
// AddSubscriptionList Subscriber's handling of thresholds.
func (u *UserMongoDriver) AddSubscriptionList(ctx context.Context, userID string, userIDList []string) error {
// Check the number of lists in the key.
filter := bson.M{SubscriptionPrefix + userID: bson.M{"$size": 1}}
result, err := u.userCollection.Find(context.Background(), filter)
if err != nil {
return err
}
var newUserIDList []string
for result.Next(context.Background()) {
err := result.Decode(&newUserIDList)
if err != nil {
log.Fatal(err)
}
}
// If the threshold is exceeded, pop out the previous MaximumSubscription - len(userIDList) and insert it.
if len(newUserIDList)+len(userIDList) > MaximumSubscription {
newUserIDList = newUserIDList[MaximumSubscription-len(userIDList):]
_, err := u.userCollection.UpdateOne(
ctx,
bson.M{"user_id": SubscriptionPrefix + userID},
bson.M{"$set": bson.M{"user_id_list": newUserIDList}},
)
if err != nil {
return err
}
//for i := 1; i <= MaximumSubscription-len(userIDList); i++ {
// _, err := u.userCollection.UpdateOne(
// ctx,
// bson.M{"user_id": SubscriptionPrefix + userID},
// bson.M{SubscriptionPrefix + userID: bson.M{"$pop": -1}},
// )
// if err != nil {
// return err
// }
//}
}
upsert := true
opts := &options.UpdateOptions{
Upsert: &upsert,
}
_, err = u.userCollection.UpdateOne(
ctx,
bson.M{"user_id": SubscriptionPrefix + userID},
bson.M{"$addToSet": bson.M{"user_id_list": bson.M{"$each": userIDList}}},
opts,
)
if err != nil {
return err
}
for _, user := range userIDList {
_, err = u.userCollection.UpdateOne(
ctx,
bson.M{"user_id": SubscribedPrefix + user},
bson.M{"$addToSet": bson.M{"user_id_list": userID}},
opts,
)
if err != nil {
return utils.Wrap(err, "transaction failed")
}
}
return nil
}
// UnsubscriptionList Handling of unsubscribe.
func (u *UserMongoDriver) UnsubscriptionList(ctx context.Context, userID string, userIDList []string) error {
_, err := u.userCollection.UpdateOne(
ctx,
bson.M{"user_id": SubscriptionPrefix + userID},
bson.M{"$pull": bson.M{"user_id_list": bson.M{"$in": userIDList}}},
)
if err != nil {
return err
}
err = u.RemoveSubscribedListFromUser(ctx, userID, userIDList)
if err != nil {
return err
}
return nil
}
// RemoveSubscribedListFromUser Among the unsubscribed users, delete the user from the subscribed list.
func (u *UserMongoDriver) RemoveSubscribedListFromUser(ctx context.Context, userID string, userIDList []string) error {
var newUserIDList []string
for _, value := range userIDList {
newUserIDList = append(newUserIDList, SubscribedPrefix+value)
}
_, err := u.userCollection.UpdateOne(
ctx,
bson.M{"user_id": bson.M{"$in": newUserIDList}},
bson.M{"$pull": bson.M{"user_id_list": userID}},
)
return utils.Wrap(err, "")
}
+12 -15
View File
@@ -37,24 +37,12 @@ function onCtrlC () {
exit 1
}
# Load environment variables from .env file
source ${OPENIM_ROOT}/.env
# Get the public internet IP address
internet_ip=$(curl ifconfig.me -s)
echo -e "${PURPLE_PREFIX}=========> Your public internet IP address is ${internet_ip} ${COLOR_SUFFIX} \n"
# Replace local IP address with the public IP address in .env file
if [ $API_URL == "http://127.0.0.1:10002/object/" ]; then
sed -i "s/127.0.0.1/${internet_ip}/" ${OPENIM_ROOT}/.env
fi
if [ $MINIO_ENDPOINT == "http://127.0.0.1:10005" ]; then
sed -i "s/127.0.0.1/${internet_ip}/" ${OPENIM_ROOT}/.env
fi
# Load environment variables from .env file
source ${OPENIM_ROOT}/.env
echo -e "${PURPLE_PREFIX}=========> Your minio endpoint is ${MINIO_ENDPOINT} ${COLOR_SUFFIX} \n"
@@ -71,6 +59,15 @@ echo -e "${PURPLE_PREFIX}=========> env_check.sh ${COLOR_SUFFIX} \n"
${SCRIPTS_ROOT}/env_check.sh
# Replace local IP address with the public IP address in .env file
if [ $API_URL == "http://127.0.0.1:10002/object/" ]; then
sed -i "s/127.0.0.1/${internet_ip}/" ${OPENIM_ROOT}/.env
fi
if [ $MINIO_ENDPOINT == "http://127.0.0.1:10005" ]; then
sed -i "s/127.0.0.1/${internet_ip}/" ${OPENIM_ROOT}/.env
fi
# Go back to the previous directory
cd ${OPENIM_ROOT}
@@ -82,4 +79,4 @@ else
docker compose up -d
fi
${SCRIPTS_ROOT}/docker_check_service.sh
${SCRIPTS_ROOT}/docker_check_service.sh
+2 -2
View File
@@ -17,7 +17,7 @@
#
GO := go
GO_SUPPORTED_VERSIONS ?= 1.18|1.19|1.20|1.21
GO_SUPPORTED_VERSIONS ?= 1.18|1.19|1.20
GO_LDFLAGS += -X $(VERSION_PACKAGE).gitVersion=$(GIT_TAG) \
-X $(VERSION_PACKAGE).gitCommit=$(GIT_COMMIT) \
@@ -204,4 +204,4 @@ go.clean:
## copyright.help: Show copyright help
.PHONY: go.help
go.help: scripts/make-rules/golang.mk
$(call smallhelp)
$(call smallhelp)