1use lash_trace::{TraceContext, TraceLevel, TraceSink};
2use std::sync::Arc;
3
4use super::process::{
5 InMemoryProcessExecutionEnvStore, ProcessEngineRegistry, ProcessExecutionEnvStore,
6 ProcessRegistry,
7};
8use super::{
9 EffectHost, InlineEffectHost, ProcessWorkDriver, QueuedWorkDriver, SessionStoreFactory,
10 TerminationPolicy,
11};
12
13#[derive(Clone)]
15pub struct RuntimeHostConfig {
16 pub durability: RuntimeDurabilityConfig,
17 pub process_engines: ProcessEngineRegistry,
18 pub providers: RuntimeProviderConfig,
19 pub prompt: RuntimePromptConfig,
20 pub control: RuntimeControlConfig,
21 pub tracing: RuntimeTracingConfig,
22 pub clock: Arc<dyn super::Clock>,
26}
27
28#[derive(Clone)]
29pub struct RuntimeDurabilityConfig {
30 pub attachment_store: Arc<dyn crate::AttachmentStore>,
31 pub process_env_store: Arc<dyn ProcessExecutionEnvStore>,
32}
33
34#[derive(Clone)]
35pub struct RuntimeProviderConfig {
36 pub provider_resolver: Arc<dyn crate::RuntimeProviderResolver>,
37}
38
39#[derive(Clone)]
40pub struct RuntimePromptConfig {
41 pub prompt: crate::PromptLayer,
42}
43
44#[derive(Clone)]
45pub struct RuntimeControlConfig {
46 pub effect_host: Arc<dyn EffectHost>,
47 pub process_cancel_ability: Arc<dyn crate::ProcessCancelAbility>,
48 pub termination: TerminationPolicy,
49}
50
51#[derive(Clone)]
52pub struct RuntimeTracingConfig {
53 pub trace_sink: Option<Arc<dyn TraceSink>>,
54 pub trace_level: TraceLevel,
55 pub trace_context: TraceContext,
56}
57
58impl RuntimeHostConfig {
59 pub fn new(
67 effect_host: Arc<dyn EffectHost>,
68 attachment_store: Arc<dyn crate::AttachmentStore>,
69 process_env_store: Arc<dyn ProcessExecutionEnvStore>,
70 ) -> Self {
71 Self {
72 durability: RuntimeDurabilityConfig {
73 attachment_store,
74 process_env_store,
75 },
76 process_engines: ProcessEngineRegistry::new(),
77 providers: RuntimeProviderConfig {
78 provider_resolver: Arc::new(crate::EmptyProviderResolver),
79 },
80 prompt: RuntimePromptConfig {
81 prompt: crate::PromptLayer::new(),
82 },
83 control: RuntimeControlConfig {
84 termination: TerminationPolicy::default(),
85 effect_host,
86 process_cancel_ability: Arc::new(crate::DefaultProcessCancelAbility),
87 },
88 tracing: RuntimeTracingConfig {
89 trace_sink: None,
90 trace_level: TraceLevel::Standard,
91 trace_context: TraceContext::default(),
92 },
93 clock: Arc::new(super::SystemClock),
94 }
95 }
96
97 pub fn with_clock(mut self, clock: Arc<dyn super::Clock>) -> Self {
101 self.clock = clock;
102 self
103 }
104
105 pub fn in_memory() -> Self {
111 Self::new(
112 Arc::new(InlineEffectHost::default()),
113 Arc::new(crate::InMemoryAttachmentStore::new()),
114 Arc::new(InMemoryProcessExecutionEnvStore::new()),
115 )
116 }
117
118 pub fn with_process_env_store(
119 mut self,
120 process_env_store: Arc<dyn ProcessExecutionEnvStore>,
121 ) -> Self {
122 self.durability.process_env_store = process_env_store;
123 self
124 }
125
126 pub fn with_process_cancel_ability(
127 mut self,
128 process_cancel_ability: Arc<dyn crate::ProcessCancelAbility>,
129 ) -> Self {
130 self.control.process_cancel_ability = process_cancel_ability;
131 self
132 }
133
134 pub fn with_process_engine(mut self, engine: Arc<dyn crate::ProcessEngine>) -> Self {
135 self.process_engines = self.process_engines.with_engine(engine);
136 self
137 }
138}
139
140#[derive(Clone)]
142pub struct EmbeddedRuntimeHost {
143 pub core: RuntimeHostConfig,
144 pub session_store_factory: Option<Arc<dyn SessionStoreFactory>>,
145 pub trigger_store: Option<Arc<dyn crate::TriggerStore>>,
146}
147
148impl EmbeddedRuntimeHost {
149 pub fn new(core: RuntimeHostConfig) -> Self {
150 let clock = Arc::clone(&core.clock);
151 Self {
152 core,
153 session_store_factory: None,
154 trigger_store: Some(Arc::new(crate::InMemoryTriggerStore::with_clock(clock))),
155 }
156 }
157
158 pub fn with_session_store_factory(
159 mut self,
160 session_store_factory: Arc<dyn SessionStoreFactory>,
161 ) -> Self {
162 self.session_store_factory = Some(session_store_factory);
163 self
164 }
165
166 pub fn with_trigger_store(mut self, store: Arc<dyn crate::TriggerStore>) -> Self {
167 self.trigger_store = Some(store);
168 self
169 }
170}
171
172#[derive(Clone)]
174pub struct ProcessRuntimeHost {
175 pub embedded: EmbeddedRuntimeHost,
176 pub process_registry: Arc<dyn ProcessRegistry>,
177 pub process_work_driver: Option<ProcessWorkDriver>,
178 pub queued_work_driver: Option<QueuedWorkDriver>,
179}
180
181impl ProcessRuntimeHost {
182 pub fn new(embedded: EmbeddedRuntimeHost, process_registry: Arc<dyn ProcessRegistry>) -> Self {
183 Self {
184 embedded,
185 process_registry,
186 process_work_driver: None,
187 queued_work_driver: None,
188 }
189 }
190
191 pub fn with_process_work_driver(mut self, driver: ProcessWorkDriver) -> Self {
192 self.process_work_driver = Some(driver);
193 self
194 }
195
196 pub fn with_queued_work_driver(mut self, driver: QueuedWorkDriver) -> Self {
197 self.queued_work_driver = Some(driver);
198 self
199 }
200}
201
202#[derive(Clone)]
203pub(crate) struct RuntimeHost {
204 pub core: RuntimeHostConfig,
205 pub session_store_factory: Option<Arc<dyn SessionStoreFactory>>,
206 pub trigger_store: Option<Arc<dyn crate::TriggerStore>>,
207 pub process_registry: Option<Arc<dyn ProcessRegistry>>,
208 pub process_work_driver: Option<ProcessWorkDriver>,
210 pub queued_work_driver: Option<QueuedWorkDriver>,
213}
214
215impl RuntimeHost {
216 pub(crate) fn resolve_session_policy(
217 &self,
218 session_id: &str,
219 policy: crate::SessionPolicy,
220 ) -> Result<crate::RuntimeSessionPolicy, crate::SessionError> {
221 let provider_id = policy.recorded_provider_id();
222 let mut binding = self
223 .core
224 .providers
225 .provider_resolver
226 .resolve_provider_binding(provider_id)
227 .map_err(|err| match err {
228 crate::ProviderResolutionError::MissingProviderId => {
229 crate::SessionError::ProviderUnconfigured {
230 session_id: session_id.to_string(),
231 }
232 }
233 crate::ProviderResolutionError::UnknownProvider { provider_id } => {
234 crate::SessionError::ProviderUnavailable {
235 provider_id,
236 session_id: session_id.to_string(),
237 }
238 }
239 crate::ProviderResolutionError::ProviderIdMismatch { expected, actual } => {
240 crate::SessionError::ProviderMismatch {
241 expected,
242 actual,
243 session_id: session_id.to_string(),
244 }
245 }
246 })?;
247 binding.provider = binding.provider.with_clock(Arc::clone(&self.core.clock));
248 Ok(crate::RuntimeSessionPolicy::new(policy, binding))
249 }
250}
251
252impl From<EmbeddedRuntimeHost> for RuntimeHost {
253 fn from(value: EmbeddedRuntimeHost) -> Self {
254 Self {
255 core: value.core,
256 session_store_factory: value.session_store_factory,
257 trigger_store: value.trigger_store,
258 process_registry: None,
259 process_work_driver: None,
260 queued_work_driver: None,
261 }
262 }
263}
264
265impl From<ProcessRuntimeHost> for RuntimeHost {
266 fn from(value: ProcessRuntimeHost) -> Self {
267 Self {
268 core: value.embedded.core,
269 session_store_factory: value.embedded.session_store_factory,
270 trigger_store: value.embedded.trigger_store,
271 process_registry: Some(value.process_registry),
272 process_work_driver: value.process_work_driver,
273 queued_work_driver: value.queued_work_driver,
274 }
275 }
276}