app-cloudep-permission-server/internal/repository/member_status.go

105 lines
2.9 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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,
}
}