Get user online status (#693)

* Resolving code conflicts after project directory changes and Add subscribe and unsubscribe mongodb operations

* Organize and update module dependencies

* Get user online status

* Get user online status

* Get user online status
pull/703/head
pluto 12 months ago committed by GitHub
parent 8979b9dce1
commit e24b0e2114
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -81,6 +81,7 @@ func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.Unive
userRouterGroup.POST("/get_users_online_token_detail", ParseToken, u.GetUsersOnlineTokenDetail) userRouterGroup.POST("/get_users_online_token_detail", ParseToken, u.GetUsersOnlineTokenDetail)
userRouterGroup.POST("/subscribe_users_status", ParseToken, u.UnSubscriberStatus) userRouterGroup.POST("/subscribe_users_status", ParseToken, u.UnSubscriberStatus)
userRouterGroup.POST("/unsubscribe_users_status", ParseToken, u.UnSubscriberStatus) userRouterGroup.POST("/unsubscribe_users_status", ParseToken, u.UnSubscriberStatus)
userRouterGroup.POST("/get_users_status", ParseToken, u.GetUserStatus)
} }
// friend routing group // friend routing group

@ -194,3 +194,7 @@ func (u *UserApi) SubscriberStatus(c *gin.Context) {
func (u *UserApi) UnSubscriberStatus(c *gin.Context) { func (u *UserApi) UnSubscriberStatus(c *gin.Context) {
a2r.Call(user.UserClient.SubscribeOrCancelUsersStatus, u.Client, c) a2r.Call(user.UserClient.SubscribeOrCancelUsersStatus, u.Client, c)
} }
func (u *UserApi) GetUserStatus(c *gin.Context) {
a2r.Call(user.UserClient.GetUserStatus, u.Client, c)
}

@ -261,11 +261,18 @@ func (s *userServer) SubscribeOrCancelUsersStatus(ctx context.Context, req *pbus
} }
func (s *userServer) GetUserStatus(ctx context.Context, req *pbuser.GetUserStatusReq) (resp *pbuser.GetUserStatusResp, err error) { func (s *userServer) GetUserStatus(ctx context.Context, req *pbuser.GetUserStatusReq) (resp *pbuser.GetUserStatusResp, err error) {
//TODO implement me //TODO 是否加一个参数校验-判断req.userID的数量每一个获取加一个限制一次请求限制500
panic("implement me") 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) { func (s *userServer) SetUserStatus(ctx context.Context, req *pbuser.SetUserStatusReq) (resp *pbuser.SetUserStatusResp, err error) {
//TODO implement me err = s.UserDatabase.SetUserStatus(ctx, req.StatusList)
panic("implement me") if err != nil {
return nil, err
}
return &pbuser.SetUserStatusResp{}, nil
} }

@ -16,6 +16,9 @@ package cache
import ( import (
"context" "context"
"encoding/json"
"github.com/OpenIMSDK/protocol/user"
"strconv"
"time" "time"
"github.com/dtm-labs/rockscache" "github.com/dtm-labs/rockscache"
@ -25,9 +28,12 @@ import (
) )
const ( const (
userExpireTime = time.Second * 60 * 60 * 12 userExpireTime = time.Second * 60 * 60 * 12
userInfoKey = "USER_INFO:" userInfoKey = "USER_INFO:"
userGlobalRecvMsgOptKey = "USER_GLOBAL_RECV_MSG_OPT_KEY:" userGlobalRecvMsgOptKey = "USER_GLOBAL_RECV_MSG_OPT_KEY:"
olineStatusKey = "ONLINE_STATUS:"
userOlineStatusExpireTime = time.Second * 60 * 60 * 24
statusMod = 500
) )
type UserCache interface { type UserCache interface {
@ -38,10 +44,13 @@ type UserCache interface {
DelUsersInfo(userIDs ...string) UserCache DelUsersInfo(userIDs ...string) UserCache
GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error) GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error)
DelUsersGlobalRecvMsgOpt(userIDs ...string) UserCache DelUsersGlobalRecvMsgOpt(userIDs ...string) UserCache
GetUserStatus(ctx context.Context, userIDs []string) ([]*user.OnlineStatus, error)
SetUserStatus(ctx context.Context, list []*user.OnlineStatus) error
} }
type UserCacheRedis struct { type UserCacheRedis struct {
metaCache metaCache
rdb redis.UniversalClient
userDB relationTb.UserModelInterface userDB relationTb.UserModelInterface
expireTime time.Duration expireTime time.Duration
rcClient *rockscache.Client rcClient *rockscache.Client
@ -54,6 +63,7 @@ func NewUserCacheRedis(
) UserCache { ) UserCache {
rcClient := rockscache.NewClient(rdb, options) rcClient := rockscache.NewClient(rdb, options)
return &UserCacheRedis{ return &UserCacheRedis{
rdb: rdb,
metaCache: NewMetaCacheRedis(rcClient), metaCache: NewMetaCacheRedis(rcClient),
userDB: userDB, userDB: userDB,
expireTime: userExpireTime, expireTime: userExpireTime,
@ -63,6 +73,7 @@ func NewUserCacheRedis(
func (u *UserCacheRedis) NewCache() UserCache { func (u *UserCacheRedis) NewCache() UserCache {
return &UserCacheRedis{ return &UserCacheRedis{
rdb: u.rdb,
metaCache: NewMetaCacheRedis(u.rcClient, u.metaCache.GetPreDelKeys()...), metaCache: NewMetaCacheRedis(u.rcClient, u.metaCache.GetPreDelKeys()...),
userDB: u.userDB, userDB: u.userDB,
expireTime: u.expireTime, expireTime: u.expireTime,
@ -145,3 +156,71 @@ func (u *UserCacheRedis) DelUsersGlobalRecvMsgOpt(userIDs ...string) UserCache {
cache.AddKeys(keys...) cache.AddKeys(keys...)
return cache 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
}

@ -18,6 +18,7 @@ import (
"context" "context"
unRelationTb "github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/table/unrelation" unRelationTb "github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/table/unrelation"
"github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/protocol/user"
"time" "time"
"github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/cache" "github.com/OpenIMSDK/Open-IM-Server/pkg/common/db/cache"
@ -56,6 +57,10 @@ type UserDatabase interface {
GetAllSubscribeList(ctx context.Context, userID string) ([]string, error) GetAllSubscribeList(ctx context.Context, userID string) ([]string, error)
// GetSubscribedList Get all subscribed lists // GetSubscribedList Get all subscribed lists
GetSubscribedList(ctx context.Context, userID string) ([]string, error) 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 { type userDatabase struct {
@ -195,3 +200,14 @@ func (u *userDatabase) GetSubscribedList(ctx context.Context, userID string) ([]
//TODO 获取所有被订阅 //TODO 获取所有被订阅
return nil, nil 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)
}

Loading…
Cancel
Save