Alpaca券商对账与幂等
将以下提示词粘贴到你的 AI 对话框中:
请根据 https://skillhub.cn/install/skillhub.md,安装 @user_3c6cb52e/alpaca-broker-reconciliation-idempotency-k268。
技能介绍
要解决的问题
把 Alpaca 当真实资金系统接入时,最大风险是把 200 当成已经结算,把 SSE 事件当成唯一事实,或在超时后盲目重试。Alpaca 是异步、最终一致的券商系统:写入稍后才落定,事件可能丢失、重放或乱序,部分 rails 根本没有事件,executed 也可能被 cashiering 或 correction 推翻。正确目标不是让某次调用“恰好一次”成功,而是让本地数据库成为 Alpaca 状态的忠实、可自愈缓存。
技能如何工作
核心原则是:Alpaca 是 source of truth,本地库必须收敛到它。任何写入都只是请求,任何事件都只是提示,正确性来自幂等处理加对账循环。
- Layer 1:幂等写入。 订单写入前先由本地事务 ID 派生
client_order_id(≤128 字符);响应丢失时先按orders:by_client_order_id查,再决定是否重试。Journal 发送Idempotency-Key:同 key 同 body 返回原 journal,同 key 异 body 得到422。网络调用前先写 intent row 和生成 key,崩溃后还能对账;返回的account_id、order_id、journal_id、transfer_id要立即持久化。 - Layer 2:幂等事件摄入。 事件是 at-least-once,因此先以
event_id(ULID)做 raw snapshot 的 upsert / skip-on-duplicate。业务记录用 Alpaca ID 做主键而不是本地自增,并做 upsert。处理前检查当前状态是否 terminal,更新时SELECT ... FOR UPDATE锁行;游标只在成功后推进。 - Layer 3:对账 / heal job。 定时从 Alpaca 重新拉取权威状态:对每个 active account 分页拉取最近 N 天的 trade / non-trade activities,再拉 journals 和 transfers;按 Alpaca ID upsert 回本地。窗口重扫能吸收修正、延迟结算、部署期间漏掉的事件,而不需要每晚全量重扫。用小 worker pool 限并发,并遵循 rate-limit resilience。
- 无事件 rails 必须轮询。 funding-wallet per-transfer status 不会推送,要按计划
GET /v1beta/.../funding_wallet/transfers/{id};轮询器错峰,只处理status IN (pending, processing, ...),到达 terminal 后退出集合。classic wire transfer 没有 GET-by-id,要按direction=OUTGOING拉列表并在客户端匹配 ID。 - 状态映射集中管理。 为 account、order、journal、transfer、funding-wallet 各建一张显式映射表,未知状态记日志并跳过;明确哪些状态是 terminal,以停止轮询和处理。
适用边界与注意点
它解决的是 Alpaca 券商集成中的一致性架构,不替代具体 domain skill。使用前应先读 alpaca-broker-integration、alpaca-broker-sse-events 和相关领域技能。落地依赖数据库唯一约束、事务性 intent write、游标持久化和 reconciliation 窗口;缺少任何一层,超时重试、事件重放、漏事件或 correction 仍会造成重复资金移动、重复通知或账目失真。不要把 executed/COMPLETE 当作最终态,因为 journal 可能被 reverse,transfer 可能 RETURNED;200 只代表 accepted,资金是否到账要以 terminal event / poll 为准。
使用场景
- 订单写入响应超时,无法判断是否已成交,需要用 client_order_id 查回后安全重试,避免重复下单。
- SSE 事件重放或乱序到达,需要按 event_id 去重并锁行处理,防止重复通知和重复放款。
- 部署期间漏收事件,需要跑夜间 heal job 重扫最近 3 天 activities,把缺失流水补齐到本地库。
- funding-wallet 转账不推送事件,需要按计划轮询状态并回写终态,不能只依赖 create 响应。
适合人员
- 负责券商交易系统数据一致性的后端工程师,需要让本地订单表最终收敛到 Alpaca 权威状态,而不是每次超时就盲目重试。
- 搭建资金结算对账链路的工程负责人,需要在 journal correction 或 cashiering 反向冲正后自动修复账目。
- 维护实时事件消费服务的后端工程师,需要在 SSE 断线重连或事件重放时避免下游动作被重复触发。
- 设计资金类 API 的架构师,需要判断哪些状态算终态、哪些 rails 必须轮询,并据此设定轮询窗口和延迟预期。