5.7 KiB
5.7 KiB
name, overview, todos
| name | overview | todos | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 允许免费额度配置为 0 | 修复新用户免费额度配置无法设为 0 的问题:配置字段改为 *int64 以区分「未配置」与「显式 0」,未配置回落内置默认,显式 0 生效为 0。 |
|
产品概述
修复新用户免费额度初始化的配置语义缺陷:原有实现把「配置为 0」误判为「未配置」而回落内置默认,导致无法将某类免费额度配成 0(例如要求新用户 AI 推荐额度为 0、必须购买后才可用)。
核心功能
- 区分「未配置」与「显式 0」:
UserDefaultQuota四个配置字段改为指针类型,未配置(nil)回落内置默认 20/3/10/5,显式配置 0 则生效为 0 - 保持兜底能力:整段配置缺失、单个键缺失、配置为负数三种情况仍回落内置默认,不破坏既有部署
- 文档同步:README 配置项说明、config.example.yaml 注释、接口文档额度说明统一为「允许配 0,未配置回落默认」
- 行为不变:四类额度的初始化流程、流水记录、唯一索引幂等逻辑完全不动
技术栈
- Go 1.27,模块
git.lzcwy.cn/zhengchiliu/zt-closet-backend - 配置:
pkg/setting(viper 只读configs/config.yaml,ReadSection走UnmarshalKey/mapstructure) - 消费点唯一:
internal/service/quota.go的defaultQuotaValue(grep 已确认无其它引用)
实现方案
采用指针字段区分三态:把 UserDefaultQuotaSettingS 的 Cos/AI/OutfitShare/ClosetShare 由 int64 改为 *int64。viper 解码时键存在则分配指针(含 0),键不存在则保持 nil,从而在类型层面区分「未配置」与「配置为 0」。
取值判据(defaultQuotaValue):
cfg == nil(整段缺失)→ 内置默认cfg.X == nil(该键缺失)→ 内置默认*cfg.X >= 0→ 用配置值(0 生效,本次修复目标)*cfg.X < 0→ 内置默认(防御:负数会让total为负,破坏额度校验)
关键决策与取舍:
- 用
*int64而非把判据改成>= 0:后者能让 0 生效,但「键缺失」解码后同样是 0,会静默把兜底默认值变成 0——对现有未显式配置的环境是破坏性变更。指针方案零歧义,代价仅是多一层判空。 - 用指针而非
viper.IsSet逐键查询:配置结构仍由结构体承载,ReadSection用法与其它配置段一致,不引入第二套读取方式,符合现有架构。 - 负数回落而非报错:保持 best-effort 风格(与额度初始化失败仅告警不阻断一致),不引入启动期配置校验的新失败路径。
- 保留内置常量值 20/3/10/5 不变:只改判据与注释,不动
ensureDefaultQuota的创建+流水事务逻辑。
性能与可靠性:该路径仅在首次登录注册时执行 4 次,指针判空为 O(1) 无额外开销;风险点仅为指针解引用,通过判空分支覆盖,并有 go build/go vet 兜底。
实现要点(防回归)
- 改字段类型后必须全量编译,
global.UserDefaultQuotaSetting的其它消费点若有解引用会直接编译报错(当前仅 quota.go 一处)。 - 判空顺序必须为
cfg != nil && cfg.X != nil && *cfg.X >= 0,避免 nil 解引用 panic。 - 注释需同步:结构体注释「值 <=0 视为未设置」、
constants.go:42「配置缺省或 <=0 时回落」、defaultQuotaValue函数注释,三处都要改成新语义,否则后续维护者会按旧语义改回去。 - 不要扩大范围:
Upload.MaxSizeMB、MattingModel.MaxRetry等其它<=0兜底语义不同(0 无业务意义),本次不动,仅在结论中提示。 - 不改动
configs/config.yaml(用户本地文件,已被 .gitignore 忽略)。
目录结构
pkg/setting/section.go # [MODIFY] UserDefaultQuotaSettingS 四字段 int64 → *int64;
# 注释改为「nil=未配置回落默认;非 nil 生效,允许 0」
internal/service/quota.go # [MODIFY] defaultQuotaValue 判据改为指针判空 + >=0 生效;
# 函数注释同步(未配置/负数回落,0 生效)
internal/service/constants.go # [MODIFY] 第 42 行注释「配置缺省或 <=0 时回落」→「未配置(nil)或负数时回落」
README.md # [MODIFY] 第 195 行配置表说明改为「未配置回落内置默认 20/3/10/5;可显式配 0」
configs/config.example.yaml # [MODIFY] UserDefaultQuota 段注释补充「可为 0 表示不赠送;留空则回落内置默认」
接口文档.md # [MODIFY] 第 488/1432/1446 行及 5.2 节额度表格补「可由 UserDefaultQuota 配置,允许为 0」