Get user online status

pull/693/head
plutoyty 2 years ago
parent 4f9e7415d7
commit 28c3985d60

@ -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_user_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,10 @@ package cache
import ( import (
"context" "context"
"encoding/json"
"fmt"
"github.com/OpenIMSDK/protocol/user"
"strconv"
"time" "time"
"github.com/dtm-labs/rockscache" "github.com/dtm-labs/rockscache"
@ -25,9 +29,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 +45,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 +64,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 +74,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 +157,70 @@ 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 {
return nil, err
} else if err == redis.Nil {
// key or field does not exist
res = append(res, &user.OnlineStatus{
UserID: userID,
Status: 0,
PlatformID: -1,
})
fmt.Println("Field does not exist")
continue
}
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