123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- package repository
- import (
- "context"
- "fmt"
- "github.com/redis/go-redis/v9"
- "strconv"
- "time"
- )
- // PlanListType 定义了要操作的套餐列表类型
- type PlanListType string
- const (
- // ClosedPlansList 代表已关闭的套餐列表 (使用 Redis Set)
- ClosedPlansList PlanListType = "closed"
- // ExpiringSoonPlansList 代表即将过期的套餐列表 (使用 Redis Sorted Set)
- ExpiringSoonPlansList PlanListType = "expiring_soon"
- )
- // ExpiredRepository 定义了与过期套餐相关的操作接口
- type ExpiredRepository interface {
- // AddPlans 将一个或多个套餐ID添加到指定的列表中
- AddPlans(ctx context.Context, listType PlanListType, planIds ...int64) error
- // RemovePlans 从指定的列表中移除一个或多个套餐ID
- RemovePlans(ctx context.Context, listType PlanListType, planIds ...int64) error
- // GetAllPlanIds 获取指定列表中的所有套餐ID
- GetAllPlanIds(ctx context.Context, listType PlanListType) ([]int64, error)
- // IsPlanInList 检查一个套餐ID是否存在于指定的列表中
- IsPlanInList(ctx context.Context, listType PlanListType, planId int64) (bool, error)
- }
- func NewExpiredRepository(
- repository *Repository,
- ) ExpiredRepository {
- return &expiredRepository{
- Repository: repository,
- }
- }
- type expiredRepository struct {
- *Repository
- }
- // Key的前缀,用于标识所有已关闭套餐的Key
- // closePlansKey 用于存储所有已关闭套餐ID的Set
- const closePlansKey = "waf:closed_plans"
- // expiringSoonPlansKey 用于存储7天后过期套餐ID的Sorted Set
- // Score: 过期时间戳, Value: planId
- const expiringSoonPlansKey = "waf:expiring_soon_plans"
- // AddPlans 将一个或多个套餐ID添加到指定的列表中
- func (r *expiredRepository) AddPlans(ctx context.Context, listType PlanListType, planIds ...int64) error {
- if len(planIds) == 0 {
- return nil
- }
- switch listType {
- case ClosedPlansList:
- members := make([]interface{}, len(planIds))
- for i, id := range planIds {
- members[i] = id
- }
- return r.Rdb.SAdd(ctx, closePlansKey, members...).Err()
- case ExpiringSoonPlansList:
- // Score 代表套餐的实际过期时间戳,用于后续查询
- expirationTimestamp := float64(time.Now().Add(7 * 24 * time.Hour).Unix())
- members := make([]redis.Z, len(planIds))
- for i, id := range planIds {
- members[i] = redis.Z{
- Score: expirationTimestamp,
- Member: id,
- }
- }
- return r.Rdb.ZAdd(ctx, expiringSoonPlansKey, members...).Err()
- default:
- return fmt.Errorf("未知的列表类型: %s", listType)
- }
- }
- // RemovePlans 从指定的列表中移除一个或多个套餐ID
- func (r *expiredRepository) RemovePlans(ctx context.Context, listType PlanListType, planIds ...int64) error {
- if len(planIds) == 0 {
- return nil
- }
- members := make([]interface{}, len(planIds))
- for i, id := range planIds {
- members[i] = id
- }
- switch listType {
- case ClosedPlansList:
- return r.Rdb.SRem(ctx, closePlansKey, members...).Err()
- case ExpiringSoonPlansList:
- return r.Rdb.ZRem(ctx, expiringSoonPlansKey, members...).Err()
- default:
- return fmt.Errorf("未知的列表类型: %s", listType)
- }
- }
- // GetAllPlanIds 获取指定列表中的所有套餐ID
- func (r *expiredRepository) GetAllPlanIds(ctx context.Context, listType PlanListType) ([]int64, error) {
- var members []string
- var err error
- switch listType {
- case ClosedPlansList:
- members, err = r.Rdb.SMembers(ctx, closePlansKey).Result()
- case ExpiringSoonPlansList:
- members, err = r.Rdb.ZRange(ctx, expiringSoonPlansKey, 0, -1).Result()
- default:
- return nil, fmt.Errorf("未知的列表类型: %s", listType)
- }
- if err != nil {
- return nil, err
- }
- planIds := make([]int64, len(members))
- for i, memberStr := range members {
- id, err := strconv.ParseInt(memberStr, 10, 64)
- if err != nil {
- return nil, fmt.Errorf("无法解析套餐ID '%s': %w", memberStr, err)
- }
- planIds[i] = id
- }
- return planIds, nil
- }
- // IsPlanInList 检查一个套餐ID是否存在于指定的列表中
- func (r *expiredRepository) IsPlanInList(ctx context.Context, listType PlanListType, planId int64) (bool, error) {
- switch listType {
- case ClosedPlansList:
- return r.Rdb.SIsMember(ctx, closePlansKey, planId).Result()
- case ExpiringSoonPlansList:
- _, err := r.Rdb.ZScore(ctx, expiringSoonPlansKey, strconv.FormatInt(planId, 10)).Result()
- if err == redis.Nil {
- return false, nil
- }
- return err == nil, err
- default:
- return false, fmt.Errorf("未知的列表类型: %s", listType)
- }
- }
|