wsprism_gateway/dispatch/
dispatcher.rs1use std::sync::Arc;
2
3use async_trait::async_trait;
4use dashmap::DashMap;
5
6use wsprism_core::error::{Result, WsPrismError};
7use wsprism_core::protocol::hot::HotFrame;
8use wsprism_core::protocol::text::Envelope;
9
10use crate::realtime::RealtimeCtx;
11
12#[async_trait]
14pub trait TextService: Send + Sync {
15 fn svc(&self) -> &'static str;
16 async fn handle(&self, ctx: RealtimeCtx, env: Envelope) -> Result<()>;
17}
18
19#[async_trait]
21pub trait BinaryService: Send + Sync {
22 fn svc_id(&self) -> u8;
23 async fn handle_binary(&self, ctx: RealtimeCtx, frame: HotFrame) -> Result<()>;
24}
25
26#[derive(Default)]
28pub struct Dispatcher {
29 text: DashMap<&'static str, Arc<dyn TextService>>,
30 hot: DashMap<u8, Arc<dyn BinaryService>>,
31}
32
33impl Dispatcher {
34 pub fn new() -> Self {
35 Self {
36 text: DashMap::new(),
37 hot: DashMap::new(),
38 }
39 }
40
41 pub fn register_text(&self, svc: Arc<dyn TextService>) {
42 self.text.insert(svc.svc(), svc);
43 }
44
45 pub fn register_hot(&self, svc: Arc<dyn BinaryService>) {
46 self.hot.insert(svc.svc_id(), svc);
47 }
48
49 pub fn registered_text_svcs(&self) -> Vec<&'static str> {
50 self.text.iter().map(|e| *e.key()).collect()
51 }
52
53 pub fn registered_hot_svcs(&self) -> Vec<u8> {
54 self.hot.iter().map(|e| *e.key()).collect()
55 }
56
57 pub async fn dispatch_text(&self, ctx: RealtimeCtx, env: Envelope) -> Result<()> {
58 let svc = env.svc.as_str();
59 let handler = self
60 .text
61 .get(svc)
62 .ok_or_else(|| WsPrismError::BadRequest(format!("unknown svc: {svc}")))?
63 .value()
64 .clone();
65 handler.handle(ctx, env).await
66 }
67
68 pub async fn dispatch_hot(&self, ctx: RealtimeCtx, frame: HotFrame) -> Result<()> {
69 let sid = frame.svc_id;
70 let handler = self
71 .hot
72 .get(&sid)
73 .ok_or_else(|| WsPrismError::BadRequest(format!("unknown hot svc_id: {sid}")))?
74 .value()
75 .clone();
76 handler.handle_binary(ctx, frame).await
77 }
78}