pub const REST_SHARED_CONN: u64 = 0xFFFF_FFFE;Expand description
v1.4.90 P0-B: REST 全 endpoint 共享 conn_id(替代之前每次请求 next_conn_id()
自增 → 永久泄漏 sub-quota 直到耗尽 4000 上限)。
背景:v1.4.81 一直到 v1.4.89 之前,REST proto_request 每次都调
state.next_conn_id() 拿新 virtual conn_id(10_000_000 自增)。SubscriptionManager
按 conn_id 记账:subscribe 把 (security, sub_type) 挂在 conn_id 下、quota
+=1;unsubscribe 从同一 conn_id 删除、quota -=1。但 REST subscribe 用 conn_id=X
→ backend 订阅 ✓,下一次 REST unsubscribe 用 conn_id=Y → 找不到任何挂载 →
静默 no-op,quota 永不释放。日积月累 4000 quota 耗尽,整个 daemon 不能再
订阅任何东西。
修法:所有 REST sub-related endpoint(subscribe / unsubscribe /
get_sub_info / query_subscription)锁定到 REST_SHARED_CONN. lifecycle
由 daemon 进程管,不随 REST 请求生灭。
REST 视角合理性:REST 是 stateless API,调用方不持续持有 daemon TCP
连接,“连接 ID” 在 REST 层面没物理意义。把所有 REST 流量当作“REST gateway“
这一个虚拟客户端的多次调用,对应一个固定 conn_id 是最干净的语义。v1.4.106
起 quote / kline / orderbook / ticker / rt handler 也会检查
SubscriptionManager::is_qot_subscribed(conn_id, ...),所以这些订阅门禁
读路径也必须锁定到同一 REST_SHARED_CONN,否则 REST subscribe 后下一次
REST read 看不到同一个 conn 的订阅。
取值选择:0xFFFF_FFFE_u64(4_294_967_294)。next_conn_id 起点
10_000_000,要 ~4.28B 次调用才碰到此值,daemon 早已重启。0xFFFF_FFFF_u64
留给未来可能的 sentinel(如“all REST“广播)。
对齐 MCP 路径行为:MCP 用单 FutuClient 复用底层 TCP,所有 MCP 请求自然
共享同一个 daemon 分配的 conn_id,不存在该 bug。REST 现在显式实现同语义。