@ -16,6 +16,9 @@ package cache
import (
"context"
"encoding/json"
"github.com/OpenIMSDK/protocol/user"
"strconv"
"time"
"github.com/dtm-labs/rockscache"
@ -25,9 +28,12 @@ import (
)
const (
userExpireTime = time . Second * 60 * 60 * 12
userInfoKey = "USER_INFO:"
userGlobalRecvMsgOptKey = "USER_GLOBAL_RECV_MSG_OPT_KEY:"
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
)
type UserCache interface {
@ -38,10 +44,13 @@ 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
@ -54,6 +63,7 @@ func NewUserCacheRedis(
) UserCache {
rcClient := rockscache . NewClient ( rdb , options )
return & UserCacheRedis {
rdb : rdb ,
metaCache : NewMetaCacheRedis ( rcClient ) ,
userDB : userDB ,
expireTime : userExpireTime ,
@ -63,6 +73,7 @@ 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 ,
@ -145,3 +156,71 @@ 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
}