actr_runtime/
context_factory.rs

1//! Context factory
2//!
3//! 负责创建 RuntimeContext 实例,注入 OutGate 和其他依赖。
4
5use crate::context::RuntimeContext;
6use crate::inbound::{DataStreamRegistry, MediaFrameRegistry};
7use crate::outbound::OutGate;
8use crate::transport::InprocTransportManager;
9use crate::wire::webrtc::SignalingClient;
10use actr_config::lock::LockFile;
11use actr_protocol::{AIdCredential, ActrId};
12use std::path::PathBuf;
13use std::sync::Arc;
14
15/// Context factory
16///
17/// # 职责
18///
19/// - 创建 RuntimeContext 实例
20/// - 注入 OutGate(enum dispatch,零虚函数)
21/// - 管理默认配置
22#[derive(Clone)]
23pub struct ContextFactory {
24    /// 进程内通信 gate(本地调用)- 立即可用
25    pub(crate) inproc_gate: OutGate,
26
27    /// 跨进程通信 gate(远程调用)- 延迟初始化
28    pub(crate) outproc_gate: Option<OutGate>,
29
30    /// Shell → Workload 方向的传输管理器
31    pub(crate) shell_to_workload: Arc<InprocTransportManager>,
32
33    /// Workload → Shell 方向的传输管理器
34    pub(crate) workload_to_shell: Arc<InprocTransportManager>,
35
36    /// DataStream 回调注册表
37    pub(crate) data_stream_registry: Arc<DataStreamRegistry>,
38
39    /// MediaTrack 回调注册表
40    pub(crate) media_frame_registry: Arc<MediaFrameRegistry>,
41
42    /// Signaling client for discovery
43    pub(crate) signaling_client: Arc<dyn SignalingClient>,
44
45    /// Actr.lock.toml for dependency fingerprint lookups
46    pub(crate) actr_lock: Option<LockFile>,
47
48    /// Config directory path for compat.lock.toml
49    pub(crate) config_dir: Option<PathBuf>,
50}
51
52impl ContextFactory {
53    /// 创建新的 ContextFactory
54    ///
55    /// # 参数
56    ///
57    /// - `inproc_gate`: 进程内通信 gate(Dest::Shell/Local)- 立即可用
58    /// - `shell_to_workload`: Shell → Workload 方向的传输管理器
59    /// - `workload_to_shell`: Workload → Shell 方向的传输管理器
60    /// - `data_stream_registry`: DataStream 回调注册表
61    /// - `media_frame_registry`: MediaTrack 回调注册表
62    ///
63    /// # 设计说明
64    ///
65    /// - **inproc_gate**: 在 ActrSystem::new() 时创建,立即可用(Shell/Local 通信不需要 ActorId)
66    /// - **outproc_gate**: 初始为 None,在 ActrNode::start() WebRTC 初始化完成后设置
67    /// - **双向 InprocTransportManager**: 确保 Shell 和 Workload 的 pending_requests 完全分离
68    /// - **data_stream_registry**: 管理 DataStream 回调,支持应用数据流传输
69    /// - **media_frame_registry**: 管理 MediaTrack 回调,支持 WebRTC 原生媒体流
70    pub fn new(
71        inproc_gate: OutGate,
72        shell_to_workload: Arc<InprocTransportManager>,
73        workload_to_shell: Arc<InprocTransportManager>,
74        data_stream_registry: Arc<DataStreamRegistry>,
75        media_frame_registry: Arc<MediaFrameRegistry>,
76        signaling_client: Arc<dyn SignalingClient>,
77    ) -> Self {
78        Self {
79            inproc_gate,
80            outproc_gate: None, // 延迟初始化,等待 WebRTC 就绪
81            shell_to_workload,
82            workload_to_shell,
83            data_stream_registry,
84            media_frame_registry,
85            signaling_client,
86            actr_lock: None, // 延迟设置,在 ActrNode::start() 时从 actr_node.actr_lock 传入
87            config_dir: None, // 延迟设置,在 ActrNode::start() 时从 actr_node.config 传入
88        }
89    }
90
91    /// 设置跨进程通信 gate
92    ///
93    /// # 用途
94    ///
95    /// ActrNode::start() 完成 WebRTC 初始化后调用
96    pub fn set_outproc_gate(&mut self, gate: OutGate) {
97        tracing::debug!("🔄 Setting outproc OutGate in ContextFactory");
98        self.outproc_gate = Some(gate);
99    }
100
101    /// 设置 Actr.lock.toml 文件
102    ///
103    /// # 用途
104    ///
105    /// ActrNode::start() 时调用,用于 discover_route_candidate 获取依赖 fingerprint
106    pub fn set_actr_lock(&mut self, actr_lock: LockFile) {
107        tracing::debug!("🔄 Setting actr_lock in ContextFactory");
108        self.actr_lock = Some(actr_lock);
109    }
110
111    /// 设置配置目录路径
112    ///
113    /// # 用途
114    ///
115    /// ActrNode::start() 时调用,用于 compat.lock.toml Fast Path 缓存
116    pub fn set_config_dir(&mut self, config_dir: PathBuf) {
117        tracing::debug!("🔄 Setting config_dir in ContextFactory: {:?}", config_dir);
118        self.config_dir = Some(config_dir);
119    }
120
121    /// 获取 Shell → Workload 方向的传输管理器
122    pub fn shell_to_workload(&self) -> Arc<InprocTransportManager> {
123        self.shell_to_workload.clone()
124    }
125
126    /// 获取 Workload → Shell 方向的传输管理器
127    pub fn workload_to_shell(&self) -> Arc<InprocTransportManager> {
128        self.workload_to_shell.clone()
129    }
130
131    /// 创建 Context(用于消息处理)
132    ///
133    /// # 参数
134    ///
135    /// - `self_id`: 当前 Actor ID
136    /// - `caller_id`: 调用方 Actor ID(可选)
137    /// - `request_id`: 请求唯一 ID
138    ///
139    /// # 返回
140    ///
141    /// 返回 RuntimeContext 实例(实现了 Context trait)
142    pub fn create(
143        &self,
144        self_id: &ActrId,
145        caller_id: Option<&ActrId>,
146        request_id: &str,
147        credential: &AIdCredential,
148    ) -> RuntimeContext {
149        RuntimeContext::new(
150            self_id.clone(),
151            caller_id.cloned(),
152            request_id.to_string(),
153            self.inproc_gate.clone(), // Clone OutGate enum(Arc 内部,开销低)
154            self.outproc_gate.clone(), // Clone Option<OutGate>
155            self.data_stream_registry.clone(), // Clone Arc<DataStreamRegistry>
156            self.media_frame_registry.clone(), // Clone Arc<MediaFrameRegistry>
157            self.signaling_client.clone(),
158            credential.clone(),
159            self.actr_lock.clone(),  // Clone Option<LockFile>
160            self.config_dir.clone(), // Clone Option<PathBuf>
161        )
162    }
163
164    /// 创建引导 Context(用于生命周期钩子)
165    ///
166    /// # 用途
167    ///
168    /// 用于 on_start/on_stop 钩子,无 caller_id
169    pub fn create_bootstrap(&self, self_id: &ActrId, credential: &AIdCredential) -> RuntimeContext {
170        RuntimeContext::new(
171            self_id.clone(),
172            None,
173            uuid::Uuid::new_v4().to_string(),
174            self.inproc_gate.clone(),
175            self.outproc_gate.clone(),
176            self.data_stream_registry.clone(),
177            self.media_frame_registry.clone(),
178            self.signaling_client.clone(),
179            credential.clone(),
180            self.actr_lock.clone(),
181            self.config_dir.clone(),
182        )
183    }
184}