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.111 daemon admin shutdown handler(`/api/admin/shutdown` 用)
30 pub admin_shutdown_handler: Option<AdminShutdownHandler>,
31 /// v1.4.32+ daemon admin reload handler(`/api/admin/reload` 用)
32 pub admin_reload_handler: Option<AdminReloadHandler>,
33 /// v1.4.83 §9 Phase 2 F5: Push channel health snapshot provider
34 /// (`/api/push-subscriber-info` 真实 state — 不是 stub 文案)
35 pub push_health_snapshot_provider: Option<PushHealthSnapshotProvider>,
36 /// v1.4.105 D12 (Phase 2): card_num → acc_ids 解析器, REST trade handler
37 /// 在 dispatch 前用于解析 user 传 `card_num` 字段 → acc_id. 未注入 →
38 /// trade endpoint 收到 card_num 字段时 503 reject (loud — 让 user 知道
39 /// daemon 配置问题, 不 silent fall back acc_id).
40 pub card_num_resolver: Option<CardNumResolver>,
41 /// 虚拟连接 ID 分配器(REST 请求从 10_000_000 开始)
42 conn_id_counter: Arc<AtomicU64>,
43 /// 序列号分配器
44 serial_counter: Arc<AtomicU32>,
45 /// v1.4.102 codex 46 F2/F3 (P1): REST sub-acc-push 状态 (per API key).
46 ///
47 /// 之前 REST sub-acc-push 透 dispatch 到 gateway SubscriptionManager 但用
48 /// REST 临时虚拟 conn_id, unsub 用新 conn_id 删不到; 即使 sub OK, REST
49 /// WsBroadcaster 也没基于这个 state 过滤 trade push (只按 scope), 等于
50 /// 所有 acc:read 持有者收所有 trade push, sub-acc-push/unsub-acc-push 是空操作.
51 ///
52 /// 此 map 是 REST 层 per-key acc subscription 真相源:
53 /// - `/api/sub-acc-push` 写入 (key_id → set of acc_id)
54 /// - `/api/unsub-acc-push` 删除
55 /// - WsBroadcaster trade push delivery 检查: key 已 sub 此 acc 才 forward
56 ///
57 /// `None` (key 未 sub-acc-push) → 默认 deliver 所有 acc:read scope 的 push
58 /// (向后兼容, 兼容未升级老 client).
59 pub rest_acc_subscriptions: RestAccSubscriptions,
60}
61
62impl RestState {
63 pub fn new(router: Arc<RequestRouter>, ws_broadcaster: Arc<WsBroadcaster>) -> Self {
64 Self::with_key_store(router, ws_broadcaster, Arc::new(KeyStore::empty()))
65 }
66
67 pub fn with_key_store(
68 router: Arc<RequestRouter>,
69 ws_broadcaster: Arc<WsBroadcaster>,
70 key_store: Arc<KeyStore>,
71 ) -> Self {
72 Self::with_auth(
73 router,
74 ws_broadcaster,
75 key_store,
76 Arc::new(futu_auth::RuntimeCounters::new()),
77 )
78 }
79
80 /// v1.2 推荐入口:同时接 KeyStore + 共享 RuntimeCounters
81 pub fn with_auth(
82 router: Arc<RequestRouter>,
83 ws_broadcaster: Arc<WsBroadcaster>,
84 key_store: Arc<KeyStore>,
85 counters: Arc<futu_auth::RuntimeCounters>,
86 ) -> Self {
87 Self {
88 router,
89 ws_broadcaster,
90 key_store,
91 counters,
92 filter_registry: Arc::new(futu_auth_pipeline::FilterRegistry::with_defaults()),
93 admin_status_provider: None,
94 admin_shutdown_handler: None,
95 admin_reload_handler: None,
96 push_health_snapshot_provider: None,
97 card_num_resolver: None,
98 conn_id_counter: Arc::new(AtomicU64::new(10_000_000)),
99 serial_counter: Arc::new(AtomicU32::new(1)),
100 rest_acc_subscriptions: Arc::new(RwLock::new(HashMap::new())),
101 }
102 }
103
104 /// v1.4.104 阶段 7-1: 注入显式 FilterRegistry (跨 surface 共享同一份).
105 /// 默认 with_defaults 已注册 proto 2001; 此 setter 让调用方覆盖.
106 pub fn with_filter_registry(
107 mut self,
108 registry: Arc<futu_auth_pipeline::FilterRegistry>,
109 ) -> Self {
110 self.filter_registry = registry;
111 self
112 }
113
114 /// v1.4.32+ 注入 admin status provider(一般在 futu-opend main 里
115 /// 注入一个捕获 `Arc<GatewayBridge>` 的 closure)。
116 pub fn with_admin_status_provider(mut self, provider: AdminStatusProvider) -> Self {
117 self.admin_status_provider = Some(provider);
118 self
119 }
120
121 /// v1.4.111 注入 admin shutdown handler。
122 pub fn with_admin_shutdown_handler(mut self, handler: AdminShutdownHandler) -> Self {
123 self.admin_shutdown_handler = Some(handler);
124 self
125 }
126
127 /// v1.4.32+ 注入 admin reload handler
128 pub fn with_admin_reload_handler(mut self, handler: AdminReloadHandler) -> Self {
129 self.admin_reload_handler = Some(handler);
130 self
131 }
132
133 /// v1.4.83 §9 Phase 2 F5: 注入 push health snapshot provider.
134 pub fn with_push_health_snapshot_provider(
135 mut self,
136 provider: PushHealthSnapshotProvider,
137 ) -> Self {
138 self.push_health_snapshot_provider = Some(provider);
139 self
140 }
141
142 /// v1.4.105 D12 (Phase 2): 注入 card_num → acc_ids 解析器 closure.
143 /// opend 启动时由 main.rs 注入捕获 `bridge.caches.trd_cache` 的 closure. 未注入
144 /// → trade endpoint 收 card_num 字段时 503 reject (loud).
145 pub fn with_card_num_resolver(mut self, resolver: CardNumResolver) -> Self {
146 self.card_num_resolver = Some(resolver);
147 self
148 }
149
150 /// 分配虚拟连接 ID
151 pub fn next_conn_id(&self) -> u64 {
152 self.conn_id_counter.fetch_add(1, Ordering::Relaxed)
153 }
154
155 /// 分配序列号
156 pub fn next_serial(&self) -> u32 {
157 self.serial_counter.fetch_add(1, Ordering::Relaxed)
158 }
159}