Skip to main content

hydra_sync/
server.rs

1//! Core implementation for the `HydraSync` server.
2use crate::channel::{ClosedError, FullError};
3use crate::client::ServerMetrics;
4use crate::crypto::{NONCE_LEN, TAG_LEN};
5use crate::protocol::StatusCode;
6use crate::protocol::{
7    Role, perform_server_handshake, read_join_header, write_server_metrics,
8    write_server_read_write_len, write_status_code,
9};
10use crate::session::SessionMap;
11use crate::{ChannelOverflowStrategy, START_TIME, error, get_uptime_hrs, info, trace, warn};
12use anyhow::Result;
13use bytes::BytesMut;
14use hex::encode;
15use std::net::SocketAddr;
16use std::ops::{Deref, DerefMut};
17use std::sync::Arc;
18use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
19use std::time::Duration;
20use tokio::io::{AsyncReadExt, AsyncWriteExt};
21use tokio::net::{TcpListener, TcpStream};
22use tokio::sync::Notify;
23
24/// Padded atomic64 to avoid false sharing on hot counters (64B cache line).
25#[repr(C, align(64))]
26struct PaddedAtomicU64(AtomicU64);
27impl PaddedAtomicU64 {
28    const fn pad(v: u64) -> Self {
29        Self(AtomicU64::new(v))
30    }
31}
32impl Deref for PaddedAtomicU64 {
33    type Target = AtomicU64;
34    fn deref(&self) -> &Self::Target {
35        &self.0
36    }
37}
38impl DerefMut for PaddedAtomicU64 {
39    fn deref_mut(&mut self) -> &mut Self::Target {
40        &mut self.0
41    }
42}
43
44/// `HydraServer`- A light-weight, E2E `(AES-GCM)`, multi-threaded SPMC broadcast server using `TCP`.
45/// It implements internal _ring buffer_ configured by [`HydraConfig`], uses **little memory** and **minimal copy** as possible.
46///
47/// ```no_run
48/// use hydra_sync::server::HydraServer;
49///
50/// #[tokio::main]
51/// async fn main() {
52///     let (server, addr) = HydraServer::bind_default().await.unwrap();
53///     println!("Server running on: {}", addr);
54///     let server_runner = server.clone();
55///     tokio::spawn(async move { server_runner.run().await }); // run in background
56///
57///     server.shutdown().await.unwrap(); // shutdown gracefully
58/// }
59/// ```
60pub struct HydraServer {
61    listener: TcpListener,
62    config: Arc<HydraConfig>,
63    /*
64    field below are used for collecting server metrics
65    */
66    /// Global session concurrent map.
67    session_map: Arc<SessionMap>,
68    /// Track the number of active connections to the server.
69    active_connections: Arc<AtomicU64>,
70    /// Total number of sessions ever created.
71    total_sessions: Arc<PaddedAtomicU64>,
72    /// Total number of bytes relayed through the server.
73    total_bytes: Arc<PaddedAtomicU64>,
74    /// Flag to indicate if the server is shutting down gracefully
75    /// (server will stop accepting new connections and wait for existing sessions to finish).
76    shutdown_flag: Arc<AtomicBool>,
77}
78
79/// Configuration for the `HydraServer` features.
80pub struct HydraConfig {
81    /// Maximum number of concurrent connections allowed.
82    pub max_connections: u64,
83    /// Timeout in milliseconds for accepting new connections when capacity is reached.
84    pub accept_timeout: u64,
85    /// Fixed length of a single packet/frame in bytes to read/write `(excluding AES-GCM overhead)`.
86    /// This length is used to `read/write EXACT` data from/to the network stream.
87    pub fixed_packet_length: u64,
88    /// Capacity of the internal channel for each session.
89    pub channel_capacity: u64,
90    /// Token for authenticating observer clients for getting [`ServerMetrics`] from server ring's buffer.
91    pub observer_token: Option<[u8; 64]>,
92    /// Strategy for handling channel overflow when consumers cannot keep up with producers.
93    pub overflow_mode: ChannelOverflowStrategy,
94}
95
96impl HydraConfig {
97    /// Creates `HydraConfig` with the specified parameters.
98    /// > NOTE: `fixed_packet_length` is the length of the plaintext data, the actual read/write length will be `fixed_packet_length + AES-GCM overhead (28 bytes)`.
99    /// > So this function adds the AES-GCM overhead to the `fixed_packet_length` (make sure to consider for it, if `HydraConfig` is constructed without calling this function).
100    pub fn config(
101        max_connections: u64,
102        accept_timeout: u64,
103        fixed_packet_length: u64,
104        channel_capacity: u64,
105        observer_token: Option<[u8; 64]>,
106        overflow_mode: ChannelOverflowStrategy,
107    ) -> Self {
108        if fixed_packet_length == 0 {
109            panic!("fixed_packet_length must be greater than 0");
110        }
111        Self {
112            max_connections,
113            accept_timeout,
114            fixed_packet_length: fixed_packet_length + (NONCE_LEN + TAG_LEN) as u64, // add aes-gcm overhead
115            channel_capacity,
116            observer_token,
117            overflow_mode,
118        }
119    }
120}
121
122impl Default for HydraConfig {
123    /// Default HydraConfig
124    /// - max_connections: 32
125    /// - accept_timeout: 500 ms
126    /// - fixed_packet_length: 4 MB + `AES-GCM overhead (28 bytes)`
127    /// - channel_capacity: 256
128    /// - observer_token: randomly generated
129    /// - overflow_mode: DropPacket
130    fn default() -> Self {
131        Self {
132            max_connections: 32,
133            accept_timeout: 500,
134            fixed_packet_length: (4 << 20) + (NONCE_LEN + TAG_LEN) as u64, // 4 MB + AES-GCM overhead
135            channel_capacity: 256,
136            observer_token: Some(rand::random::<[u8; 64]>()),
137            overflow_mode: ChannelOverflowStrategy::DropPacket,
138        }
139    }
140}
141
142impl HydraServer {
143    /// Binds the server with random local port and default [`HydraConfig`], returns the port.
144    pub async fn bind_default() -> Result<(Arc<Self>, SocketAddr)> {
145        let addr = "127.0.0.1:0".parse::<SocketAddr>()?;
146        let (server, server_addr) = HydraServer::bind(addr, HydraConfig::default()).await?;
147        Ok((server, server_addr))
148    }
149
150    /// Binds the server to the specified [`SocketAddr`] with the provided [`HydraConfig`].
151    pub async fn bind(
152        socket_addr: SocketAddr,
153        hydra_config: HydraConfig,
154    ) -> Result<(Arc<Self>, SocketAddr)> {
155        let server_tcp = TcpListener::bind(socket_addr).await?;
156        let server_addr = server_tcp.local_addr()?;
157        Ok((
158            Arc::new(Self {
159                listener: server_tcp,
160                config: Arc::new(hydra_config),
161                session_map: Arc::new(SessionMap::init()),
162                active_connections: Arc::new(AtomicU64::new(0)),
163                total_sessions: Arc::new(PaddedAtomicU64::pad(0)),
164                total_bytes: Arc::new(PaddedAtomicU64::pad(0)),
165                shutdown_flag: Arc::new(AtomicBool::new(false)),
166            }),
167            server_addr,
168        ))
169    }
170
171    /// Starts the server, accepting incoming connections and handling them concurrently.
172    /// Overview:
173    /// * Accept incoming `TCP connections`, spawn handler tasks and `allocate read/write buffers` or reject if max connections reached.
174    /// * Perform handshake, read/decrypt `JoinHeader`, determine role (Producer/Consumer/Admin).
175    /// * For Producers: Create valid session, read data (exactly **fixed_packet_length**, including `AES-GCM` (28 bytes) overhead, with `read_exact()`, so it may truncate)
176    ///   and broadcast `(cheap-copy)` to all Consumers in the session (Write behavior is configured by [`ChannelOverflowStrategy`]).
177    /// * For Consumers: Validate session, read from `local ring buffer` from producer handle, write to TCP stream.
178    /// * `LOG_LEVEL` & `LOG_FILE_DIR` env vars can be set to control `logging verbosity` and output file (defaults to `info` level and stdout and file).
179    /// * EOF check are gracefully handled by closing the connection without logging an error.
180    pub async fn run(&self) -> Result<()> {
181        START_TIME.set(chrono::Local::now()).ok();
182
183        loop {
184            // check shutdown token
185            if self.shutdown_flag.load(Ordering::Relaxed) {
186                // return if no active connections
187                if self.active_connections.load(Ordering::Relaxed) == 0 {
188                    return Ok(());
189                }
190                loop {
191                    // check current connections, every 3 seconds, wait for them to finish and return
192                    tokio::time::sleep(Duration::from_secs(3)).await;
193                    if self.active_connections.load(Ordering::Relaxed) > 0 {
194                        info!(
195                            "Server is shutting down, waiting for {} active connections to finish...",
196                            self.active_connections.load(Ordering::Relaxed)
197                        );
198                    } else {
199                        info!("Server has stopped.");
200                        return Ok(());
201                    }
202                }
203            }
204
205            if self.active_connections.fetch_add(1, Ordering::Relaxed)
206                >= self.config.max_connections
207            {
208                self.active_connections.fetch_sub(1, Ordering::Relaxed);
209                warn!(
210                    "Max connections reached: {}, waiting {} ms before accepting new connections",
211                    self.config.max_connections, self.config.accept_timeout
212                );
213                tokio::time::sleep(Duration::from_millis(self.config.accept_timeout)).await;
214                continue;
215            }
216
217            tokio::select! {
218                // accept new connection
219                result = self.listener.accept() => {
220                    match result {
221                        Ok((stream, peer_addr)) => {
222                            stream.set_nodelay(true).ok();
223                            let config = Arc::clone(&self.config);
224                            let session_map = Arc::clone(&self.session_map);
225                            let connections = Arc::clone(&self.active_connections);
226                            let total_sessions = Arc::clone(&self.total_sessions);
227                            let total_bytes = Arc::clone(&self.total_bytes);
228                            let is_shutting_down = Arc::clone(&self.shutdown_flag);
229                            // spawn client_handler task
230                            tokio::spawn(async move {
231                                trace!("Accepted connection from: {}", peer_addr);
232                                if let Err(e) = Self::handle_connection(
233                                    stream,
234                                    session_map,
235                                    config,
236                                    total_sessions,
237                                    total_bytes,
238                                    is_shutting_down,
239                                )
240                                .await
241                                {
242                                    error!("Connection handling error: {} from: {}", e, peer_addr);
243                                }
244                                connections.fetch_sub(1, Ordering::Release);
245                            });
246                        }
247                        Err(e) => {
248                            self.active_connections.fetch_sub(1, Ordering::Release);
249                            error!("Connection accepting error: {}", e);
250                        }
251                    }
252                }
253                // shutdown signal, then break blocking accept()
254                _ = async {
255                    while !self.shutdown_flag.load(Ordering::Relaxed) {
256                        tokio::time::sleep(Duration::from_millis(100)).await;
257                    }
258                } => {
259                    self.active_connections.fetch_sub(1, Ordering::Release);
260                    continue;
261                }
262            }
263        }
264    }
265
266    /// Handles an individual client connection.
267    async fn handle_connection(
268        mut stream: TcpStream,
269        sessions: Arc<SessionMap>,
270        config: Arc<HydraConfig>,
271        total_sessions: Arc<PaddedAtomicU64>,
272        total_bytes: Arc<PaddedAtomicU64>,
273        is_shutting_down: Arc<AtomicBool>,
274    ) -> Result<()> {
275        stream.set_nodelay(true).ok();
276        let client_addr = stream.peer_addr()?;
277        let (mut read_h, mut writer_h) = stream.split();
278        let mut read_buffer = BytesMut::zeroed(config.fixed_packet_length as usize);
279        let transport_key = perform_server_handshake(&mut read_h, &mut writer_h).await?;
280        let join_header = read_join_header(&mut read_h, &transport_key, &mut read_buffer).await?;
281
282        // determine role and handle accordingly
283        let role = match Role::from_u8(join_header.role) {
284            Ok(role) => {
285                info!(
286                    "Client (ip: {}) joined with role: {}, session_uuid: {}...",
287                    client_addr,
288                    role.to_string(),
289                    &encode(join_header.uuid_or_token)[..12]
290                );
291                role
292            }
293            Err(_) => {
294                warn!(
295                    "Client (ip: {}) joining with invalid role: {:#04x}",
296                    client_addr, join_header.role
297                );
298                write_status_code(
299                    &mut writer_h,
300                    StatusCode::ErrInvalidRole,
301                    &transport_key,
302                    &mut read_buffer,
303                )
304                .await?;
305                return Ok(());
306            }
307        };
308
309        // handle roles
310        match role {
311            Role::Producer => {
312                // create session for producer, if already exists, return error
313                if !sessions.try_create_session(join_header.uuid_or_token) {
314                    warn!(
315                        "Producer (ip: {}) failed to create session_uuid: {}...",
316                        client_addr,
317                        &encode(join_header.uuid_or_token)[..12]
318                    );
319
320                    // send error code
321                    write_status_code(
322                        &mut writer_h,
323                        StatusCode::ErrSessionAlreadyOccupied,
324                        &transport_key,
325                        &mut read_buffer,
326                    )
327                    .await?;
328                    return Ok(());
329                }
330
331                info!(
332                    "Producer (ip: {}) created session_uuid: {}...",
333                    client_addr,
334                    &encode(join_header.uuid_or_token)[..12]
335                );
336
337                total_sessions.fetch_add(1, Ordering::Relaxed);
338                // on successful session creation, send read_len to producer
339                write_status_code(
340                    &mut writer_h,
341                    StatusCode::Success,
342                    &transport_key,
343                    &mut read_buffer,
344                )
345                .await?;
346                write_server_read_write_len(
347                    &mut writer_h,
348                    config.fixed_packet_length - (NONCE_LEN + TAG_LEN) as u64, // announce raw payload capacity (encryption overhead is internal)
349                    &transport_key,
350                    &mut read_buffer,
351                )
352                .await?;
353
354                // read from producer and write to all consumers with fixed read_write len
355                let mut write_buffer = BytesMut::zeroed(config.fixed_packet_length as usize);
356                let mut dead_consumers = vec![]; // 'client to drop' collection
357                let mut pending_consumers = vec![]; // 'slow client' collection
358
359                loop {
360                    // react_exact to fill buf, this does not extend buf anyway,
361                    // this will return an error if the stream is closed or if it cannot fill the buffer exactly
362                    // 'reads' may get truncated and may send corrupted data to consumers
363                    match read_h.read_exact(&mut write_buffer).await {
364                        Ok(_) => {
365                            let data = write_buffer.split().freeze(); // zero-copy 'freeze' to Bytes
366
367                            // get session ref (TODO; get read lock, maybe block other map shards? idk)
368                            if let Some(session) =
369                                sessions.try_get_session(join_header.uuid_or_token)
370                            {
371                                // non-blocking pass over every consumer ring,
372                                // fast consumers are served immediately, regardless of where a
373                                // slow one sits in the (arbitrary) DashMap iteration order
374                                for mut entry in session.consumer_local_buffers.iter_mut() {
375                                    // rm consumers that disconnected and their rings
376                                    if entry.value_mut().is_closed() {
377                                        dead_consumers.push(*entry.key());
378                                        continue;
379                                    }
380                                    // broadcast away
381                                    let data_len = data.len() as u64;
382                                    match entry.value_mut().push(data.clone()) {
383                                        Ok(()) => {
384                                            total_bytes.fetch_add(data_len, Ordering::Relaxed);
385                                        }
386                                        Err(FullError) => match config.overflow_mode {
387                                            ChannelOverflowStrategy::DropPacket => {
388                                                // skip, don't push latest packet to local consumer queue
389                                            }
390                                            ChannelOverflowStrategy::DropClient => {
391                                                // collect the 'lagged' client
392                                                dead_consumers.push(*entry.key());
393                                            }
394                                            ChannelOverflowStrategy::BackPressure => {
395                                                // collect all slow consumer
396                                                pending_consumers.push(*entry.key());
397                                            }
398                                        },
399                                    }
400                                }
401
402                                // blocking delivery pass for full rings only,
403                                // parks until space frees up; woken by pop() or by the
404                                // consumer disconnecting by ClosedError
405                                for id in pending_consumers.drain(..) {
406                                    loop {
407                                        enum Step {
408                                            Pushed,
409                                            Remove,
410                                            Wait(Arc<Notify>),
411                                        }
412                                        let step: Step = 'lock: {
413                                            // get lock on the consumer ring, or remove the entry
414                                            let Some(mut entry) =
415                                                session.consumer_local_buffers.get_mut(&id)
416                                            else {
417                                                break 'lock Step::Remove;
418                                            };
419                                            // check if closed, or remove
420                                            let p = entry.value_mut();
421                                            if p.is_closed() {
422                                                break 'lock Step::Remove;
423                                            }
424                                            match p.push(data.clone()) {
425                                                Ok(()) => {
426                                                    total_bytes.fetch_add(
427                                                        data.len() as u64,
428                                                        Ordering::Relaxed,
429                                                    );
430                                                    Step::Pushed
431                                                }
432                                                Err(FullError) => Step::Wait(p.space_notify()),
433                                            }
434                                        };
435                                        match step {
436                                            Step::Pushed => break,
437                                            Step::Remove => {
438                                                dead_consumers.push(id);
439                                                break;
440                                            }
441                                            // no lock held here, the guard was dropped at 'lock
442                                            Step::Wait(notify) => notify.notified().await,
443                                        }
444                                    }
445                                }
446
447                                // remove dead consumer queues
448                                for id in dead_consumers.drain(..) {
449                                    session.consumer_local_buffers.remove(&id);
450                                }
451                            }
452
453                            write_buffer.resize(config.fixed_packet_length as usize, 0);
454                        }
455                        Err(_) => {
456                            error!(
457                                "Producer (ip: {}) read error, closing connection for session_uuid: {}...",
458                                client_addr,
459                                &encode(join_header.uuid_or_token)[..12]
460                            );
461                            break;
462                        }
463                    }
464                }
465
466                info!(
467                    "Producer (ip: {}) disconnected, removing session_uuid: {}...",
468                    client_addr,
469                    &encode(join_header.uuid_or_token)[..12]
470                );
471
472                // remove session and return (close stream) on disconnect or error
473                sessions.remove_session(join_header.uuid_or_token);
474            }
475
476            Role::Consumer => {
477                // check session exists, if not, return error
478                let session = match sessions.try_get_session(join_header.uuid_or_token) {
479                    Some(s) => s,
480                    None => {
481                        warn!(
482                            "Consumer (ip: {}) failed to join session_uuid: {}...",
483                            client_addr,
484                            &encode(join_header.uuid_or_token)[..12]
485                        );
486
487                        write_status_code(
488                            &mut writer_h,
489                            StatusCode::ErrSessionNotFound,
490                            &transport_key,
491                            &mut read_buffer,
492                        )
493                        .await?;
494                        return Ok(());
495                    }
496                };
497
498                info!(
499                    "Consumer (ip: {}) joined session_uuid: {}...",
500                    client_addr,
501                    &encode(join_header.uuid_or_token)[..12]
502                );
503
504                // on success, send write_len to consumer
505                write_status_code(
506                    &mut writer_h,
507                    StatusCode::Success,
508                    &transport_key,
509                    &mut read_buffer,
510                )
511                .await?;
512                write_server_read_write_len(
513                    &mut writer_h,
514                    config.fixed_packet_length - (NONCE_LEN + TAG_LEN) as u64, // announce raw payload capacity (encryption overhead is internal)
515                    &transport_key,
516                    &mut read_buffer,
517                )
518                .await?;
519
520                // add new consumer to session, this adds local ring buffer for this consumer, and returns a consumer handle
521                let (consumer_id, mut consumer) =
522                    session.add_consumer(config.channel_capacity as usize)?;
523
524                let mut peek = [0u8; 1]; // for checking conn alive
525                loop {
526                    tokio::select! {
527                        // block (async) until a packet arrives or peer drops;
528                        // no busy waiting, woken exactly when the ring has data
529                        popped = consumer.pop_async() => {
530                            match popped {
531                                Ok(data) => {
532                                    if writer_h.write_all(&data).await.is_err() {
533                                        let _ = writer_h.flush().await;
534                                        let _ = writer_h.shutdown().await;
535                                        error!(
536                                            "Consumer (ip: {}) write error, closing connection for session: {}...",
537                                            client_addr,
538                                            &encode(join_header.uuid_or_token)[..12]
539                                        );
540                                        break // if write fails (broken pipe and such issues)
541                                    }
542                                }
543                                Err(ClosedError) => {
544                                    let _ = writer_h.flush().await;
545                                    let _ = writer_h.shutdown().await;
546                                    info!(
547                                        "Consumer (ip: {}) session closed, closing connection for session: {}...",
548                                        client_addr,
549                                        &encode(join_header.uuid_or_token)[..12]
550                                    );
551                                    break // producer gone / session removed
552                                },
553                            }
554                        }
555                        result = read_h.read(&mut peek) => {
556                            match result {
557                                Ok(0) => break, // EOF check
558                                Err(_) => {
559                                    let _ = writer_h.flush().await;
560                                    let _ = writer_h.shutdown().await;
561                                    info!(
562                                        "Consumer (ip: {}) peer read error, closing connection for session: {}...",
563                                        client_addr,
564                                        &encode(join_header.uuid_or_token)[..12]
565                                    );
566                                    break // if read fails or connection closed, break
567                                },
568                                _ => {}
569                            }
570                        }
571                    }
572                }
573
574                info!(
575                    "Consumer (ip: {}) disconnected, closing connection for session_uuid: {}...",
576                    client_addr,
577                    &encode(join_header.uuid_or_token)[..12]
578                );
579
580                // remove own queue from the session, its dead weight
581                if let Some(session) = sessions.try_get_session(join_header.uuid_or_token) {
582                    session.consumer_local_buffers.remove(&consumer_id);
583                }
584            }
585
586            Role::Observer => {
587                // check token, if not present or invalid, return error
588                if let Some(token) = config.observer_token
589                    && token != join_header.uuid_or_token
590                {
591                    warn!(
592                        "Observer (ip: {}) failed to authenticate with token: {}...",
593                        client_addr,
594                        &encode(join_header.uuid_or_token)[..12]
595                    );
596
597                    write_status_code(
598                        &mut writer_h,
599                        StatusCode::ErrInvalidToken,
600                        &transport_key,
601                        &mut read_buffer,
602                    )
603                    .await?;
604                    return Ok(());
605                }
606
607                info!("Observer (ip: {}) token approved", client_addr,);
608                write_status_code(
609                    &mut writer_h,
610                    StatusCode::Success,
611                    &transport_key,
612                    &mut read_buffer,
613                )
614                .await?;
615                // send this anyway
616                write_server_read_write_len(
617                    &mut writer_h,
618                    config.fixed_packet_length - (NONCE_LEN + TAG_LEN) as u64,
619                    &transport_key,
620                    &mut read_buffer,
621                )
622                .await?;
623
624                // client sends 1 dumb byte, server replies with latest metrics
625                // client polls manually
626                let mut signal = [0u8; 1];
627                loop {
628                    // instant break server shutting down, no wait
629                    if is_shutting_down.load(Ordering::Relaxed) {
630                        break;
631                    }
632                    if read_h.read_exact(&mut signal).await.is_err() {
633                        break; // client closed / read error
634                    }
635                    let metrics = ServerMetrics {
636                        uptime_hrs: get_uptime_hrs(),
637                        total_sessions: total_sessions.load(Ordering::Relaxed),
638                        active_sessions: sessions.map.len() as u64,
639                        total_network_bandwidth: total_bytes.load(Ordering::Relaxed),
640                    };
641                    if write_server_metrics(
642                        &mut writer_h,
643                        &metrics,
644                        &transport_key,
645                        &mut read_buffer,
646                    )
647                    .await
648                    .is_err()
649                    {
650                        break; // broken pipe
651                    }
652                }
653                info!(
654                    "Observer (ip: {}) disconnected, closing connection...",
655                    client_addr,
656                );
657                return Ok(());
658            }
659        }
660
661        Ok(())
662    }
663
664    /// Returns the number of `active connections` to the server.
665    pub fn get_active_connections(&self) -> u64 {
666        self.active_connections.load(Ordering::Relaxed)
667    }
668
669    /// Returns the number of `active sessions` to the server.
670    pub fn get_active_sessions(&self) -> u64 {
671        self.session_map.map.len() as u64
672    }
673
674    /// Returns the total number of sessions ever created on the server.
675    pub fn get_total_sessions(&self) -> u64 {
676        self.total_sessions.load(Ordering::Relaxed)
677    }
678
679    /// Returns the observer token.
680    pub fn get_observer_token(&self) -> Option<[u8; 64]> {
681        self.config.observer_token
682    }
683
684    /// Returns the server uptime in seconds.
685    pub fn get_uptime_secs(&self) -> f64 {
686        if let Some(start_time) = START_TIME.get() {
687            let now = chrono::Local::now();
688            let duration = now.signed_duration_since(*start_time);
689            duration.as_seconds_f64()
690        } else {
691            0.0
692        }
693    }
694
695    /// Gracefully shuts down the server, stopping it from accepting `new connections` and waiting for `existing sessions` to finish.
696    pub async fn shutdown(&self) -> Result<()> {
697        self.shutdown_flag.store(true, Ordering::Relaxed);
698        Ok(())
699    }
700}
701
702#[allow(unused)]
703async fn handle_producer() -> Result<()> {
704    Ok(())
705}
706#[allow(unused)]
707async fn handle_consumer() -> Result<()> {
708    Ok(())
709}
710#[allow(unused)]
711async fn handle_observer() -> Result<()> {
712    Ok(())
713}