Documentation
¶
Overview ¶
Package invalidate 管理面变更的去抖定向失效(Phase 6 O2):
脏标记(Mark 路径零锁零 DB——atomic CAS 合并 + 非阻塞唤醒,不阻塞任何 调用方;消除 Phase 6 压测实证的 33,705 goroutine reloadMu 串行雪崩)+ 定时窗口到点批量执行一次合并重载;后沿语义(评审 C-6:执行完成后若又脏 立即再执行,不按固定间隔 throttle——不与长 reload 重叠)。
接线矩阵(评审 M-1 定稿,reloadAll 实现):
- 用户 CRUD(含创建)/余额变更 → auth + 余额快照全量(新用户必须即刻在 快照——评审 M-2,防 ≤10s 402 窗口,回归测试 tools/e2e)
- 模板(base_url/models/映射)→ sched 全量 + clients 失效(base_url 变更需按新地址重建 SDK 客户端)
- 账号 → sched 组级定向 InvalidateGroup(包含关系:full ⊇ 组级 ⊇ 无)
- 组倍率 / 用户-组专属倍率 → 余额倍率快照定向刷新(EffectiveMultiplier 陈旧 ≤10s 不可接受)
- key CRUD(#14 多实例 key 缺口)→ auth 快照全量 Reload(v1 不做增量 定向——单实例 auth 增量 Upsert/Delete 语义不变,多实例需全量覆盖其余 实例的陈旧快照)
- settings 变更(UpdateSetting)→ settings 快照重载(service 实现, cfg.Settings 未注入则跳过)
- 规则 CRUD → 规则表全量重载(重载清窗口计数,全实例同步执行语义)
- pricing → 现状(内部 reloadPricing,不进 invalidate)
读端永不阻塞:重载在单 goroutine 串行执行;各实体快照原子替换由实体自身 保证(scheduler snapshotStore / Balances atomic.Pointer / Auth RWMutex 换 整体),本包只在变更侧去抖合并。
Index ¶
- Constants
- type AuthReloader
- type BalancesReloader
- type ClientsReloader
- type Config
- type Debouncer
- func (d *Debouncer) Accounts(gids []int64, keyChanged bool)
- func (d *Debouncer) Clients()
- func (d *Debouncer) Close(ctx context.Context) error
- func (d *Debouncer) Keys()
- func (d *Debouncer) Multipliers()
- func (d *Debouncer) Name() string
- func (d *Debouncer) Rules()
- func (d *Debouncer) SetSettings(r SettingsReloader)
- func (d *Debouncer) Settings()
- func (d *Debouncer) Start(ctx context.Context) error
- func (d *Debouncer) Stats() any
- func (d *Debouncer) Templates()
- func (d *Debouncer) Users()
- type DebouncerStats
- type Kind
- type RulesReloader
- type SchedReloader
- type SettingsReloader
- type State
Constants ¶
const DefaultWindow = 200 * time.Millisecond
DefaultWindow 去抖窗口。生效延迟语义:管理面变更在 ≤200ms 窗口到点后执行 一次合并重载(总延迟 = 窗口 + 一次重载时长;评审 M-1/M-2 定稿 ≤200ms 可 接受——新用户 402 窗口回归测试对"建用户 → <0.5s 请求 → 200"做硬断言)。
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AuthReloader ¶
AuthReloader 鉴权快照全量重载(proxy.Auth 实现)。
type BalancesReloader ¶
type BalancesReloader interface {
Reload(ctx context.Context) error
ReloadMultipliers(ctx context.Context) error
}
BalancesReloader 余额/倍率快照(billing.Balances 实现;billing 关闭时 nil, reloadAll 跳过余额路径)。
type ClientsReloader ¶
type ClientsReloader interface {
InvalidateAll()
}
ClientsReloader aiclient 工厂客户端失效(aiclient.Factory 实现)。
type Config ¶
type Config struct {
Window time.Duration // 去抖窗口(0 → DefaultWindow)
Sched SchedReloader // 必填
Clients ClientsReloader // 必填
Auth AuthReloader // 必填
Balances BalancesReloader // billing.enabled=false → nil
Settings SettingsReloader // 可选(nil → settings 分支跳过)
Rules RulesReloader // 可选(nil → rules 分支跳过)
Log *logx.Logger // 可空(nil = 不记日志)
}
Config 装配参数(main 接线)。
type Debouncer ¶
type Debouncer struct {
// contains filtered or unexported fields
}
Debouncer 去抖器(O2 核心):
- Mark 路径(Users/Templates/Accounts/Multipliers):零锁零 DB——原子 CAS 合并脏状态 + 非阻塞 channel 唤醒;任何调用方(含 50k 并发 fill)不阻塞。
- 执行路径:单 goroutine 串行(Start 启动),窗口到点消费脏状态执行合并 重载;执行期间新变更 → 完成后立即再执行(后沿语义,评审 C-6)。
同时满足 service.Invalidator 接口(main 装配传给 service.New)。
func (*Debouncer) Accounts ¶
Accounts 账号变更(创建/更新/删除/批量):sched 组级定向重载受影响组 (gids;与全量位同窗口时被包含跳过);keyChanged(upstream_key 变更)→ clients 失效。gids 空且 keyChanged=false(无分组账号变更)→ 无任何快照 受影响,直接 no-op(不入脏)。
func (*Debouncer) Clients ¶
func (d *Debouncer) Clients()
Clients 仅客户端工厂失效(aiclient.Factory.InvalidateAll):模板/账号 变更以外独立出现的 clients 失效(#14 T3a notify Dispatcher 独立映射; 服务端发布点恒与 Templates 或 Groups 并排,此处是防御性兜底)。
func (*Debouncer) Close ¶
Close 无操作:循环随 Start 的 ctx 取消退出(worker 契约:幂等、未 Start 也 安全)。停机不补最后 flush——DB 权威,残留变更随下次启动全量加载。
func (*Debouncer) Keys ¶
func (d *Debouncer) Keys()
Keys key CRUD(创建/轮换/删除/改额度,#14 多实例 key 缺口):auth 快照全量 Reload(v1 不做增量定向——现状 auth 增量 Upsert/Delete 是单实例语义;多实例 其余实例的陈旧快照需全量覆盖)。供 notify Dispatcher 远端变更转发。
func (*Debouncer) Multipliers ¶
func (d *Debouncer) Multipliers()
Multipliers 组倍率 / 用户-组专属倍率(price_multiplier)变更(含组创建/ 删除与 group_assignment CRUD——新倍率须即刻进快照,防 ×1 计费窗口):余额 倍率快照定向刷新(组 + assignment 两路小表单查,非全量 Reload—— EffectiveMultiplier 陈旧 ≤10s 不可接受)。
func (*Debouncer) Rules ¶
func (d *Debouncer) Rules()
Rules 规则表变更(规则 CRUD):规则表全量重载(重载清窗口计数——全实例 同步执行语义,NOTIFY 广播)。供 notify Dispatcher 远端变更转发。
func (*Debouncer) SetSettings ¶
func (d *Debouncer) SetSettings(r SettingsReloader)
SetSettings 后置注入 settings 重载器(#14 T3a 装配):main 构造顺序上 service 在 invalidate 之后(service.New 需要去抖器做 Invalidator,去抖器 需要 svc 做 SettingsReloader——构造环),svc 构造完成后回填。必须在 Start 前调用(reloadAll 读 cfg,无锁)。
func (*Debouncer) Settings ¶
func (d *Debouncer) Settings()
Settings settings 快照变更(UpdateSetting):settings 快照全量重载。 生产侧死分支(仅测试引用):dispatcher 已改同步直连路径、UpdateSetting 从 未 Mark——详见 KindSettings 常量注释。
func (*Debouncer) Stats ¶
Stats 满足 handler.StatsProvider(独立于 worker.Worker 契约;装配链路见 internal/handler/ops.go 文件头)。
func (*Debouncer) Templates ¶
func (d *Debouncer) Templates()
Templates 模板(base_url/models/映射)变更:sched 全量 + clients 失效 (base_url 变更需按新地址重建 SDK 客户端——评审发现:此前 Factory.InvalidateAll 无人调用,模板 base_url 更新后流量仍打旧上游直至 重启)。
func (*Debouncer) Users ¶
func (d *Debouncer) Users()
Users 用户 CRUD(含创建)/余额变更:auth + 余额快照全量(评审 M-2:新用户 必须即刻进余额快照——去抖窗口内收敛,防 ≤10s 402 窗口;回归测试 tools/e2e "建用户 → <0.5s 请求 → 200")。
auth 定向回退规则(评审 I-3):本轮不做 Auth.UpsertUser 定向刷新,先全量 Reload(加载在锁外——Auth.Reload 内部先 LoadKeys/LoadUsers 再整体换快照, 读端 RWMutex 不阻塞)。回退规则:仅当压测复测用户 fill <100/s 且 pprof 显示 auth.Reload 为热点时才新增 UpsertUser 定向路径。
type DebouncerStats ¶
type DebouncerStats struct {
Dirty bool `json:"dirty"` // 是否有待执行的重载
DirtyKinds string `json:"dirty_kinds"` // 脏位名(逗号分隔;空 = 纯组级定向)
DirtyGroups int `json:"dirty_groups"` // 组级定向账号数
WindowMs int64 `json:"window_ms"` // 去抖窗口
}
DebouncerStats 去抖器脏状态(当前是否有待执行的合并重载)。
type Kind ¶
type Kind uint8
Kind 是需要"全量重载"的脏位;纯组级定向不占位(走 State.Groups)。
const ( // KindUsers 用户 CRUD(含创建)/余额变更:auth + 余额快照全量 Reload。 KindUsers Kind = 1 << iota // KindTemplates 模板(base_url/models/映射)变更:sched 全量 + clients 失效。 KindTemplates // KindClients aiclient 工厂失效(模板 base_url / 账号 upstream_key 变更)。 KindClients // KindMultipliers 组倍率 / 用户-组专属倍率(price_multiplier)变更:余额 // 倍率快照定向刷新。 KindMultipliers // KindKeys key CRUD(创建/轮换/删除/改额度,#14 多实例 key 缺口):auth // 快照全量 Reload(v1 不做增量定向)。 KindKeys // KindSettings settings 快照变更:settings 快照全量重载。生产侧死分支 // (仅测试引用):dispatcher 的 settings 分支已改同步 ReloadSettings + 注册 // 表 scope 精确重载(#36 时序),UpdateSetting 从未经去抖器 Mark(本地直连 // Apply + NOTIFY 广播)。保留防御性——reloadAll 分支仍接线,未来若恢复 // Mark 路径可复用。 KindSettings // KindRules 规则表变更(规则 CRUD):规则表全量重载(重载清窗口计数, // 全实例同步执行语义)。 KindRules )
type RulesReloader ¶
RulesReloader 规则表全量重载(rule.RuleEngine 实现——现有签名 Reload(ctx) error,T2 需加 ReloadRules 适配;重载清窗口计数,全实例同步 执行语义)。未注入 nil → reloadAll 跳过。
type SchedReloader ¶
type SchedReloader interface {
InvalidateAll()
InvalidateGroup(groupID int64)
}
SchedReloader 调度器快照重载(scheduler.Scheduler 实现)。
type SettingsReloader ¶
SettingsReloader settings 快照全量重载(service.Service 实现,T2 提供; 未注入 nil → reloadAll 跳过,单实例现状行为不变)。