Documentation
¶
Overview ¶
Package idempotency 提供幂等执行原语:同一 key 的重复请求只执行一次, 后续请求(含并发)复用首次结果,直到该 key 过期。
解决的问题:网络重试 / 客户端重发 / 消息重投会让同一逻辑操作执行多次—— 抽卡重复扣钱、充值重复到账、发奖重复发放。给每次操作分配一个幂等 key (订单号 / 请求 ID / txID),用本原语包住执行体,重复 key 不再重复执行。
两条语义合一:
- 去重(dedup):key 已有完成结果 → 直接返回缓存的结果,不再执行 fn;
- 并发合并(singleflight):同一 key 多个请求同时到达 → 只有一个执行 fn, 其余阻塞等待同一结果,避免"缓存击穿式"重复执行。
结果按 TTL 过期(默认 10 分钟),到点后同 key 可重新执行。fn 返回 error 时 默认不缓存(允许重试);可用 WithCacheErrors 改为连错误一起缓存(适合 "确定性失败无需重试"的场景)。
泛型 T 为结果类型。并发安全。零值不可用,用 New 构造;Stop 后清扫 goroutine 退出。
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Option ¶
type Option func(*config)
Option 配置 Store。
func WithCacheErrors ¶
WithCacheErrors 设置是否缓存失败结果(默认 false)。 false:fn 返回 error 不缓存,同 key 下次请求会重新执行(适合瞬时错误可重试); true:错误也按 TTL 缓存,同 key 直接返回该错误(适合确定性失败,避免无谓重试)。 注意:store 模式只缓存**成功**结果(错误不跨进程序列化),此选项仅内存模式生效。
func WithGCInterval ¶
WithGCInterval 设置过期清扫间隔(默认 1 分钟,仅内存模式)。
func WithOnStoreError ¶
WithOnStoreError 设置 store 出错回调。默认静默 + 降级为直接执行 fn。
func WithStore ¶
WithStore 让幂等结果走外部共享存储(如 Redis),使去重跨实例生效。 结果用 JSON 序列化后存入 store(故 T 须可被 encoding/json 编解码)。
语义差异(务必知悉):内存模式提供"去重 + 并发单飞(阻塞等待首次结果)"; store 模式只提供**去重 + 复用已完成结果**——用 SetNX 抢占执行权,抢到的执行 fn 并写回结果,没抢到的**不阻塞等待**,而是读已有结果(若尚未写完则自己执行一次)。 即:跨实例的并发同 key 可能各自执行一次,幂等性由"结果最终以 key 唯一存储 + 复用" 保证,而非"全局只执行一次"。要严格单飞请在 fn 内配合分布式锁,或接受此 at-least-once 语义(这正是幂等键要求业务操作本身可安全重试的原因)。 只缓存成功结果;fn 返回 error 时不写 store,允许重试。
type Store ¶
type Store[T any] struct { // contains filtered or unexported fields }
Store 幂等结果存储。按 key 维护"执行中/已完成"记录。 零值不可用,用 New 构造。并发安全。
func (*Store[T]) Do ¶
Do 以 key 为幂等键执行 fn:
- key 首次出现:执行 fn,缓存结果(按配置决定是否缓存 error),返回 (result, err, false);
- key 执行中(并发):阻塞等待首次执行完成,返回其结果 + shared=true;
- key 已完成且未过期:直接返回缓存结果 + shared=true,不执行 fn。
shared 表示本次结果是否复用自其他请求(true=未真正执行 fn)。 fn 内 panic 不被捕获——调用方若需防护请在 fn 内自行 recover;panic 会 导致等待同 key 的其他请求也观察到该记录被清理(可重试)。