feat(session): 实现同平台抢登互踢功能,优化会话踢下线逻辑
新增同平台会话踢下线能力,将iOS/Android/mobile归为同一移动分组,web仅匹配web;扩展会话存储接口支持按平台、带原因踢除会话,同步更新集群广播逻辑与各调用点,统一传递踢下线原因参数
This commit is contained in:
+41
-2
@@ -304,13 +304,16 @@ func (ss *SessionStore) Shutdown() {
|
||||
}
|
||||
|
||||
// EvictUser terminates all sessions of a given user.
|
||||
func (ss *SessionStore) EvictUser(uid types.Uid, skipSid string) {
|
||||
func (ss *SessionStore) EvictUser(uid types.Uid, skipSid string, reason ...string) {
|
||||
ss.lock.Lock()
|
||||
defer ss.lock.Unlock()
|
||||
|
||||
// FIXME: this probably needs to be optimized. This may take very long time if the node hosts 100000 sessions.
|
||||
evicted := NoErrEvicted("", "", types.TimeNow())
|
||||
evicted.AsUser = uid.UserId()
|
||||
if len(reason) > 0 && reason[0] != "" {
|
||||
evicted.Ctrl.Params = map[string]any{"reason": reason[0]}
|
||||
}
|
||||
for _, s := range ss.sessCache {
|
||||
if s.uid == uid && !s.isMultiplex() && s.sid != skipSid {
|
||||
_, data := s.serialize(evicted)
|
||||
@@ -326,7 +329,7 @@ func (ss *SessionStore) EvictUser(uid types.Uid, skipSid string) {
|
||||
}
|
||||
|
||||
// EvictUserDevice terminates all sessions of a given user connected with a device.
|
||||
func (ss *SessionStore) EvictUserDevice(uid types.Uid, deviceID string) int {
|
||||
func (ss *SessionStore) EvictUserDevice(uid types.Uid, deviceID string, reason ...string) int {
|
||||
ss.lock.Lock()
|
||||
defer ss.lock.Unlock()
|
||||
|
||||
@@ -335,6 +338,9 @@ func (ss *SessionStore) EvictUserDevice(uid types.Uid, deviceID string) int {
|
||||
}
|
||||
evicted := NoErrEvicted("", "", types.TimeNow())
|
||||
evicted.AsUser = uid.UserId()
|
||||
if len(reason) > 0 && reason[0] != "" {
|
||||
evicted.Ctrl.Params = map[string]any{"reason": reason[0]}
|
||||
}
|
||||
count := 0
|
||||
for _, s := range ss.sessCache {
|
||||
if s.uid == uid && s.deviceID == deviceID && !s.isMultiplex() {
|
||||
@@ -352,6 +358,39 @@ func (ss *SessionStore) EvictUserDevice(uid types.Uid, deviceID string) int {
|
||||
return count
|
||||
}
|
||||
|
||||
// EvictUserPlatform terminates all sessions of a given user in the same eviction
|
||||
// platform group, keeping the session identified by skipSid (e.g. the new login
|
||||
// which triggers the eviction). ios/android/mobile are treated as one mobile
|
||||
// group (顶号互踢); web only matches web.
|
||||
func (ss *SessionStore) EvictUserPlatform(uid types.Uid, platf, skipSid string, reason ...string) int {
|
||||
ss.lock.Lock()
|
||||
defer ss.lock.Unlock()
|
||||
|
||||
if uid.IsZero() || platf == "" {
|
||||
return 0
|
||||
}
|
||||
evicted := NoErrEvicted("", "", types.TimeNow())
|
||||
evicted.AsUser = uid.UserId()
|
||||
if len(reason) > 0 && reason[0] != "" {
|
||||
evicted.Ctrl.Params = map[string]any{"reason": reason[0]}
|
||||
}
|
||||
count := 0
|
||||
for _, s := range ss.sessCache {
|
||||
if s.uid == uid && sameEvictPlatform(s.platf, platf) && !s.isMultiplex() && s.sid != skipSid {
|
||||
_, data := s.serialize(evicted)
|
||||
s.stopSession(data)
|
||||
delete(ss.sessCache, s.sid)
|
||||
if s.proto == LPOLL {
|
||||
ss.lru.Remove(s.lpTracker)
|
||||
}
|
||||
count++
|
||||
}
|
||||
}
|
||||
|
||||
statsSet("LiveSessions", int64(len(ss.sessCache)))
|
||||
return count
|
||||
}
|
||||
|
||||
// NodeRestarted removes stale sessions from a restarted cluster node.
|
||||
// - nodeName is the name of affected node
|
||||
// - fingerprint is the new fingerprint of the node.
|
||||
|
||||
Reference in New Issue
Block a user