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

105 lines
2.9 KiB
Go
Raw Permalink Normal View History

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