Skip to main content

flare_core/server/connection/manager/
mod.rs

1//! 连接管理器模块
2//!
3//! 提供连接的统一管理、存储和查询功能
4//! 支持按连接 ID、用户 ID 等方式管理连接
5
6use crate::common::error::{FlareError, Result};
7use crate::server::connection::r#trait::{
8    ConnectionManagerTrait, ConnectionStats as TraitConnectionStats,
9};
10use crate::transport::connection::Connection;
11use async_trait::async_trait;
12use futures_util::stream::{self, StreamExt};
13use std::collections::{HashMap, hash_map::DefaultHasher};
14use std::hash::{Hash, Hasher};
15use std::sync::{
16    Arc, RwLock, Weak,
17    atomic::{AtomicUsize, Ordering},
18};
19use std::time::{Duration, Instant};
20use tokio::sync::{Mutex, mpsc};
21
22const DEFAULT_FANOUT_CONCURRENCY: usize = 256;
23const DEFAULT_SEND_TIMEOUT: Duration = Duration::from_secs(10);
24const DEFAULT_WRITE_QUEUE_CAPACITY: usize = 1024;
25const CONNECTION_SHARD_COUNT: usize = 64;
26const USER_CONNECTION_SHARD_COUNT: usize = 64;
27
28type ConnectionHandle = Arc<Mutex<Box<dyn Connection>>>;
29type ConnectionWriteHandle = Arc<ConnectionWriteQueue>;
30type ConnectionEntry = (ConnectionHandle, ConnectionWriteHandle, ConnectionInfo);
31type ConnectionHandleSnapshot = (String, ConnectionWriteHandle);
32type ConnectionAuthSnapshot = (String, ConnectionWriteHandle, bool);
33type ConnectionSnapshot = (String, ConnectionWriteHandle, ConnectionInfo);
34type TimeoutConnectionSnapshot = (String, ConnectionHandle, Option<String>);
35type ConnectionShard = RwLock<HashMap<String, ConnectionEntry>>;
36type UserConnectionShard = RwLock<HashMap<String, Vec<String>>>;
37
38struct QueuedWrite {
39    data: Vec<u8>,
40}
41
42#[derive(Clone)]
43struct ConnectionRemovalRegistry {
44    connection_shards: Weak<Vec<ConnectionShard>>,
45    user_connection_shards: Weak<Vec<UserConnectionShard>>,
46    connection_count: Arc<AtomicUsize>,
47    user_count: Arc<AtomicUsize>,
48}
49
50impl ConnectionRemovalRegistry {
51    fn remove_connection(&self, connection_id: &str) -> bool {
52        let Some(connection_shards) = self.connection_shards.upgrade() else {
53            return false;
54        };
55        let shard_index = ConnectionManager::shard_index(connection_id, connection_shards.len());
56
57        let Ok(mut shard) = connection_shards[shard_index].write() else {
58            return false;
59        };
60
61        let Some((_, _, info)) = shard.remove(connection_id) else {
62            return false;
63        };
64        drop(shard);
65
66        self.connection_count.fetch_sub(1, Ordering::Relaxed);
67
68        if let Some(user_id) = info.user_id {
69            self.remove_user_connection(&user_id, connection_id);
70        }
71
72        true
73    }
74
75    fn remove_user_connection(&self, user_id: &str, connection_id: &str) {
76        let Some(user_connection_shards) = self.user_connection_shards.upgrade() else {
77            return;
78        };
79        let shard_index = ConnectionManager::shard_index(user_id, user_connection_shards.len());
80
81        let Ok(mut shard) = user_connection_shards[shard_index].write() else {
82            return;
83        };
84
85        if ConnectionManager::remove_user_connection_index(&mut shard, user_id, connection_id) {
86            self.user_count.fetch_sub(1, Ordering::Relaxed);
87        }
88    }
89}
90
91struct ConnectionWriteQueue {
92    sender: mpsc::Sender<QueuedWrite>,
93    receiver: std::sync::Mutex<Option<mpsc::Receiver<QueuedWrite>>>,
94    connection: ConnectionHandle,
95    closed: Arc<std::sync::atomic::AtomicBool>,
96    writer_started: std::sync::atomic::AtomicBool,
97    connection_id: String,
98    send_timeout: Duration,
99    removal_registry: ConnectionRemovalRegistry,
100}
101
102impl ConnectionWriteQueue {
103    fn new(
104        connection_id: String,
105        connection: ConnectionHandle,
106        send_timeout: Duration,
107        queue_capacity: usize,
108        removal_registry: ConnectionRemovalRegistry,
109    ) -> ConnectionWriteHandle {
110        let (sender, receiver) = mpsc::channel(queue_capacity.max(1));
111        let closed = Arc::new(std::sync::atomic::AtomicBool::new(false));
112        Arc::new(Self {
113            sender,
114            receiver: std::sync::Mutex::new(Some(receiver)),
115            connection: Arc::clone(&connection),
116            closed: Arc::clone(&closed),
117            connection_id,
118            send_timeout,
119            removal_registry,
120            writer_started: std::sync::atomic::AtomicBool::new(false),
121        })
122    }
123
124    fn ensure_writer_started(&self) -> Result<()> {
125        if self.writer_started.load(Ordering::Acquire) {
126            return Ok(());
127        }
128
129        let handle = tokio::runtime::Handle::try_current().map_err(|_| {
130            FlareError::connection_failed("Connection write queue requires a Tokio runtime")
131        })?;
132
133        if self
134            .writer_started
135            .compare_exchange(false, true, Ordering::AcqRel, Ordering::Acquire)
136            .is_err()
137        {
138            return Ok(());
139        }
140
141        let Some(receiver) = self
142            .receiver
143            .lock()
144            .ok()
145            .and_then(|mut receiver| receiver.take())
146        else {
147            self.closed.store(true, Ordering::Release);
148            return Err(FlareError::connection_closed(
149                "Connection write queue receiver is unavailable",
150            ));
151        };
152
153        handle.spawn(Self::writer_task(
154            self.connection_id.clone(),
155            Arc::clone(&self.connection),
156            receiver,
157            self.send_timeout,
158            Arc::clone(&self.closed),
159            self.removal_registry.clone(),
160        ));
161
162        Ok(())
163    }
164
165    fn try_enqueue(&self, data: &[u8]) -> Result<()> {
166        if self.closed.load(Ordering::Acquire) {
167            return Err(FlareError::connection_closed(
168                "Connection write queue is closed",
169            ));
170        }
171        self.ensure_writer_started()?;
172
173        self.sender
174            .try_send(QueuedWrite {
175                data: data.to_vec(),
176            })
177            .map_err(|err| match err {
178                mpsc::error::TrySendError::Full(_) => {
179                    FlareError::connection_timeout("Connection write queue is full")
180                }
181                mpsc::error::TrySendError::Closed(_) => {
182                    FlareError::connection_closed("Connection write queue is closed")
183                }
184            })
185    }
186
187    fn mark_closed(&self) -> bool {
188        !self.closed.swap(true, Ordering::AcqRel)
189    }
190
191    fn close_underlying_in_background(&self) {
192        if !self.mark_closed() {
193            return;
194        }
195
196        if tokio::runtime::Handle::try_current().is_err() {
197            return;
198        }
199
200        let connection = Arc::clone(&self.connection);
201        tokio::spawn(async move {
202            let mut conn = connection.lock().await;
203            let _ = conn.close().await;
204        });
205    }
206
207    async fn writer_task(
208        connection_id: String,
209        connection: ConnectionHandle,
210        mut receiver: mpsc::Receiver<QueuedWrite>,
211        send_timeout: Duration,
212        closed: Arc<std::sync::atomic::AtomicBool>,
213        removal_registry: ConnectionRemovalRegistry,
214    ) {
215        while let Some(write) = receiver.recv().await {
216            if closed.load(Ordering::Acquire) {
217                break;
218            }
219
220            let result = {
221                let mut conn = connection.lock().await;
222                tokio::time::timeout(send_timeout, conn.send(&write.data)).await
223            };
224
225            match result {
226                Ok(Ok(())) => {}
227                Ok(Err(err)) => {
228                    closed.store(true, Ordering::Release);
229                    tracing::warn!(
230                        connection_id = %connection_id,
231                        error = ?err,
232                        "Connection writer failed; isolating connection"
233                    );
234                    let mut conn = connection.lock().await;
235                    let _ = conn.close().await;
236                    removal_registry.remove_connection(&connection_id);
237                    break;
238                }
239                Err(_) => {
240                    closed.store(true, Ordering::Release);
241                    tracing::warn!(
242                        connection_id = %connection_id,
243                        timeout = ?send_timeout,
244                        "Connection writer timed out; isolating connection"
245                    );
246                    let mut conn = connection.lock().await;
247                    let _ = conn.close().await;
248                    removal_registry.remove_connection(&connection_id);
249                    break;
250                }
251            }
252        }
253    }
254}
255
256/// 连接信息
257#[derive(Clone)]
258pub struct ConnectionInfo {
259    /// 连接 ID(唯一标识符)
260    pub connection_id: String,
261    /// 用户 ID(如果已认证)
262    pub user_id: Option<String>,
263    /// 创建时间
264    pub created_at: Instant,
265    /// 最后活跃时间
266    pub last_active: Instant,
267    /// 连接元数据
268    pub metadata: HashMap<String, String>,
269    /// 设备信息(如果已提供)
270    pub device_info: Option<crate::common::device::DeviceInfo>,
271    /// 序列化格式(由客户端协商决定,默认 JSON)
272    pub serialization_format: crate::common::protocol::SerializationFormat,
273    /// 压缩算法(由客户端协商决定,默认不压缩)
274    pub compression: crate::common::compression::CompressionAlgorithm,
275    /// 加密凡事(协商决定)
276    pub encryption: crate::common::encryption::EncryptionAlgorithm,
277    /// 是否已验证(如果启用认证,只有已验证的连接才能收发消息)
278    pub authenticated: bool,
279    /// 认证时间戳(Unix 时间戳,秒,如果已验证)
280    pub authenticated_at: Option<u64>,
281    /// 协商是否已完成(CONNECT 和 CONNECT_ACK 完成)
282    pub negotiation_completed: bool,
283    /// 协商是否已确认(客户端收到 CONNECT_ACK 后发送确认,服务端收到后标记)
284    /// 确认后,消息必须严格按照协商好的方式处理,不再容错
285    pub negotiation_confirmed: bool,
286    /// 缓存的 MessageParser(协商完成后创建,避免每次消息处理都创建新的 parser)
287    pub cached_parser: Option<std::sync::Arc<crate::common::MessageParser>>,
288    /// 缓存的 MessagePipeline(协商完成后创建,如果配置了中间件或处理器)
289    pub cached_pipeline: Option<std::sync::Arc<crate::common::message::pipeline::MessagePipeline>>,
290}
291
292impl ConnectionInfo {
293    /// 创建新的连接信息
294    ///
295    /// # 参数
296    /// - `connection_id`: 连接 ID
297    /// - `requires_auth`: 是否需要认证(如果为 false,连接直接标记为已验证)
298    pub fn new(connection_id: String, requires_auth: bool) -> Self {
299        let now = Instant::now();
300        let authenticated = !requires_auth; // 如果不需要认证,直接标记为已验证
301        Self {
302            connection_id,
303            user_id: None,
304            created_at: now,
305            last_active: now,
306            metadata: HashMap::new(),
307            device_info: None,
308            // 默认使用 JSON 且不压缩(客户端可以协商)
309            serialization_format: crate::common::protocol::SerializationFormat::Json,
310            compression: crate::common::compression::CompressionAlgorithm::None,
311            encryption: crate::common::encryption::EncryptionAlgorithm::None,
312            authenticated,
313            authenticated_at: authenticated.then(|| {
314                std::time::SystemTime::now()
315                    .duration_since(std::time::UNIX_EPOCH)
316                    .unwrap_or_default()
317                    .as_secs()
318            }),
319            negotiation_completed: false, // 初始状态:协商未完成
320            negotiation_confirmed: false, // 初始状态:协商未确认
321            cached_parser: None,          // 初始状态:未缓存 parser
322            cached_pipeline: None,        // 初始状态:未缓存 pipeline
323        }
324    }
325
326    /// 标记为已验证
327    pub fn set_authenticated(&mut self, user_id: Option<String>) {
328        self.authenticated = true;
329        self.authenticated_at = Some(
330            std::time::SystemTime::now()
331                .duration_since(std::time::UNIX_EPOCH)
332                .unwrap_or_default()
333                .as_secs(),
334        );
335        if let Some(uid) = user_id {
336            self.user_id = Some(uid);
337        }
338    }
339
340    /// 检查连接是否已验证
341    pub fn is_authenticated(&self) -> bool {
342        self.authenticated
343    }
344
345    /// 设置设备信息
346    pub fn with_device_info(mut self, device_info: crate::common::device::DeviceInfo) -> Self {
347        self.device_info = Some(device_info);
348        self
349    }
350
351    /// 设置序列化格式
352    pub fn with_serialization_format(
353        mut self,
354        format: crate::common::protocol::SerializationFormat,
355    ) -> Self {
356        self.serialization_format = format;
357        self
358    }
359
360    /// 设置压缩算法
361    pub fn with_compression(
362        mut self,
363        compression: crate::common::compression::CompressionAlgorithm,
364    ) -> Self {
365        self.compression = compression;
366        self
367    }
368
369    /// 检查连接是否超时
370    pub fn is_timeout(&self, timeout: Duration) -> bool {
371        self.last_active.elapsed() > timeout
372    }
373
374    /// 更新最后活跃时间
375    pub fn update_active(&mut self) {
376        self.last_active = Instant::now();
377    }
378}
379
380/// 连接管理器
381///
382/// 管理所有活跃连接,支持按 ID 查询、按用户 ID 查询等功能
383pub struct ConnectionManager {
384    /// 分片连接存储:connection_id -> (Connection, ConnectionInfo)
385    connection_shards: Arc<Vec<ConnectionShard>>,
386    /// 分片用户连接索引:user_id -> connection_ids
387    user_connection_shards: Arc<Vec<UserConnectionShard>>,
388    /// 当前连接数。高频读路径不应抢全局连接表锁。
389    connection_count: Arc<AtomicUsize>,
390    /// 当前有连接绑定的用户数。指标采集不应抢用户索引锁。
391    user_count: Arc<AtomicUsize>,
392    /// 单次底层写入超时时间
393    send_timeout: Duration,
394    /// fanout 发送最大并发度
395    fanout_concurrency: usize,
396    /// 每连接写队列容量
397    write_queue_capacity: usize,
398}
399
400impl Default for ConnectionManager {
401    fn default() -> Self {
402        Self::new()
403    }
404}
405
406mod lifecycle;
407mod ops;
408#[cfg(test)]
409mod tests;
410mod trait_impl;