77fa0cadd2
Co-authored-by: multica-agent <github@multica.ai>
82 lines
2.0 KiB
Go
82 lines
2.0 KiB
Go
package user
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/perfect-panel/server/internal/config"
|
|
"github.com/perfect-panel/server/internal/svc"
|
|
)
|
|
|
|
func clearAllSessions(ctx context.Context, svcCtx *svc.ServiceContext, userID int64) error {
|
|
userIDText := strconv.FormatInt(userID, 10)
|
|
sessionSet := make(map[string]struct{})
|
|
|
|
pattern := fmt.Sprintf("%s:*", config.SessionIdKey)
|
|
var cursor uint64
|
|
for {
|
|
keys, nextCursor, err := svcCtx.Redis.Scan(ctx, cursor, pattern, 200).Result()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, sessionKey := range keys {
|
|
value, err := svcCtx.Redis.Get(ctx, sessionKey).Result()
|
|
if err != nil || value != userIDText {
|
|
continue
|
|
}
|
|
sessionID := strings.TrimPrefix(sessionKey, config.SessionIdKey+":")
|
|
if sessionID == "" || strings.HasPrefix(sessionID, "detail:") {
|
|
continue
|
|
}
|
|
sessionSet[sessionID] = struct{}{}
|
|
}
|
|
cursor = nextCursor
|
|
if cursor == 0 {
|
|
break
|
|
}
|
|
}
|
|
|
|
if len(sessionSet) == 0 {
|
|
return nil
|
|
}
|
|
|
|
deviceKeySet := make(map[string]struct{})
|
|
devicePattern := fmt.Sprintf("%s:*", config.DeviceCacheKeyKey)
|
|
cursor = 0
|
|
for {
|
|
keys, nextCursor, err := svcCtx.Redis.Scan(ctx, cursor, devicePattern, 200).Result()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, deviceKey := range keys {
|
|
sessionID, err := svcCtx.Redis.Get(ctx, deviceKey).Result()
|
|
if err != nil {
|
|
continue
|
|
}
|
|
if _, exists := sessionSet[sessionID]; exists {
|
|
deviceKeySet[deviceKey] = struct{}{}
|
|
}
|
|
}
|
|
cursor = nextCursor
|
|
if cursor == 0 {
|
|
break
|
|
}
|
|
}
|
|
|
|
sessionsKey := fmt.Sprintf("%s%v", config.UserSessionsKeyPrefix, userID)
|
|
pipe := svcCtx.Redis.TxPipeline()
|
|
for sessionID := range sessionSet {
|
|
pipe.Del(ctx, fmt.Sprintf("%v:%v", config.SessionIdKey, sessionID))
|
|
pipe.Del(ctx, fmt.Sprintf("%s:detail:%s", config.SessionIdKey, sessionID))
|
|
pipe.ZRem(ctx, sessionsKey, sessionID)
|
|
}
|
|
pipe.Del(ctx, sessionsKey)
|
|
for deviceKey := range deviceKeySet {
|
|
pipe.Del(ctx, deviceKey)
|
|
}
|
|
_, err := pipe.Exec(ctx)
|
|
return err
|
|
}
|