package repository import ( "app-cloudep-permission-server/internal/domain/repository" "code.30cm.net/digimon/library-go/utils/invited_code" "context" "fmt" "github.com/zeromicro/go-zero/core/stores/redis" ) type MemberOnlineStatusRepositoryParam struct { Store *redis.Redis `name:"redis"` } type memberOnlineStatusRepository struct { store *redis.Redis } // 使用 UID 計算 Bitmap 的 offset func (t *memberOnlineStatusRepository) uidToOffset(uid string) (int64, error) { converter := invited_code.MustConverter(10, invited_code.DefaultCodeLen, invited_code.ConvertTable) // 將 UID 轉換為整數型,並減去基礎 UID (1000000) uidInt, err := converter.DecodeFromCode(uid) if err != nil { return 0, fmt.Errorf("invalid UID: %w", err) } // 以 1000000 作為基準 baseUID := invited_code.InitAutoId if uidInt < int64(baseUID) { return 0, fmt.Errorf("UID smaller than base: %d", baseUID) } return uidInt - int64(baseUID), nil } func (t *memberOnlineStatusRepository) SetMemberOnline(ctx context.Context, uid string) (bool, error) { offset, err := t.uidToOffset(uid) if err != nil { return false, err } // 使用 SET BIT 設置對應的位為 1 _, err = t.store.SetBit("member_status", offset, 1) if err != nil { return false, fmt.Errorf("failed to set member online: %w", err) } return true, nil } func (t *memberOnlineStatusRepository) SetMemberOffline(ctx context.Context, uid string) (bool, error) { offset, err := t.uidToOffset(uid) if err != nil { return false, err } // 使用 SET BIT 設置對應的位為 1 _, err = t.store.SetBit("member_status", offset, 0) if err != nil { return false, fmt.Errorf("failed to set member offline: %w", err) } return true, nil } func (t *memberOnlineStatusRepository) IsMemberOnline(ctx context.Context, uid string) (bool, error) { offset, err := t.uidToOffset(uid) if err != nil { return false, err } // 使用 GET BIT 獲取對應的位,1 表示在線,0 表示離線 status, err := t.store.GetBit("member_status", offset) if err != nil { return false, fmt.Errorf("failed to get member status: %w", err) } return status == 1, nil } func (t *memberOnlineStatusRepository) QueryMemberOnlineList(ctx context.Context, uids []string) ([]repository.MemberOnlineStatusResp, error) { statusMap := make([]repository.MemberOnlineStatusResp, 0, len(uids)) // 遍歷所有用戶的 UID,查詢他們的在線狀態 for _, uid := range uids { isOnline, err := t.IsMemberOnline(ctx, uid) if err != nil { return nil, fmt.Errorf("failed to query member status for UID %s: %w", uid, err) } statusMap = append(statusMap, repository.MemberOnlineStatusResp{ UID: uid, Status: isOnline, }) } return statusMap, nil } func NewMemberOnlineStatusRepository(param MemberOnlineStatusRepositoryParam) repository.MemberOnlineStatusRepository { return &memberOnlineStatusRepository{ store: param.Store, } }