Skip to main content

flare_core/client/builder/
flare.rs

1//! Flare 模式客户端构建器
2//!
3//! 提供完整功能实现,包含所有 `common` 和 `client` 模块的能力,推荐用于生产环境。
4//!
5//! ## 特点
6//! - ✅ **实现 `MessageListener` trait(必需)**:提供统一的消息处理接口
7//! - ✅ **消息管道**:自动处理序列化、压缩、加密
8//! - ✅ **中间件支持**:日志、性能监控、验证等
9//! - ✅ **处理器链**:可组合多个处理器
10//! - ✅ **序列化协商**:自动协商最佳序列化格式(JSON/Protobuf)和压缩算法(None/Gzip/Zstd)
11//! - ✅ **心跳管理**:自动心跳和超时管理
12//! - ✅ **自动重连**:支持断线重连
13//! - ✅ **多协议支持**:WebSocket + QUIC 双协议竞速
14//! - ✅ **统一事件处理**:使用 Observer 模式统一处理所有事件(连接事件、消息事件等)
15//!
16//! ## 适用场景
17//! - 生产环境
18//! - 需要完整功能的企业应用
19//! - 需要高性能和可扩展性的场景
20//! - 需要统一消息处理流程的场景
21//!
22//! ## 架构说明
23//!
24//! Flare 模式基于 `HybridClient`,使用 `MessagePipeline` 提供统一的消息处理流程。
25//! 消息管道支持中间件、自动序列化/压缩、加密等功能,同时保持与底层实现的统一。
26
27#[cfg(not(target_arch = "wasm32"))]
28use crate::client::HybridClient;
29#[cfg(target_arch = "wasm32")]
30use crate::client::WebSocketClient;
31use crate::client::builder::{BaseClientBuilderConfig, ClientWrapper};
32use crate::common::MessageParser;
33use crate::common::config_types::{HeartbeatAppState, HeartbeatConfig};
34use crate::common::error::Result;
35use crate::common::message::{
36    ArcMessageMiddleware, ArcMessageProcessor, MessageContext, MessagePipeline, MessageProcessor,
37};
38use crate::common::protocol::Frame;
39use crate::common::protocol::flare::core::commands::command::Type as CommandType;
40use crate::transport::events::{ConnectionEvent, ConnectionObserver};
41use async_trait::async_trait;
42use std::sync::Arc;
43use tokio::sync::Mutex;
44use tracing::{debug, error, info, warn};
45
46/// 消息监听器
47///
48/// 用户只需要实现这个简单的接口就能处理消息
49#[async_trait]
50pub trait MessageListener: Send + Sync {
51    /// 处理收到的消息
52    ///
53    /// # 参数
54    /// - `frame`: 收到的消息 Frame
55    ///
56    /// # 返回
57    /// - `Ok(Some(Frame))`: 需要发送的响应
58    /// - `Ok(None)`: 不需要响应
59    /// - `Err`: 处理失败
60    async fn on_message(&self, frame: &Frame) -> Result<Option<Frame>> {
61        let _ = frame;
62        Ok(None)
63    }
64
65    /// 连接建立时调用
66    async fn on_connect(&self) -> Result<()> {
67        Ok(())
68    }
69
70    /// 连接断开时调用
71    async fn on_disconnect(&self, reason: Option<&str>) -> Result<()> {
72        let _ = reason;
73        Ok(())
74    }
75
76    /// 连接错误时调用
77    async fn on_error(&self, error: &str) -> Result<()> {
78        let _ = error;
79        Ok(())
80    }
81}
82
83/// Flare 模式客户端构建器
84///
85/// 提供完整功能实现的客户端构建器
86///
87/// 用户需要实现 `MessageListener` trait,框架会自动处理消息序列化、压缩、加密和心跳管理
88/// - 压缩/解压
89/// - 加密/解密
90/// - 心跳管理
91/// - 自动重连
92pub struct FlareClientBuilder {
93    base: BaseClientBuilderConfig,
94    listener: Option<Arc<dyn MessageListener>>,
95    middlewares: Vec<ArcMessageMiddleware>,
96    processors: Vec<ArcMessageProcessor>,
97    observers: Vec<Arc<dyn ConnectionObserver>>,
98}
99
100impl FlareClientBuilder {
101    /// 创建新的 Flare 客户端构建器
102    pub fn new(server_url: impl Into<String>) -> Self {
103        Self {
104            base: BaseClientBuilderConfig::new(server_url),
105            listener: None,
106            middlewares: Vec::new(),
107            processors: Vec::new(),
108            observers: Vec::new(),
109        }
110    }
111
112    /// 设置消息监听器(必须)
113    pub fn with_listener(mut self, listener: Arc<dyn MessageListener>) -> Self {
114        self.listener = Some(listener);
115        self
116    }
117
118    /// 添加中间件
119    pub fn with_middleware(mut self, middleware: ArcMessageMiddleware) -> Self {
120        self.middlewares.push(middleware);
121        self
122    }
123
124    /// 添加处理器
125    pub fn with_processor(mut self, processor: ArcMessageProcessor) -> Self {
126        self.processors.push(processor);
127        self
128    }
129
130    /// 添加连接观察者(可选)
131    ///
132    /// 观察者会收到连接事件(Connected、Disconnected、Error、Message)
133    ///
134    /// 添加连接观察者
135    ///
136    /// 观察者会收到连接事件(Connected、Disconnected、Error、Message)
137    ///
138    /// ## 示例
139    ///
140    /// ```rust,no_run
141    /// use flare_core::client::builder::flare::FlareClientBuilder;
142    /// use flare_core::transport::events::{ConnectionObserver, ConnectionEvent};
143    /// use std::sync::Arc;
144    ///
145    /// struct MyObserver;
146    ///
147    /// impl ConnectionObserver for MyObserver {
148    ///     fn on_event(&self, event: &ConnectionEvent) {
149    ///         match event {
150    ///             ConnectionEvent::Connected => {
151    ///                 println!("已连接");
152    ///             }
153    ///             ConnectionEvent::Disconnected(reason) => {
154    ///                 println!("连接断开: {}", reason);
155    ///             }
156    ///             ConnectionEvent::Message(data) => {
157    ///                 // 处理原始消息数据
158    ///                 println!("收到消息: {} bytes", data.len());
159    ///             }
160    ///             ConnectionEvent::Error(err) => {
161    ///                 println!("连接错误: {:?}", err);
162    ///             }
163    ///         }
164    ///     }
165    /// }
166    ///
167    /// let builder = FlareClientBuilder::new("ws://127.0.0.1:8080")
168    ///     .with_observer(Arc::new(MyObserver));
169    /// ```
170    pub fn with_observer(mut self, observer: Arc<dyn ConnectionObserver>) -> Self {
171        self.observers.push(observer);
172        self
173    }
174
175    // ============================================================
176    // 配置方法(委托给 BaseClientBuilderConfig)
177    // ============================================================
178
179    /// 设置传输协议
180    pub fn with_protocol(
181        mut self,
182        protocol: crate::common::config_types::TransportProtocol,
183    ) -> Self {
184        self.base = self.base.with_protocol(protocol);
185        self
186    }
187
188    /// 启用多协议竞速
189    pub fn with_protocol_race(
190        mut self,
191        protocols: Vec<crate::common::config_types::TransportProtocol>,
192    ) -> Self {
193        self.base = self.base.with_protocol_race(protocols);
194        self
195    }
196
197    /// 为特定协议设置服务器地址
198    pub fn with_protocol_url(
199        mut self,
200        protocol: crate::common::config_types::TransportProtocol,
201        url: String,
202    ) -> Self {
203        self.base = self.base.with_protocol_url(protocol, url);
204        self
205    }
206
207    /// 设置用户 ID
208    pub fn with_user_id(mut self, user_id: String) -> Self {
209        self.base = self.base.with_user_id(user_id);
210        self
211    }
212
213    /// 设置序列化格式
214    pub fn with_format(mut self, format: crate::common::protocol::SerializationFormat) -> Self {
215        self.base = self.base.with_format(format);
216        self
217    }
218
219    /// 设置压缩算法
220    pub fn with_compression(
221        mut self,
222        compression: crate::common::compression::CompressionAlgorithm,
223    ) -> Self {
224        self.base = self.base.with_compression(compression);
225        self
226    }
227
228    /// 强制指定序列化格式
229    pub fn force_format(mut self, format: crate::common::protocol::SerializationFormat) -> Self {
230        self.base = self.base.force_format(format);
231        self
232    }
233
234    /// 强制指定压缩算法
235    pub fn force_compression(
236        mut self,
237        compression: crate::common::compression::CompressionAlgorithm,
238    ) -> Self {
239        self.base = self.base.force_compression(compression);
240        self
241    }
242
243    /// 设置设备信息
244    pub fn with_device_info(mut self, device_info: crate::common::device::DeviceInfo) -> Self {
245        self.base = self.base.with_device_info(device_info);
246        self
247    }
248
249    /// 设置心跳配置
250    pub fn with_heartbeat(
251        mut self,
252        heartbeat: crate::common::config_types::HeartbeatConfig,
253    ) -> Self {
254        self.base = self.base.with_heartbeat(heartbeat);
255        self
256    }
257
258    /// 设置 TLS 配置
259    pub fn with_tls(mut self, tls: crate::common::config_types::TlsConfig) -> Self {
260        self.base = self.base.with_tls(tls);
261        self
262    }
263
264    /// 设置连接超时
265    pub fn with_connect_timeout(mut self, timeout: std::time::Duration) -> Self {
266        self.base = self.base.with_connect_timeout(timeout);
267        self
268    }
269
270    /// 设置协议竞速超时
271    pub fn with_race_timeout(mut self, timeout: std::time::Duration) -> Self {
272        self.base = self.base.with_race_timeout(timeout);
273        self
274    }
275
276    /// 设置重连间隔
277    pub fn with_reconnect_interval(mut self, interval: std::time::Duration) -> Self {
278        self.base = self.base.with_reconnect_interval(interval);
279        self
280    }
281
282    /// 设置最大重连次数
283    pub fn with_max_reconnect_attempts(mut self, attempts: Option<u32>) -> Self {
284        self.base = self.base.with_max_reconnect_attempts(attempts);
285        self
286    }
287
288    /// 设置 Token(用于认证)
289    pub fn with_token(mut self, token: String) -> Self {
290        self.base = self.base.with_token(token);
291        self
292    }
293
294    /// 启用消息路由
295    pub fn enable_router(mut self) -> Self {
296        self.base = self.base.enable_router();
297        self
298    }
299
300    /// 构建客户端(使用协议竞速)
301    pub async fn build_with_race(self) -> Result<FlareClient> {
302        let listener = self.listener.ok_or_else(|| {
303            crate::common::error::FlareError::protocol_error(
304                "MessageListener is required".to_string(),
305            )
306        })?;
307
308        use crate::common::message::parser::PRE_NEGOTIATION_PARSER;
309
310        // WASM: 先建连再初始化 pipeline,避免在 LocalSet 驱动尚未打开 WS 前卡在 pipeline.await。
311        #[cfg(target_arch = "wasm32")]
312        let client = WebSocketClient::connect_with_config(self.base.config.clone()).await?;
313
314        let pipeline = Arc::new(Mutex::new(MessagePipeline::new(
315            PRE_NEGOTIATION_PARSER.clone(),
316        )));
317
318        for middleware in self.middlewares {
319            pipeline.lock().await.add_middleware(middleware).await;
320        }
321
322        let listener_processor = Arc::new(ListenerProcessor {
323            listener: listener.clone(),
324        });
325        pipeline
326            .lock()
327            .await
328            .add_processor(listener_processor)
329            .await;
330
331        for processor in self.processors {
332            pipeline.lock().await.add_processor(processor).await;
333        }
334
335        #[cfg(not(target_arch = "wasm32"))]
336        let client = HybridClient::connect_with_race(self.base.config.clone()).await?;
337
338        let wrapper = ClientWrapper::new(client);
339
340        // 创建观察者(集成消息管道)
341        let observer = Arc::new(FlareObserver {
342            pipeline: pipeline.clone(),
343            listener: listener.clone(),
344        });
345
346        let observer_clone = observer.clone();
347
348        // 添加观察者(FlareObserver 和用户提供的 observers)
349        // 注意:统一使用 Observer 模式,不再使用 event_handler
350        // 所有事件处理都通过 Observer 完成,更符合 IM SDK 的最佳实践
351        wrapper.add_observer(observer_clone).await;
352        for observer in self.observers {
353            wrapper.add_observer(observer).await;
354        }
355
356        wrapper
357            .wait_for_negotiation(std::time::Duration::from_secs(10))
358            .await?;
359        let parser = wrapper.parser_snapshot().await;
360        pipeline.lock().await.update_parser(parser).await;
361
362        Ok(FlareClient {
363            wrapper,
364            pipeline,
365            listener,
366        })
367    }
368}
369
370/// Flare 客户端
371#[derive(Clone)]
372pub struct FlareClient {
373    wrapper: ClientWrapper,
374    #[allow(dead_code)] // 保留用于未来扩展(如动态更新管道配置)
375    pipeline: Arc<Mutex<MessagePipeline>>,
376    #[allow(dead_code)] // 保留用于未来扩展(如动态更新监听器)
377    listener: Arc<dyn MessageListener>,
378}
379
380impl FlareClient {
381    /// 发送消息 Frame
382    pub async fn send_frame(&self, frame: &Frame) -> Result<()> {
383        self.wrapper.send_frame(frame).await
384    }
385
386    /// 发送并等待响应(按 message_id 匹配)
387    pub async fn send_frame_and_wait(
388        &self,
389        frame: &Frame,
390        timeout: std::time::Duration,
391    ) -> Result<Frame> {
392        self.wrapper.send_frame_and_wait(frame, timeout).await
393    }
394
395    /// 检查是否已连接(native 同步;WASM 请用 [`Self::is_connected_async`])
396    #[cfg(not(target_arch = "wasm32"))]
397    pub fn is_connected(&self) -> bool {
398        crate::client::runtime::run_client_async(self.is_connected_async())
399    }
400
401    /// 检查是否已连接(async,全平台)
402    pub async fn is_connected_async(&self) -> bool {
403        self.wrapper.is_connected_async().await
404    }
405
406    /// 断开连接
407    pub async fn disconnect(self) -> Result<()> {
408        self.wrapper.disconnect().await
409    }
410
411    /// 获取连接 ID(native 同步;WASM 请用 [`Self::connection_id_async`])
412    #[cfg(not(target_arch = "wasm32"))]
413    pub fn connection_id(&self) -> Option<String> {
414        crate::client::runtime::run_client_async(self.connection_id_async())
415    }
416
417    /// 获取连接 ID(async,全平台)
418    pub async fn connection_id_async(&self) -> Option<String> {
419        self.wrapper.connection_id_async().await
420    }
421
422    /// 获取协商后的消息解析器快照
423    pub async fn parser_snapshot(&self) -> MessageParser {
424        self.wrapper.parser_snapshot().await
425    }
426
427    /// 获取活动协议
428    pub fn active_protocol(&self) -> crate::common::config_types::TransportProtocol {
429        self.wrapper.active_protocol()
430    }
431
432    /// 运行期替换心跳策略。
433    pub async fn update_heartbeat_config(&self, config: HeartbeatConfig) {
434        self.wrapper.update_heartbeat_config(config).await;
435    }
436
437    /// 更新应用前后台状态。移动端进入后台时可拉长心跳,回到前台时恢复较短心跳。
438    pub async fn set_heartbeat_app_state(&self, state: HeartbeatAppState) {
439        self.wrapper.set_heartbeat_app_state(state).await;
440    }
441
442    /// 更新 NAT 空闲超时探测结果。传入 `None` 表示清除探测值。
443    pub async fn set_heartbeat_nat_timeout(&self, timeout: Option<std::time::Duration>) {
444        self.wrapper.set_heartbeat_nat_timeout(timeout).await;
445    }
446
447    /// 当前实际心跳间隔。
448    pub async fn heartbeat_effective_interval(&self) -> std::time::Duration {
449        self.wrapper.heartbeat_effective_interval().await
450    }
451
452    /// 更新消息管道解析器(协商完成后调用)
453    pub async fn update_parser(&self, parser: MessageParser) {
454        let mut pipeline = self.pipeline.lock().await;
455        *pipeline = MessagePipeline::new(parser);
456    }
457
458    /// 添加连接观察者
459    ///
460    /// 观察者会收到连接事件(Connected、Disconnected、Error、Message)
461    pub async fn add_observer(&self, observer: Arc<dyn ConnectionObserver>) {
462        self.wrapper.add_observer(observer).await;
463    }
464}
465
466/// Flare 客户端观察者
467struct FlareObserver {
468    pipeline: Arc<Mutex<MessagePipeline>>,
469    listener: Arc<dyn MessageListener>,
470}
471
472impl ConnectionObserver for FlareObserver {
473    fn on_event(&self, event: &ConnectionEvent) {
474        match event {
475            ConnectionEvent::Connected => {
476                info!("[FlareClient] ✅ 已连接");
477                // 在后台任务中调用 listener.on_connect
478                let listener = self.listener.clone();
479                crate::client::runtime::spawn_client_task(async move {
480                    if let Err(e) = listener.on_connect().await {
481                        error!("[FlareClient] on_connect 失败: {}", e);
482                    }
483                });
484            }
485
486            ConnectionEvent::Disconnected(reason) => {
487                // 使用 Arc<str> 避免 String clone,减少内存分配
488                let reason_arc: Arc<str> = Arc::from(reason.as_str());
489                info!("[FlareClient] ❌ 连接断开: {}", reason_arc);
490                let listener = self.listener.clone();
491                crate::client::runtime::spawn_client_task(async move {
492                    if let Err(e) = listener.on_disconnect(Some(&reason_arc)).await {
493                        error!("[FlareClient] on_disconnect 失败: {}", e);
494                    }
495                });
496            }
497
498            ConnectionEvent::Error(err) => {
499                // 过滤协议竞速时关闭未选中连接导致的错误
500                // 这些错误是正常的,因为协议竞速会选择最快的协议,其他协议会被关闭
501                let err_str = format!("{:?}", err);
502                // 协议竞速错误:关闭未选中连接时的正常错误
503                let is_race_error = err_str.contains("Connection reset without closing handshake")
504                    || (err_str.contains("ConnectionFailed")
505                        && err_str.contains("WebSocket protocol error"));
506
507                // 连接丢失错误:可能是网络问题或服务器关闭连接
508                let is_connection_lost = err_str.contains("connection lost")
509                    || err_str.contains("connection closed")
510                    || err_str.contains("Connection reset");
511
512                if is_race_error {
513                    // 协议竞速相关的错误,只记录 debug 级别(不通知 listener)
514                    debug!(
515                        "[FlareClient] 协议竞速:未选中协议连接已关闭(这是正常的,协议竞速会选择最快的协议)"
516                    );
517                } else if is_connection_lost {
518                    // 连接丢失错误,记录为 warn 级别并通知 listener
519                    // 注意:底层客户端(WebSocketClient/QUICClient)会自动尝试重连
520                    warn!("[FlareClient] 连接丢失: {:?}", err);
521                    info!("[FlareClient] 💡 底层客户端将自动尝试重连(如果配置了重连)");
522                    let listener = self.listener.clone();
523                    // 使用 Arc<str> 避免 String clone,减少内存分配
524                    let err_str_arc: Arc<str> = Arc::from(err_str.as_str());
525                    crate::client::runtime::spawn_client_task(async move {
526                        if let Err(e) = listener.on_error(&err_str_arc).await {
527                            error!("[FlareClient] on_error 失败: {}", e);
528                        }
529                    });
530                } else {
531                    // 其他错误,正常记录并通知 listener
532                    warn!("[FlareClient] 连接错误: {:?}", err);
533                    let listener = self.listener.clone();
534                    // 使用 Arc<str> 避免 String clone,减少内存分配
535                    let err_str_arc: Arc<str> = Arc::from(err_str.as_str());
536                    crate::client::runtime::spawn_client_task(async move {
537                        if let Err(e) = listener.on_error(&err_str_arc).await {
538                            error!("[FlareClient] on_error 失败: {}", e);
539                        }
540                    });
541                }
542            }
543
544            ConnectionEvent::Message(data) => {
545                // 先尝试用 PRE_NEGOTIATION_PARSER 解析,检查是否是 CONNECT_ACK 消息
546                // CONNECT_ACK 消息必须使用 PRE_NEGOTIATION_PARSER(JSON、不压缩、不加密)
547                use crate::common::message::parser::PRE_NEGOTIATION_PARSER;
548                use crate::common::protocol::flare::core::commands::system_command::Type as SysType;
549
550                let pipeline = self.pipeline.clone();
551                let data = data.clone();
552                crate::client::runtime::spawn_client_task(async move {
553                    // 1. 先尝试用 PRE_NEGOTIATION_PARSER 解析,检查是否是 CONNECT_ACK
554                    if let Ok(frame) = PRE_NEGOTIATION_PARSER.parse(&data)
555                        && let Some(cmd) = &frame.command
556                        && let Some(CommandType::System(sys_cmd)) = &cmd.r#type
557                        && sys_cmd.r#type == SysType::ConnectAck as i32
558                    {
559                        // 这是 CONNECT_ACK 消息,需要更新 MessagePipeline 的 parser
560                        // 从 CONNECT_ACK 中提取协商结果
561                        let format =
562                            crate::common::protocol::SerializationFormat::try_from(sys_cmd.format)
563                                .unwrap_or(crate::common::protocol::SerializationFormat::Json);
564                        let compression =
565                            crate::common::compression::CompressionAlgorithm::from_str(
566                                &sys_cmd.compression,
567                            )
568                            .unwrap_or(crate::common::compression::CompressionAlgorithm::None);
569                        let encryption = crate::common::encryption::EncryptionAlgorithm::from_str(
570                            &sys_cmd.encryption,
571                        )
572                        .unwrap_or(crate::common::encryption::EncryptionAlgorithm::None);
573
574                        // 更新 MessagePipeline 的 parser
575                        {
576                            let compression_clone = compression.clone();
577                            let encryption_clone = encryption.clone();
578                            let pipeline_guard = pipeline.lock().await;
579                            let new_parser =
580                                crate::common::MessageParser::new(format, compression, encryption);
581                            pipeline_guard.update_parser(new_parser).await;
582                            debug!(
583                                "[FlareObserver] ✅ 已更新 MessagePipeline 的 parser: format={:?}, compression={:?}, encryption={:?}",
584                                format, compression_clone, encryption_clone
585                            );
586                        }
587
588                        // 使用 PRE_NEGOTIATION_PARSER 解析的 frame 继续处理
589                        let pipeline_guard = pipeline.lock().await;
590                        match pipeline_guard.process_frame(&frame, None).await {
591                            Ok(Some(_response_data)) => {
592                                debug!(
593                                    "[FlareClient] 消息管道返回响应,但客户端无法自动发送,需要用户手动处理"
594                                );
595                            }
596                            Ok(None) => {
597                                debug!("[FlareClient] CONNECT_ACK 处理完成,无需响应");
598                            }
599                            Err(e) => {
600                                error!("[FlareClient] CONNECT_ACK 处理失败: {}", e);
601                            }
602                        }
603                        return;
604                    }
605
606                    // 2. 如果不是 CONNECT_ACK,使用 MessagePipeline 的 parser 解析
607                    let pipeline = pipeline.lock().await;
608                    match pipeline.process_raw(&data, None).await {
609                        Ok(Some(_response_data)) => {
610                            debug!(
611                                "[FlareClient] 消息管道返回响应,但客户端无法自动发送,需要用户手动处理"
612                            );
613                            // 注意:这里无法直接发送响应,因为需要访问 client
614                            // 用户应该在 listener.on_message 中返回响应 Frame
615                        }
616                        Ok(None) => {
617                            debug!("[FlareClient] 消息处理完成,无需响应");
618                        }
619                        Err(e) => {
620                            error!("[FlareClient] 消息管道处理失败: {}", e);
621                        }
622                    }
623                });
624            }
625        }
626    }
627}
628
629/// 监听器处理器
630struct ListenerProcessor {
631    listener: Arc<dyn MessageListener>,
632}
633
634#[async_trait]
635impl MessageProcessor for ListenerProcessor {
636    async fn process(&self, ctx: &MessageContext) -> Result<Option<Frame>> {
637        self.listener.on_message(&ctx.frame).await
638    }
639
640    fn name(&self) -> &str {
641        "ListenerProcessor"
642    }
643}