Alpaca券商对账幂等
将以下提示词粘贴到你的 AI 对话框中:
请根据 https://skillhub.cn/install/skillhub.md,安装 @user_3c6cb52e/alpaca-broker-reconciliation-idempotency。
技能介绍
对账与幂等问题是所有接 Alpaca 的交易系统绕不开的工程问题。
要解决什么
Alpaca 是一个异步、最终一致的系统。这意味着几类故障会反复出现:
- 网络中断后重试,你分不清
timeout到底是请求没到还是结果丢了,可能重复下单或重复记账 - SSE 事件流会重放,同一个
filled事件可能到达两次,触发两次 payout - 资金划拨(funding-wallet transfer)不推送事件,不轮询就永远拿不到终态
executed/COMPLETE不一定是终态,journal 可能被 cashiering 冲正,transfer 可能事后RETURNED
这个技能的目标,是让本地数据库成为一个忠实且自愈的 Alpaca 状态镜像。
三层防御架构
核心原则只有一句:把 Alpaca 当唯一事实源,本地库只是必须收敛的缓存。
第一层:幂等写入。 所有涉及钱和订单的写操作必须可安全重试。下单时设置自己的 client_order_id(由本地事务 ID 派生),响应丢失时先按 orders:by_client_order_id 查单再决定是否重试;journal 请求带上 Idempotency-Key header,同 key 同 body 返回原 journal,同 key 不同 body 返回 422。
第二层:幂等事件消费。 SSE 是 at-least-once,必须处理重复。按 event_id(ULID)做 upsert 去重,重复事件变成 no-op;业务记录以 Alpaca ID 而非本地自增 ID 为主键;处理前先检查当前状态,防止重复触发 payout;变更时用 SELECT ... FOR UPDATE 锁行,串行化并发事件。
第三层:对账修复任务。 定时任务重新拉取 Alpaca 权威状态并 upsert 到本地。建议跑一个移动窗口(如最近 3 天),分页拉取 /v1/accounts/activities、/v1/journals、transfers,按 Alpaca ID upsert。相比只从上次游标继续,移动窗口能吸收冲正、延迟结算,以及发布期间丢的事件。
无事件通道的轮询与状态映射
funding-wallet 的 transfer 状态不会推送,必须轮询 GET /v1beta/.../funding_wallet/transfers/{id}。轮询时只查非终态记录(status IN (pending, processing, ...)),到达终态就从轮询集移除。注意经典 wire transfer 没有按 ID 查询接口,只能拉 GET /v1/accounts/{id}/transfers?direction=OUTGOING 列表后客户端匹配 ID。
Alpaca 各域状态枚举各不相同,且会新增取值,不要在业务代码里散落原始字符串。定义显式映射表(如 executed/COMPLETE → COMPLETED),遇到未知状态记日志跳过,绝不崩。
设计边界与常见反模式
不要在 create 响应返回 200 时就确认资金到账——那只是已接受,必须等终态事件或轮询结果。修正类操作会生成新 ID(journal correct 会取消原 journal 并新建),按 Alpaca ID + 事件快照对账才能正确收敛,直接改原记录则不行。
反模式包括:重连 SSE 时不带 since_id 游标导致静默丢事件;只依赖 SSE 不做对账回填;无幂等 key 盲重试 journal/order 造成双花;把 executed 当不可逆。
相关技能:事件消费见 alpaca-broker-sse-events,journal 幂等键见 alpaca-broker-journals,轮询通道见 alpaca-broker-funding-transfers。
使用场景
- 对接 Alpaca 下单遇到超时重试时,需要幂等写入避免重复下单或重复记账
- 消费 SSE 事件时收到重复或乱序的 filled 通知,需要按 event_id 去重且不重复触发 payout
- 服务发布期间 SSE 断流丢失事件,需要定时对账任务回补最近 3 天的活动、journal 与 transfer 数据
- 资金划拨没有事件推送,需要定时轮询非终态 transfer 并确认终态后才关闭工单
适合人员
- 正在把 Alpaca 交易接口推向生产的后端工程师,诉求是超时重试时不重复下单、不重复记账
- 负责券商账务对账的后端工程师,诉求是本地库能作为 Alpaca 状态的自愈镜像最终收敛
- 实现 SSE 事件消费的后端工程师,诉求是处理重复与乱序事件时不重复触发资金划拨
- 维护对账修复定时任务的后端工程师,诉求是设计可安全重跑的移动窗口回补策略