All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 14m13s
新增 000228 成对迁移 tb_polling_priority_item:卡、任务类型、状态、触发类型、来源订单/套餐使用记录、
触发次数与来源集合、尝试次数、失败原因、人工原因与操作者、店铺快照与各时间列;以活动项部分唯一索引
uq_polling_priority_item_active(仅 deleted_at IS NULL AND status IN ('pending','processing') 占键位)
表达「同卡同任务类型至多一条活动项」,另有状态/时间索引与全列注释;down 守卫在存在活动项或未终态行时
拒绝回滚并给出中文原因。
新增优先轮询请求可靠事件 polling.priority.requested(载荷版本 v1、事件键前缀 prio:)与消费者:只在原
业务事务内追加、幂等键稳定;消费者按卡 × 纳入任务类型(realname/carddata/card_status/package)逐条
建项并在提交后下发执行提示,重复投递只合并触发次数、来源集合与最近触发时间,不新建行也不重复调用。
触发点为四类自动场景 purchase_activated / renewal_activated(按同载体更早套餐使用记录判定)/
queue_activated / addon_activated 与「无有效套餐」no_valid_package(仅在普通套餐轮询来源且存在待生效
套餐使用记录时追加;事件通道显式拒绝 manual_trigger);入队对象恒为卡,绑定设备资产在触发事务内冻结
在用卡快照逐卡建项,不使用设备当前卡槽口径。
轮询共享基类新增认领接缝:四个 Handler(realname/carddata/card_status/package)在并发信号量之后、调用
上游之前探测活动项——待执行条件认领、执行中且 90 秒租约未到期则跳过并延后、无活动项时行为与既有完全
等价;超租约允许相邻执行接管,尝试次数只在真正发起执行后累加,未达上限(3)回到活动态按既有间隔重排,
达上限或业务校验类失败进入失败终态并保留可安全展示原因;执行前校验卡自身与绑定设备的轮询开关。未引入
通用卡级锁与 Redis 活动标记,分片队列的出队、入队与移除路径未改动。
提示通道按任务类型独立键(polling:priority:{taskType}),与既有手动触发队列分离;调度器在同一周期内先
排空优先提示、再排空手动触发队列,提示排空不受分片背压跳过影响;未新建调度设施或异步任务类型。
新增人工优先入队与只读查询三条路由 POST /api/admin/polling-priority-items、
GET /api/admin/polling-priority-items、GET /api/admin/polling-priority-items/:id:人工入队复用既有轮询
权限判定(抽取为同包共享函数),原因必填,不受每日 500 次上限与 24 小时去重约束,重复抑制由活动项合并
承担;读侧按店铺快照下推数据范围,越权与不存在不可区分,不提供优先级分级、有效期或人工重触发入口。
新增 7 个审计动作(enqueue/claim/fail/retry/complete/dequeue/manual_denied)与资源
polling_priority_item,并按(操作者类型,来源)注册,人工侧与 Worker 侧均通过来源校验。
同步 OpenAPI 文档装配三处与路由注册;归档 Change 至
openspec/changes/archive/2026-09-17-add-priority-polling-queue/ 并同步主 Spec(新增
priority-polling-queue、polling-operations 追加单次执行互斥 Requirement 与三条路由索引)与上下文健康
证据(requirement-evidence 150 行、入口矩阵 http 403 / async 56)。
本机验证:junhong_cmp_test 与隔离 Redis DB 15,未连生产、未启动 Worker/API、未调用运营商上游;迁移
up/down/up 与 down 守卫实测(含 dirty=true 记账口径与 force 恢复),A–F 批 94 PASS、接缝 63 PASS、
提示通道 12 PASS、清理零残留 20 PASS。成功路径 Complete、真并发互斥、尝试上限第 3 次判定、HTTP 层权限
矩阵、通道阈值持锁复机边界与三类生效触发点生产集成留待测试部署验证(见
docs/verification/add-priority-polling-queue-verification.md 第 4 节)。自动化测试按项目决策为 N/A,
未新增 *_test.go。
580 lines
23 KiB
Go
580 lines
23 KiB
Go
package constants
|
||
|
||
import "fmt"
|
||
|
||
// ========================================
|
||
// 认证相关 Redis Key
|
||
// ========================================
|
||
|
||
// RedisAuthTokenKey 生成访问令牌的 Redis 键
|
||
// 用途:存储用户 access token 信息
|
||
// 过期时间:24 小时(可配置)
|
||
func RedisAuthTokenKey(token string) string {
|
||
return fmt.Sprintf("auth:token:%s", token)
|
||
}
|
||
|
||
// RedisAgentOpenAPINonceKey 生成代理开放接口 nonce 防重放 Redis 键
|
||
// 用途:记录账号在签名时间窗内已使用的随机串,防止重复请求
|
||
// 过期时间:与开放接口签名时间窗一致
|
||
func RedisAgentOpenAPINonceKey(account, nonce string) string {
|
||
return fmt.Sprintf("agent_open_api:nonce:%s:%s", account, nonce)
|
||
}
|
||
|
||
// RedisRefreshTokenKey 生成刷新令牌的 Redis 键
|
||
// 用途:存储用户 refresh token 信息
|
||
// 过期时间:7 天(可配置)
|
||
func RedisRefreshTokenKey(token string) string {
|
||
return fmt.Sprintf("auth:refresh:%s", token)
|
||
}
|
||
|
||
// RedisUserTokensKey 生成用户令牌列表的 Redis 键
|
||
// 用途:维护用户的所有有效 token 列表(Set 结构)
|
||
// 过期时间:7 天(可配置)
|
||
func RedisUserTokensKey(userID uint) string {
|
||
return fmt.Sprintf("auth:user:%d:tokens", userID)
|
||
}
|
||
|
||
// RedisRateLimitKey 生成限流的 Redis 键
|
||
func RedisRateLimitKey(ip string) string {
|
||
return fmt.Sprintf("ratelimit:%s", ip)
|
||
}
|
||
|
||
// RedisTaskLockKey 生成任务锁的 Redis 键
|
||
// 用途:幂等性控制,防止重复执行
|
||
// 过期时间:24 小时
|
||
func RedisTaskLockKey(requestID string) string {
|
||
return fmt.Sprintf("task:lock:%s", requestID)
|
||
}
|
||
|
||
// RedisTaskStatusKey 生成任务状态的 Redis 键
|
||
// 用途:存储任务执行状态
|
||
// 过期时间:7 天
|
||
func RedisTaskStatusKey(taskID string) string {
|
||
return fmt.Sprintf("task:status:%s", taskID)
|
||
}
|
||
|
||
// RedisExportDispatchLockKey 生成导出 dispatch 执行锁的 Redis 键
|
||
// 用途:防止同一导出任务并发执行 dispatch
|
||
// 过期时间:5 分钟
|
||
func RedisExportDispatchLockKey(taskID uint) string {
|
||
return fmt.Sprintf("export:dispatch:lock:%d", taskID)
|
||
}
|
||
|
||
// RedisExportShardLockKey 生成导出分片执行锁的 Redis 键
|
||
// 用途:防止同一分片被多个 Worker 并发处理
|
||
// 过期时间:10 分钟
|
||
func RedisExportShardLockKey(taskID, shardID uint) string {
|
||
return fmt.Sprintf("export:shard:lock:%d:%d", taskID, shardID)
|
||
}
|
||
|
||
// RedisExportFinalizeLockKey 生成导出 finalize 执行锁的 Redis 键
|
||
// 用途:防止同一导出任务并发执行 finalize
|
||
// 过期时间:2 分钟
|
||
func RedisExportFinalizeLockKey(taskID uint) string {
|
||
return fmt.Sprintf("export:finalize:lock:%d", taskID)
|
||
}
|
||
|
||
// RedisShopSubordinatesKey 生成店铺下级 ID 列表的 Redis 键
|
||
// 用途:缓存递归查询的下级店铺 ID 列表
|
||
// 过期时间:30 分钟
|
||
func RedisShopSubordinatesKey(shopID uint) string {
|
||
return fmt.Sprintf("shop:subordinates:%d", shopID)
|
||
}
|
||
|
||
// ========================================
|
||
// 个人客户认证相关 Redis Key
|
||
// ========================================
|
||
|
||
// RedisPersonalCustomerTokenKey 生成个人客户登录令牌的 Redis 键
|
||
// 用途:有状态 JWT,存储当前有效 token 字符串,支持服务端主动失效
|
||
// 过期时间:与 JWT 过期时间一致
|
||
func RedisPersonalCustomerTokenKey(customerID uint) string {
|
||
return fmt.Sprintf("personal:customer:token:%d", customerID)
|
||
}
|
||
|
||
// RedisClientAuthRateLimitIPKey 生成 C 端资产验证 IP 限流键
|
||
// 用途:A1 接口 IP 级限频 30 次/分钟
|
||
// 过期时间:1 分钟
|
||
func RedisClientAuthRateLimitIPKey(ip string) string {
|
||
return fmt.Sprintf("client:auth:ratelimit:ip:%s", ip)
|
||
}
|
||
|
||
// RedisClientSendCodePhoneLimitKey 生成验证码手机号冷却键
|
||
// 用途:A4 接口同手机号 60 秒冷却
|
||
// 过期时间:60 秒
|
||
func RedisClientSendCodePhoneLimitKey(phone string) string {
|
||
return fmt.Sprintf("client:auth:sendcode:phone:limit:%s", phone)
|
||
}
|
||
|
||
// RedisClientSendCodeIPHourKey 生成验证码 IP 小时限流键
|
||
// 用途:A4 接口同 IP 每小时 20 次
|
||
// 过期时间:1 小时
|
||
func RedisClientSendCodeIPHourKey(ip string) string {
|
||
return fmt.Sprintf("client:auth:sendcode:ip:hour:%s", ip)
|
||
}
|
||
|
||
// RedisClientSendCodePhoneDayKey 生成验证码手机号日限流键
|
||
// 用途:A4 接口同手机号每日 10 次
|
||
// 过期时间:当日剩余时间
|
||
func RedisClientSendCodePhoneDayKey(phone string) string {
|
||
return fmt.Sprintf("client:auth:sendcode:phone:day:%s", phone)
|
||
}
|
||
|
||
// ========================================
|
||
// 验证码相关 Redis Key
|
||
// ========================================
|
||
|
||
// RedisVerificationCodeKey 生成验证码的 Redis 键
|
||
// 用途:存储手机验证码
|
||
// 过期时间:5 分钟
|
||
func RedisVerificationCodeKey(phone string) string {
|
||
return fmt.Sprintf("verification:code:%s", phone)
|
||
}
|
||
|
||
// RedisVerificationCodeLimitKey 生成验证码发送频率限制的 Redis 键
|
||
// 用途:限制验证码发送频率
|
||
// 过期时间:60 秒
|
||
func RedisVerificationCodeLimitKey(phone string) string {
|
||
return fmt.Sprintf("verification:limit:%s", phone)
|
||
}
|
||
|
||
// ========================================
|
||
// 钱包相关 Redis Key
|
||
// ========================================
|
||
|
||
// RedisWalletLockKey 生成钱包操作锁的 Redis 键
|
||
// 用途:钱包余额变更时的分布式锁,防止并发冲突
|
||
// 过期时间:10 秒
|
||
func RedisWalletLockKey(walletID uint) string {
|
||
return fmt.Sprintf("wallet:lock:%d", walletID)
|
||
}
|
||
|
||
// RedisWalletBalanceKey 生成钱包余额缓存的 Redis 键
|
||
// 用途:缓存钱包余额,减少数据库查询
|
||
// 过期时间:5 分钟
|
||
func RedisWalletBalanceKey(walletID uint) string {
|
||
return fmt.Sprintf("wallet:balance:%d", walletID)
|
||
}
|
||
|
||
// RedisRechargeOrderKey 生成充值订单缓存的 Redis 键
|
||
// 用途:充值订单状态查询缓存
|
||
// 过期时间:1 小时
|
||
func RedisRechargeOrderKey(rechargeNo string) string {
|
||
return fmt.Sprintf("recharge:order:%s", rechargeNo)
|
||
}
|
||
|
||
// RedisWalletTransactionKey 生成钱包交易幂等性的 Redis 键
|
||
// 用途:防止重复交易
|
||
// 过期时间:24 小时
|
||
func RedisWalletTransactionKey(requestID string) string {
|
||
return fmt.Sprintf("wallet:transaction:%s", requestID)
|
||
}
|
||
|
||
// ========================================
|
||
// 标签相关 Redis Key
|
||
// ========================================
|
||
|
||
// RedisTagCacheKey 生成标签缓存的 Redis 键
|
||
// 用途:缓存热门标签列表
|
||
// 过期时间:1 小时
|
||
func RedisTagCacheKey() string {
|
||
return "tag:cache:list"
|
||
}
|
||
|
||
// RedisResourceTagsKey 生成资源标签关联缓存的 Redis 键
|
||
// 用途:缓存资源的标签列表
|
||
// 过期时间:30 分钟
|
||
func RedisResourceTagsKey(resourceType string, resourceID uint) string {
|
||
return fmt.Sprintf("resource:tags:%s:%d", resourceType, resourceID)
|
||
}
|
||
|
||
// ========================================
|
||
// 权限相关 Redis Key
|
||
// ========================================
|
||
|
||
// RedisUserPermissionsKey 生成用户权限列表缓存的 Redis 键
|
||
// 用途:缓存用户的所有权限列表(包含 permCode 和 platform 信息)
|
||
// 格式:JSON 数组 [{"perm_code":"user:list","platform":"web"},...]
|
||
// 过期时间:30 分钟
|
||
func RedisUserPermissionsKey(userID uint) string {
|
||
return fmt.Sprintf("permission:user:%d:list", userID)
|
||
}
|
||
|
||
// ========================================
|
||
// 佣金统计相关 Redis Key
|
||
// ========================================
|
||
|
||
// RedisCommissionStatsKey 生成佣金统计缓存的 Redis 键
|
||
// 用途:缓存梯度返佣统计数据(Hash 结构: total_count, total_amount)
|
||
// 过期时间:周期结束后 7 天
|
||
func RedisCommissionStatsKey(allocationID uint, period string) string {
|
||
return fmt.Sprintf("commission:stats:%d:%s", allocationID, period)
|
||
}
|
||
|
||
// RedisCommissionStatsLockKey 生成佣金统计同步锁的 Redis 键
|
||
// 用途:定时同步任务的分布式锁,防止并发同步
|
||
// 过期时间:5 分钟
|
||
func RedisCommissionStatsLockKey() string {
|
||
return "commission:stats:sync:lock"
|
||
}
|
||
|
||
// ========================================
|
||
// 系列分配相关 Redis Key
|
||
// ========================================
|
||
|
||
// RedisShopSeriesAllocationKey 生成店铺系列分配缓存的 Redis 键
|
||
// 用途:缓存店铺+系列的分配配置
|
||
// 过期时间:30 分钟
|
||
func RedisShopSeriesAllocationKey(shopID, seriesID uint) string {
|
||
return fmt.Sprintf("shop_series_alloc:%d:%d", shopID, seriesID)
|
||
}
|
||
|
||
// ========================================
|
||
// 轮询系统相关 Redis Key
|
||
// ========================================
|
||
|
||
// RedisPollingQueueRealnameKey 生成实名检查轮询队列的 Redis 键
|
||
// 用途:Sorted Set 存储待检查实名状态的卡,Score 为下次检查的 Unix 时间戳
|
||
// 过期时间:无(持久化数据)
|
||
func RedisPollingQueueRealnameKey() string {
|
||
return "polling:queue:realname"
|
||
}
|
||
|
||
// RedisPollingQueueCarddataKey 生成卡流量检查轮询队列的 Redis 键
|
||
// 用途:Sorted Set 存储待检查流量的卡,Score 为下次检查的 Unix 时间戳
|
||
// 过期时间:无(持久化数据)
|
||
func RedisPollingQueueCarddataKey() string {
|
||
return "polling:queue:carddata"
|
||
}
|
||
|
||
// RedisPollingQueuePackageKey 生成套餐检查轮询队列的 Redis 键
|
||
// 用途:Sorted Set 存储待检查套餐的卡,Score 为下次检查的 Unix 时间戳
|
||
// 过期时间:无(持久化数据)
|
||
func RedisPollingQueuePackageKey() string {
|
||
return "polling:queue:package"
|
||
}
|
||
|
||
// RedisPollingCardInfoKey 生成卡信息缓存的 Redis 键
|
||
// 用途:Hash 存储卡的基本信息和轮询状态
|
||
// 过期时间:7 天
|
||
func RedisPollingCardInfoKey(cardID uint) string {
|
||
return fmt.Sprintf("polling:card:%d", cardID)
|
||
}
|
||
|
||
// RedisPollingConfigsCacheKey 生成轮询配置缓存的 Redis 键
|
||
// 用途:String 存储所有轮询配置(JSON 格式)
|
||
// 过期时间:10 分钟
|
||
func RedisPollingConfigsCacheKey() string {
|
||
return "polling:configs"
|
||
}
|
||
|
||
// RedisPollingConfigCardsKey 生成配置匹配索引的 Redis 键
|
||
// 用途:Set 存储匹配该配置的所有卡 ID
|
||
// 过期时间:1 小时
|
||
func RedisPollingConfigCardsKey(configID uint) string {
|
||
return fmt.Sprintf("polling:config:cards:%d", configID)
|
||
}
|
||
|
||
// RedisPollingConcurrencyConfigKey 生成并发控制配置的 Redis 键
|
||
// 用途:String 存储任务类型的最大并发数
|
||
// 过期时间:无(持久化配置)
|
||
func RedisPollingConcurrencyConfigKey(taskType string) string {
|
||
return fmt.Sprintf("polling:concurrency:config:%s", taskType)
|
||
}
|
||
|
||
// RedisPollingConcurrencyCurrentKey 生成并发控制当前值的 Redis 键
|
||
// 用途:String 存储任务类型的当前并发数(计数器)
|
||
// 过期时间:无(实时数据)
|
||
func RedisPollingConcurrencyCurrentKey(taskType string) string {
|
||
return fmt.Sprintf("polling:concurrency:current:%s", taskType)
|
||
}
|
||
|
||
// RedisPollingConcurrencyTotalCurrentKey 返回全部轮询共享的并发计数键。
|
||
func RedisPollingConcurrencyTotalCurrentKey() string {
|
||
return "polling:concurrency:current:total"
|
||
}
|
||
|
||
// RedisPollingManualQueueKey 生成手动触发队列的 Redis 键
|
||
// 用途:List 存储手动触发的卡 ID(FIFO 队列)
|
||
// 过期时间:无(临时队列)
|
||
func RedisPollingManualQueueKey(taskType string) string {
|
||
return fmt.Sprintf("polling:manual:%s", taskType)
|
||
}
|
||
|
||
// RedisPollingManualDedupeKey 生成手动触发去重的 Redis 键
|
||
// 用途:Set 存储已加入手动触发队列的卡 ID(用于去重)
|
||
// 过期时间:24小时(与日限制周期对齐)
|
||
func RedisPollingManualDedupeKey(taskType string) string {
|
||
return fmt.Sprintf("polling:manual:dedupe:%s", taskType)
|
||
}
|
||
|
||
// RedisPollingPriorityQueueKey 生成优先轮询提示通道的 Redis 键
|
||
// 用途:List 存储需要优先执行的卡 ID;与手动触发队列(polling:manual:{taskType})分离,
|
||
// 使调度器在同一调度周期内先排空优先提示、再排空手动触发队列。
|
||
// 提示通道不是权威:丢失时库内活动优先项仍在,后续普通轮询执行按条件认领仍会执行。
|
||
// 过期时间:无(临时队列)
|
||
func RedisPollingPriorityQueueKey(taskType string) string {
|
||
return fmt.Sprintf("polling:priority:%s", taskType)
|
||
}
|
||
|
||
// RedisPollingStatsKey 生成监控统计的 Redis 键
|
||
// 用途:Hash 存储监控指标(成功数、失败数、总耗时等)
|
||
// 过期时间:无(持久化统计)
|
||
func RedisPollingStatsKey(taskType string) string {
|
||
return fmt.Sprintf("polling:stats:%s", taskType)
|
||
}
|
||
|
||
// RedisPollingInitProgressKey 生成初始化进度的 Redis 键
|
||
// 用途:Hash 存储初始化进度信息(总数、已处理数、状态)
|
||
// 过期时间:无(初始化完成后自动删除)
|
||
func RedisPollingInitProgressKey() string {
|
||
return "polling:init:progress"
|
||
}
|
||
|
||
// ========================================
|
||
// 复机并发保护相关 Redis Key
|
||
// ========================================
|
||
|
||
// RedisCardResumeLockKey 生成卡复机操作分布式锁的 Redis 键
|
||
// 用途:防止同一张卡并发触发多次 gateway.StartCard
|
||
// 过期时间:30 秒
|
||
func RedisCardResumeLockKey(cardID uint) string {
|
||
return fmt.Sprintf("card:resume:lock:%d", cardID)
|
||
}
|
||
|
||
// ========================================
|
||
// 套餐激活锁相关键
|
||
// ========================================
|
||
|
||
// RedisPackageActivationLockKey 生成套餐激活分布式锁的 Redis 键
|
||
// 用途:防止同一载体的套餐激活任务并发执行(排队激活、首次实名激活)
|
||
// 过期时间:30秒(任务执行时间)
|
||
func RedisPackageActivationLockKey(carrierType string, carrierID uint) string {
|
||
return fmt.Sprintf("package:activation:lock:%s:%d", carrierType, carrierID)
|
||
}
|
||
|
||
// ========================================
|
||
// 列表计数缓存 Redis Key
|
||
// ========================================
|
||
|
||
// RedisListCountKey 列表查询计数缓存键
|
||
// 用途:缓存分页列表的 COUNT(*) 结果,避免每次翻页重复全表计数
|
||
// 过期时间:30 秒
|
||
func RedisListCountKey(table string, version int64, userID uint, scopeHash string, filterHash string) string {
|
||
return fmt.Sprintf("list_count:v2:%s:%d:%d:%s:%s", table, version, userID, scopeHash, filterHash)
|
||
}
|
||
|
||
// RedisListCountVersionKey 列表查询计数缓存版本键
|
||
// 用途:数据变更后递增版本,让旧 COUNT(*) 缓存立即失效
|
||
func RedisListCountVersionKey(table string) string {
|
||
return fmt.Sprintf("list_count_version:%s", table)
|
||
}
|
||
|
||
// ========================================
|
||
// 订单幂等性相关 Redis Key
|
||
// ========================================
|
||
|
||
// RedisOrderIdempotencyKey 生成订单创建幂等性检测的 Redis 键
|
||
// 用途:防止相同买家在短时间内对同一载体重复下单(SETNX 快速拒绝)
|
||
// 过期时间:3 分钟
|
||
func RedisOrderIdempotencyKey(businessKey string) string {
|
||
return fmt.Sprintf("order:idempotency:%s", businessKey)
|
||
}
|
||
|
||
// RedisOrderCreateLockKey 生成订单创建分布式锁的 Redis 键
|
||
// 用途:防止同一载体的订单创建并发执行
|
||
// 过期时间:10 秒
|
||
func RedisOrderCreateLockKey(carrierType string, carrierID uint) string {
|
||
return fmt.Sprintf("order:create:lock:%s:%d", carrierType, carrierID)
|
||
}
|
||
|
||
// ========================================
|
||
// 客户端购买相关 Redis Key
|
||
// ========================================
|
||
|
||
// RedisClientPurchaseIdempotencyKey 生成客户端套餐购买幂等性检测的 Redis 键
|
||
// 用途:防止同一个人客户对同一资产重复提交购买请求(SETNX 快速拒绝)
|
||
// 过期时间:3 分钟
|
||
func RedisClientPurchaseIdempotencyKey(businessKey string) string {
|
||
return fmt.Sprintf("client:purchase:idempotency:%s", businessKey)
|
||
}
|
||
|
||
// RedisClientPurchaseLockKey 生成客户端套餐购买分布式锁的 Redis 键
|
||
// 用途:防止同一资产的购买请求并发执行
|
||
// 过期时间:10 秒
|
||
func RedisClientPurchaseLockKey(assetType string, assetID uint) string {
|
||
return fmt.Sprintf("client:purchase:lock:%s:%d", assetType, assetID)
|
||
}
|
||
|
||
// ========================================
|
||
// 设备保护期相关 Redis Key
|
||
// ========================================
|
||
|
||
// RedisDeviceProtectKey 生成设备保护期 Redis 键
|
||
// action: "stop"(停机保护期)或 "start"(复机保护期),两者互斥
|
||
// 过期时间:DeviceProtectPeriodDuration(1 小时)
|
||
func RedisDeviceProtectKey(deviceID uint, action string) string {
|
||
return fmt.Sprintf("protect:device:%d:%s", deviceID, action)
|
||
}
|
||
|
||
// RedisDeviceRefreshCooldownKey 生成设备刷新冷却期 Redis 键
|
||
// 用途:防止同一设备短时间内多次调网关刷新(限频)
|
||
// 过期时间:DeviceRefreshCooldownDuration(30 秒)
|
||
func RedisDeviceRefreshCooldownKey(deviceID uint) string {
|
||
return fmt.Sprintf("refresh:cooldown:device:%d", deviceID)
|
||
}
|
||
|
||
// ========================================
|
||
// 轮询保护期队列 Redis Key
|
||
// ========================================
|
||
|
||
// RedisPollingQueueProtectKey 保护期一致性检查轮询队列键
|
||
// 用途:存储需要进行保护期一致性检查的卡 ID(ZSet,按时间排序)
|
||
func RedisPollingQueueProtectKey() string {
|
||
return "polling:queue:protect"
|
||
}
|
||
|
||
// ========================================
|
||
// 微信配置相关 Redis Key
|
||
// ========================================
|
||
|
||
// RedisWechatConfigActiveKey 生效支付配置缓存键
|
||
// 用途:缓存当前激活的微信参数配置(JSON 或 "none" 空标记)
|
||
// 过期时间:5 分钟(有配置)/ 1 分钟(空标记)
|
||
func RedisWechatConfigActiveKey() string {
|
||
return "wechat:config:active"
|
||
}
|
||
|
||
// ========================================
|
||
// 流量日缓冲相关 Redis Key
|
||
// ========================================
|
||
|
||
// RedisCardDailyTrafficKey 生成卡日流量缓冲的 Redis 键
|
||
// 用途:INCRBYFLOAT 累计当日流量增量,每日落盘任务消费后删除
|
||
// 过期时间:48 小时
|
||
func RedisCardDailyTrafficKey(cardID uint, date string) string {
|
||
return fmt.Sprintf("traffic:daily:%d:%s", cardID, date)
|
||
}
|
||
|
||
// RedisPackageUsageRemainderKey 生成套餐扣减流量小数余量缓存键
|
||
// 用途:缓存载体维度的 <1MB 小数余量,累计后再触发整数 MB 扣减
|
||
// 过期时间:7 天
|
||
func RedisPackageUsageRemainderKey(carrierType string, carrierID uint) string {
|
||
return fmt.Sprintf("package:usage:remainder:%s:%d", carrierType, carrierID)
|
||
}
|
||
|
||
// RedisCardTrafficSyncLockKey 生成卡流量同步锁 Redis 键
|
||
// 用途:串行化轮询与手动刷新,避免同一上游读数被重复扣减套餐流量
|
||
// 过期时间:10 分钟
|
||
func RedisCardTrafficSyncLockKey(cardID uint) string {
|
||
return fmt.Sprintf("traffic:sync:lock:card:%d", cardID)
|
||
}
|
||
|
||
// ========================================
|
||
// 轮询分片队列相关 Redis Key
|
||
// ========================================
|
||
|
||
// RedisPollingShardQueueKey 轮询分片队列 Key
|
||
// shardID: 分片编号(0 到 N-1)
|
||
// taskType: 任务类型(realname/carddata/package/protect)
|
||
// 格式:polling:shard:{shardID}:queue:{taskType}
|
||
func RedisPollingShardQueueKey(shardID int, taskType string) string {
|
||
return fmt.Sprintf("polling:shard:%d:queue:%s", shardID, taskType)
|
||
}
|
||
|
||
// RedisPollingRealnameReversalCountKey 实名逆转连续计数器,防止上游单次误报触发停机
|
||
// TTL: 10分钟
|
||
func RedisPollingRealnameReversalCountKey(cardID uint) string {
|
||
return fmt.Sprintf("polling:card:realname:reversal:%d", cardID)
|
||
}
|
||
|
||
// RedisCardObservationSeriesKey 返回同场景观测序列合并键。
|
||
func RedisCardObservationSeriesKey(scene, resourceType, resourceID, syncType string) string {
|
||
return fmt.Sprintf("cardsync:series:%s:%s:%s:%s", scene, resourceType, resourceID, syncType)
|
||
}
|
||
|
||
// RedisCardObservationSeriesIndexKey 返回同资源、同步类型的活跃序列索引键。
|
||
func RedisCardObservationSeriesIndexKey(resourceType, resourceID, syncType string) string {
|
||
return fmt.Sprintf("cardsync:series:index:%s:%s:%s", resourceType, resourceID, syncType)
|
||
}
|
||
|
||
// RedisCardObservationSeriesCompletedKey 返回序列提前完成标记键。
|
||
func RedisCardObservationSeriesCompletedKey(seriesID string) string {
|
||
return fmt.Sprintf("cardsync:series:completed:%s", seriesID)
|
||
}
|
||
|
||
// RedisCardObservationAttemptKey 返回 series_id + attempt 幂等键。
|
||
func RedisCardObservationAttemptKey(seriesID string, attempt int) string {
|
||
return fmt.Sprintf("cardsync:attempt:%s:%d", seriesID, attempt)
|
||
}
|
||
|
||
// RedisCardObservationScheduleKey 返回固定阶梯任务的入队幂等键。
|
||
func RedisCardObservationScheduleKey(seriesID string, attempt int) string {
|
||
return fmt.Sprintf("cardsync:schedule:%s:%d", seriesID, attempt)
|
||
}
|
||
|
||
// RedisCardObservationInflightKey 返回一次实际 Gateway 请求的互斥键。
|
||
func RedisCardObservationInflightKey(provider, syncType, resourceID string) string {
|
||
return fmt.Sprintf("cardsync:inflight:%s:%s:%s", provider, syncType, resourceID)
|
||
}
|
||
|
||
// RedisCardObservationLastRequestKey 返回运营商接入与同步类型的最近请求时间键。
|
||
func RedisCardObservationLastRequestKey(provider, syncType, resourceID string) string {
|
||
return fmt.Sprintf("cardsync:last_request:%s:%s:%s", provider, syncType, resourceID)
|
||
}
|
||
|
||
// RedisPollingDeviceOpLockKey 设备维度停复机操作锁 Key
|
||
// 防止设备下多张卡并发触发 EvaluateAndAct 导致重复 Gateway 调用
|
||
// TTL 建议 30 秒(覆盖 stopDeviceCards/resumeDeviceCards 最长执行时间)
|
||
// 格式:polling:device:op_lock:{deviceID}
|
||
func RedisPollingDeviceOpLockKey(deviceID uint) string {
|
||
return fmt.Sprintf("polling:device:op_lock:%d", deviceID)
|
||
}
|
||
|
||
// RedisPollingSchedulerHeartbeatKey 轮询调度器心跳 Key
|
||
// 调度器每次 tick 写入当前时间戳,TTL=2s
|
||
// 告警规则:key 不存在超过 5s 视为调度器停止运行
|
||
func RedisPollingSchedulerHeartbeatKey() string {
|
||
return "polling:scheduler:heartbeat"
|
||
}
|
||
|
||
// RedisPollingConfigChangedChannel 轮询配置变更 Pub/Sub 频道
|
||
// 用途:API 进程发布配置变更事件,Worker 进程订阅后立即刷新内存缓存
|
||
// 消息内容:事件类型字符串("created"/"updated"/"deleted"),仅用于日志,不影响逻辑
|
||
func RedisPollingConfigChangedChannel() string {
|
||
return "polling:config:changed"
|
||
}
|
||
|
||
// ========================================
|
||
// 系统全局配置 Redis Key
|
||
// ========================================
|
||
|
||
// RedisSystemOperationPasswordKey 全局操作密码 Redis 键
|
||
// 用途:存储超级管理员设置的全局操作密码(bcrypt 哈希值)
|
||
// 过期时间:永久存储(无 TTL)
|
||
func RedisSystemOperationPasswordKey() string {
|
||
return "system:operation_password"
|
||
}
|
||
|
||
// ========================================
|
||
// 支付配置缓存 Redis Key
|
||
// ========================================
|
||
|
||
// RedisPaymentConfigKey 支付配置缓存 Key
|
||
// 用途:缓存 WechatConfig 数据(JSON 格式),避免每次支付时重复查询数据库
|
||
// 格式:payment:config:{configID}
|
||
// TTL:1 小时
|
||
func RedisPaymentConfigKey(configID uint) string {
|
||
return fmt.Sprintf("payment:config:%d", configID)
|
||
}
|
||
|
||
// RedisWeComAccessTokenKey 返回企业微信应用 access_token 缓存 Key。
|
||
func RedisWeComAccessTokenKey(applicationID uint) string {
|
||
return fmt.Sprintf("wecom:application:%d:access_token", applicationID)
|
||
}
|
||
|
||
// RedisWeComAccessTokenLockKey 返回企业微信应用 access_token 回源短锁 Key。
|
||
func RedisWeComAccessTokenLockKey(applicationID uint) string {
|
||
return fmt.Sprintf("wecom:application:%d:access_token:lock", applicationID)
|
||
}
|