fix(subscribe): invalidate user subscription cache when plan is updated
When administrators update subscription plan configurations (traffic limits,
nodes, speed limits, etc.), existing subscribers were not seeing the updated
settings immediately. This was caused by stale cache entries that were not
being invalidated.
The issue occurred because:
- User subscription queries cache the entire result including preloaded plan details
- Plan update/delete operations only cleared the plan's own cache keys
- User subscription cache keys (cache:user:subscribe:user:{userId}) remained stale
This fix ensures that when a subscription plan is updated or deleted, all
associated user subscription caches are properly invalidated by:
- Querying all active users subscribed to the plan
- Building cache keys for each affected user
- Clearing both plan and user subscription caches atomically
Users will now immediately see updated plan configurations without waiting
for cache expiration.
This commit is contained in:
parent
7d46b31866
commit
e215ffcae9
@ -119,13 +119,35 @@ func (m *defaultSubscribeModel) Update(ctx context.Context, data *Subscribe, tx
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return err
|
||||
}
|
||||
|
||||
// 获取所有使用该套餐的用户订阅缓存 key
|
||||
var userIds []int64
|
||||
err = m.QueryNoCacheCtx(ctx, &userIds, func(conn *gorm.DB, v interface{}) error {
|
||||
return conn.Table("user_subscribe").
|
||||
Where("subscribe_id = ? AND status IN (0, 1)", data.Id).
|
||||
Distinct("user_id").
|
||||
Pluck("user_id", &userIds).Error
|
||||
})
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return err
|
||||
}
|
||||
|
||||
// 构建用户订阅缓存 key 列表
|
||||
userSubscribeCacheKeys := make([]string, 0, len(userIds))
|
||||
for _, userId := range userIds {
|
||||
userSubscribeCacheKeys = append(userSubscribeCacheKeys, fmt.Sprintf("cache:user:subscribe:user:%d", userId))
|
||||
}
|
||||
|
||||
// 合并套餐缓存 key 和用户订阅缓存 key
|
||||
allCacheKeys := append(m.getCacheKeys(old), userSubscribeCacheKeys...)
|
||||
|
||||
err = m.ExecCtx(ctx, func(conn *gorm.DB) error {
|
||||
db := conn
|
||||
if len(tx) > 0 {
|
||||
db = tx[0]
|
||||
}
|
||||
return db.Save(data).Error
|
||||
}, m.getCacheKeys(old)...)
|
||||
}, allCacheKeys...)
|
||||
return err
|
||||
}
|
||||
|
||||
@ -137,13 +159,35 @@ func (m *defaultSubscribeModel) Delete(ctx context.Context, id int64, tx ...*gor
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// 获取所有使用该套餐的用户订阅缓存 key
|
||||
var userIds []int64
|
||||
err = m.QueryNoCacheCtx(ctx, &userIds, func(conn *gorm.DB, v interface{}) error {
|
||||
return conn.Table("user_subscribe").
|
||||
Where("subscribe_id = ? AND status IN (0, 1)", id).
|
||||
Distinct("user_id").
|
||||
Pluck("user_id", &userIds).Error
|
||||
})
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return err
|
||||
}
|
||||
|
||||
// 构建用户订阅缓存 key 列表
|
||||
userSubscribeCacheKeys := make([]string, 0, len(userIds))
|
||||
for _, userId := range userIds {
|
||||
userSubscribeCacheKeys = append(userSubscribeCacheKeys, fmt.Sprintf("cache:user:subscribe:user:%d", userId))
|
||||
}
|
||||
|
||||
// 合并套餐缓存 key 和用户订阅缓存 key
|
||||
allCacheKeys := append(m.getCacheKeys(data), userSubscribeCacheKeys...)
|
||||
|
||||
err = m.ExecCtx(ctx, func(conn *gorm.DB) error {
|
||||
db := conn
|
||||
if len(tx) > 0 {
|
||||
db = tx[0]
|
||||
}
|
||||
return db.Delete(&Subscribe{}, id).Error
|
||||
}, m.getCacheKeys(data)...)
|
||||
}, allCacheKeys...)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user