tradingSystem/QMT_SIDE_ACK_SEQ_PATCH.md

3.8 KiB
Raw Blame History

给 QMT 侧:补 ack_seq 处理(协议 §4.5

现象

PMS 每 2 秒发一次 ack_seqQMT 侧回:

{"instruction_id": null, "code": "BAD_PARAM", "reason": "unknown type ack_seq", "retryable": false}

定位到 handlers.pyhandle():类型分发链里有 hello / ping / place_order / cancel_order / query_positions / query_funds / query_orders唯独没有 ack_seq 所以落到了最后一行的兜底:

self._reject_raw(envelope, 'BAD_PARAM', f'unknown type {msg_type}', False)

对过一遍:我方下行 8 个类型,贵方实现了 7 个,只差这一个。

为什么会漏

多半是协议文档的锅,不是实现的锅。QMT_WS_PROTOCOL.md 的版本历史表里, V1.0 定稿那行排在 V0.9.2 上面,而 ack_seq 恰恰是 V0.9.2 才补进来的 (「新增下行消息 ack_seq 累积确认§4.5。从上往下读到「V1.0 定稿」就停的话, 底下引入 ack_seq 的那行会被跳过去。PMS 侧会把这两行顺序修正,条款不动。

后果(已定位,非猜测)

不处理会形成自激循环:

PMS 发 ack_seq → QMT 回 reject → reject 自身带 seq → PMS 水位推进
   → 2 秒后 PMS 又要 ack → 再被 reject → ...

实测 2 秒一条,十几分钟烧掉 800 多个 seq。通道显示 ONLINE实际只在刷 reject。

更实质的影响在贵方§6.1 规定「QMT 收到 ack_seq{seq: N} 后可清理 seq ≤ N 的消息」。 收不到 ackRedis 里的上行消息只涨不清。联调期 Redis 不设过期(双方已确认), 这部分会一直堆着。

补法

handlers.pyhandle() 里,在 if msg_type == 'ping': 附近加一个分支:

if msg_type == 'ack_seq':
    seq = int(payload.get('seq') or 0)
    if seq > 0:
        self.store.ack(seq)          # 清理 seq <= N方法名按贵方 store 的实际接口来
    return                           # 不需要回任何消息

三点提醒:

  1. ack_seq 不需要回消息。 它是单向通知,回 ackpong 都会让 PMS 侧多一条 无主上行。
  2. 累积语义。 收到 {seq: 10450} 表示 seq ≤ 10450 全部已落库,可一次性清理, 不是只清这一条。
  3. §6.1 的 7 天下限仍要守。 「已确认的消息也至少保留 7 天」——防 PMS 侧库回滚后 无从追溯。所以是「可清理」不是「立即删」,按贵方存储策略取舍。

PMS 侧已做的临时处理

PMS 已加自动降级:收到 reason 里含 ack_seq 的协议级 reject 就停发 ack_seq 打断循环。水位照常落库,重连补发靠 hello.last_seq§4.5 原话:「断线重连时以 hello.last_seq 为准,ack_seq 只用于让 QMT 及时释放存储」),不丢成交

标志位每次重连重置——贵方补上之后PMS 重连即自动恢复发送,不需要通知我们改配置。

顺带确认的几件事

  • 签名完全互通。 crypto1.pycompact_payload_json / build_canonical 与 PMS 侧 逐字一致,双向验签实测通过,这一层可以划掉了。
  • new_nonce() 已修。 上一版是 token_hex(8)8 字节),现在是 token_hex(16) 符合 §2.2。
  • 时间窗。 handlers.py 对我方每条消息做 ±30 秒检查(超了回 TS_SKEW。这是对的 但两机时钟漂开会让 place_order 直接被拒,现象是「下单没反应」,很难往时钟上想。 PMS 侧已把实测偏差显示出来,建议两边都确认 NTP 在跑。
  • pong 带 seq 是符合 §5「所有上行消息带 seq」的实现没问题。只是按 §6.1 它也会 进 Redis 并在重连时补发——5 秒一个,一天 1.7 万条纯 {}。要不要给 pong 免掉 seq 是个可以聊的口径问题,不急。