actr_runtime/outbound/mod.rs
1//! Outbound Layer 2: Outbound gate abstraction layer
2//!
3//! 提供统一的出站消息发送接口,支持进程内和跨进程通信。
4//!
5//! # 设计特性
6//!
7//! - **Enum Dispatch**:使用枚举而非 trait object,实现零虚函数调用
8//! - **零成本抽象**:编译时确定类型,静态分发
9//! - **统一接口**:InprocOut 和 OutprocOut 共享相同的方法签名
10
11mod inproc_out_gate;
12mod outproc_out_gate;
13
14pub use inproc_out_gate::InprocOutGate;
15pub use outproc_out_gate::OutprocOutGate;
16
17use actr_framework::{Bytes, MediaSample};
18use actr_protocol::{ActorResult, ActrId, RpcEnvelope};
19use std::sync::Arc;
20
21/// OutGate - 出站消息门枚举
22///
23/// # 设计原则
24///
25/// - 使用 **enum dispatch** 而非 trait object,避免虚函数调用
26/// - **零成本抽象**:编译时准确确定类型
27/// - **完全独立**:仅用于出站(Outbound),不包含任何入站路由逻辑
28///
29/// # 性能
30///
31/// ```text
32/// OutGate::send_request() 内部:
33/// match self {
34/// OutGate::InprocOut(gate) => gate.send_request(...), // ← 静态分发
35/// OutGate::OutprocOut(gate) => gate.send_request(...), // ← 静态分发
36/// }
37///
38/// 性能:
39/// - 无虚函数表查找
40/// - 编译器完全内联
41/// - CPU 分支预测命中率 >95%
42/// ```
43#[derive(Clone)]
44pub enum OutGate {
45 /// InprocOut - 进程内传输(零序列化,出站)
46 InprocOut(Arc<InprocOutGate>),
47
48 /// OutprocOut - 跨进程传输(Protobuf 序列化,出站)
49 OutprocOut(Arc<OutprocOutGate>),
50}
51
52impl OutGate {
53 /// 发送请求并等待响应
54 ///
55 /// # 参数
56 ///
57 /// - `target`: 目标 Actor ID
58 /// - `envelope`: 消息信封(包含 route_key 和 payload)
59 ///
60 /// # 返回
61 ///
62 /// 返回响应的字节数据
63 ///
64 /// # 实现
65 ///
66 /// 使用 enum dispatch 静态分发到对应的实现:
67 /// - `InprocOut`: 零序列化,直接传递 RpcEnvelope
68 /// - `OutprocOut`: Protobuf 序列化,通过 Transport 层发送
69 pub async fn send_request(&self, target: &ActrId, envelope: RpcEnvelope) -> ActorResult<Bytes> {
70 match self {
71 OutGate::InprocOut(gate) => gate.send_request(target, envelope).await,
72 OutGate::OutprocOut(gate) => gate.send_request(target, envelope).await,
73 }
74 }
75
76 /// 发送单向消息(不等待响应)
77 ///
78 /// # 参数
79 ///
80 /// - `target`: 目标 Actor ID
81 /// - `envelope`: 消息信封
82 ///
83 /// # 语义
84 ///
85 /// Fire-and-forget:发送后立即返回,不等待响应
86 pub async fn send_message(&self, target: &ActrId, envelope: RpcEnvelope) -> ActorResult<()> {
87 match self {
88 OutGate::InprocOut(gate) => gate.send_message(target, envelope).await,
89 OutGate::OutprocOut(gate) => gate.send_message(target, envelope).await,
90 }
91 }
92
93 /// 发送媒体样本(WebRTC native media)
94 ///
95 /// # 参数
96 ///
97 /// - `target`: 目标 Actor ID
98 /// - `track_id`: Media track 标识符
99 /// - `sample`: 媒体样本数据
100 ///
101 /// # 语义
102 ///
103 /// - 仅支持 OutprocOut(WebRTC)
104 /// - InprocOut 返回 NotImplemented 错误
105 /// - 使用 WebRTC RTCRtpSender 发送,无 protobuf 开销
106 pub async fn send_media_sample(
107 &self,
108 target: &ActrId,
109 track_id: &str,
110 sample: MediaSample,
111 ) -> ActorResult<()> {
112 match self {
113 OutGate::InprocOut(_gate) => {
114 // InprocOut does not support MediaTrack (WebRTC-specific feature)
115 Err(actr_protocol::ProtocolError::Actr(
116 actr_protocol::ActrError::NotImplemented {
117 feature: "MediaTrack is only supported for remote actors via WebRTC"
118 .to_string(),
119 },
120 ))
121 }
122 OutGate::OutprocOut(gate) => gate.send_media_sample(target, track_id, sample).await,
123 }
124 }
125
126 /// 发送 DataStream(Fast Path 数据流)
127 ///
128 /// # 参数
129 ///
130 /// - `target`: 目标 Actor ID
131 /// - `payload_type`: PayloadType (StreamReliable 或 StreamLatencyFirst)
132 /// - `data`: 序列化后的 DataStream bytes
133 ///
134 /// # 语义
135 ///
136 /// - InprocOut: 通过 mpsc channel 发送
137 /// - OutprocOut: 通过 WebRTC DataChannel 或 WebSocket 发送
138 pub async fn send_data_stream(
139 &self,
140 target: &ActrId,
141 payload_type: actr_protocol::PayloadType,
142 data: Bytes,
143 ) -> ActorResult<()> {
144 match self {
145 OutGate::InprocOut(gate) => gate.send_data_stream(target, payload_type, data).await,
146 OutGate::OutprocOut(gate) => gate.send_data_stream(target, payload_type, data).await,
147 }
148 }
149}