futu_rest/adapter/state.rs
1//! Split from adapter.rs: state.
2//!
3//! pub items: RestState.
4
5use std::sync::Arc;
6
7use super::*;
8
9/// REST 服务共享状态
10#[derive(Clone)]
11pub struct RestState {
12 /// 复用 OpenD 的请求路由器
13 pub router: Arc<RequestRouter>,
14 /// WebSocket 推送广播器
15 pub ws_broadcaster: Arc<WsBroadcaster>,
16 /// Bearer Token KeyStore(未配置 → is_configured() == false,WS 握手也放行)
17 pub key_store: Arc<KeyStore>,
18 /// v1.2:handler 层 full CheckCtx 用的限额计数器(与 auth middleware
19 /// 共享同一份 Arc,rate window 跨 auth/handler 一致)
20 pub counters: Arc<futu_auth::RuntimeCounters>,
21 /// v1.4.104 阶段 7-1: 跨 surface response filter 注册表 (proto 2001
22 /// TRD_GET_ACC_LIST 默认装入). 替代 routes/trd.rs::get_acc_list 内联
23 /// JSON-level filter (35 LoC), 走 proto-bytes-level filter unified with
24 /// gRPC + WS surface (FilterRegistry::apply). 加新 filter 只在 registry
25 /// 注册一次, 4 surface 自动生效.
26 pub filter_registry: Arc<futu_auth_pipeline::FilterRegistry>,
27 /// v1.4.32+ daemon admin 状态快照 provider(`/api/admin/status` 用)
28 pub admin_status_provider: Option<AdminStatusProvider>,
29 /// v1.4.32+ daemon admin reload handler(`/api/admin/reload` 用)
30 pub admin_reload_handler: Option<AdminReloadHandler>,
31 /// v1.4.83 §9 Phase 2 F5: Push channel health snapshot provider
32 /// (`/api/push-subscriber-info` 真实 state — 不是 stub 文案)
33 pub push_health_snapshot_provider: Option<PushHealthSnapshotProvider>,
34 /// v1.4.105 D12 (Phase 2): card_num → acc_ids 解析器, REST trade handler
35 /// 在 dispatch 前用于解析 user 传 `card_num` 字段 → acc_id. 未注入 →
36 /// trade endpoint 收到 card_num 字段时 503 reject (loud — 让 user 知道
37 /// daemon 配置问题, 不 silent fall back acc_id).
38 pub card_num_resolver: Option<CardNumResolver>,
39 /// 虚拟连接 ID 分配器(REST 请求从 10_000_000 开始)
40 conn_id_counter: Arc<AtomicU64>,
41 /// 序列号分配器
42 serial_counter: Arc<AtomicU32>,
43 /// v1.4.102 codex 46 F2/F3 (P1): REST sub-acc-push 状态 (per API key).
44 ///
45 /// 之前 REST sub-acc-push 透 dispatch 到 gateway SubscriptionManager 但用
46 /// REST 临时虚拟 conn_id, unsub 用新 conn_id 删不到; 即使 sub OK, REST
47 /// WsBroadcaster 也没基于这个 state 过滤 trade push (只按 scope), 等于
48 /// 所有 acc:read 持有者收所有 trade push, sub-acc-push/unsub-acc-push 是空操作.
49 ///
50 /// 此 map 是 REST 层 per-key acc subscription 真相源:
51 /// - `/api/sub-acc-push` 写入 (key_id → set of acc_id)
52 /// - `/api/unsub-acc-push` 删除
53 /// - WsBroadcaster trade push delivery 检查: key 已 sub 此 acc 才 forward
54 ///
55 /// `None` (key 未 sub-acc-push) → 默认 deliver 所有 acc:read scope 的 push
56 /// (向后兼容, 兼容未升级老 client).
57 pub rest_acc_subscriptions: RestAccSubscriptions,
58}
59
60impl RestState {
61 pub fn new(router: Arc<RequestRouter>, ws_broadcaster: Arc<WsBroadcaster>) -> Self {
62 Self::with_key_store(router, ws_broadcaster, Arc::new(KeyStore::empty()))
63 }
64
65 pub fn with_key_store(
66 router: Arc<RequestRouter>,
67 ws_broadcaster: Arc<WsBroadcaster>,
68 key_store: Arc<KeyStore>,
69 ) -> Self {
70 Self::with_auth(
71 router,
72 ws_broadcaster,
73 key_store,
74 Arc::new(futu_auth::RuntimeCounters::new()),
75 )
76 }
77
78 /// v1.2 推荐入口:同时接 KeyStore + 共享 RuntimeCounters
79 pub fn with_auth(
80 router: Arc<RequestRouter>,
81 ws_broadcaster: Arc<WsBroadcaster>,
82 key_store: Arc<KeyStore>,
83 counters: Arc<futu_auth::RuntimeCounters>,
84 ) -> Self {
85 Self {
86 router,
87 ws_broadcaster,
88 key_store,
89 counters,
90 filter_registry: Arc::new(futu_auth_pipeline::FilterRegistry::with_defaults()),
91 admin_status_provider: None,
92 admin_reload_handler: None,
93 push_health_snapshot_provider: None,
94 card_num_resolver: None,
95 conn_id_counter: Arc::new(AtomicU64::new(10_000_000)),
96 serial_counter: Arc::new(AtomicU32::new(1)),
97 rest_acc_subscriptions: Arc::new(RwLock::new(HashMap::new())),
98 }
99 }
100
101 /// v1.4.104 阶段 7-1: 注入显式 FilterRegistry (跨 surface 共享同一份).
102 /// 默认 with_defaults 已注册 proto 2001; 此 setter 让调用方覆盖.
103 pub fn with_filter_registry(
104 mut self,
105 registry: Arc<futu_auth_pipeline::FilterRegistry>,
106 ) -> Self {
107 self.filter_registry = registry;
108 self
109 }
110
111 /// v1.4.32+ 注入 admin status provider(一般在 futu-opend main 里
112 /// 注入一个捕获 `Arc<GatewayBridge>` 的 closure)。
113 pub fn with_admin_status_provider(mut self, provider: AdminStatusProvider) -> Self {
114 self.admin_status_provider = Some(provider);
115 self
116 }
117
118 /// v1.4.32+ 注入 admin reload handler
119 pub fn with_admin_reload_handler(mut self, handler: AdminReloadHandler) -> Self {
120 self.admin_reload_handler = Some(handler);
121 self
122 }
123
124 /// v1.4.83 §9 Phase 2 F5: 注入 push health snapshot provider.
125 pub fn with_push_health_snapshot_provider(
126 mut self,
127 provider: PushHealthSnapshotProvider,
128 ) -> Self {
129 self.push_health_snapshot_provider = Some(provider);
130 self
131 }
132
133 /// v1.4.105 D12 (Phase 2): 注入 card_num → acc_ids 解析器 closure.
134 /// opend 启动时由 main.rs 注入捕获 `bridge.caches.trd_cache` 的 closure. 未注入
135 /// → trade endpoint 收 card_num 字段时 503 reject (loud).
136 pub fn with_card_num_resolver(mut self, resolver: CardNumResolver) -> Self {
137 self.card_num_resolver = Some(resolver);
138 self
139 }
140
141 /// 分配虚拟连接 ID
142 pub fn next_conn_id(&self) -> u64 {
143 self.conn_id_counter.fetch_add(1, Ordering::Relaxed)
144 }
145
146 /// 分配序列号
147 pub fn next_serial(&self) -> u32 {
148 self.serial_counter.fetch_add(1, Ordering::Relaxed)
149 }
150}