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 attachment_source_policy: Arc<dyn crate::AttachmentSourcePolicy>,
23 pub clock: Arc<dyn super::Clock>,
27}
28
29#[derive(Clone)]
30pub struct RuntimeDurabilityConfig {
31 pub attachment_store: Arc<crate::SessionAttachmentStore>,
38 pub process_env_store: Arc<dyn ProcessExecutionEnvStore>,
39}
40
41#[derive(Clone)]
42pub struct RuntimeProviderConfig {
43 pub provider_resolver: Arc<dyn crate::RuntimeProviderResolver>,
44}
45
46#[derive(Clone)]
47pub struct RuntimePromptConfig {
48 pub prompt: crate::PromptLayer,
49}
50
51#[derive(Clone)]
52pub struct RuntimeControlConfig {
53 pub effect_host: Arc<dyn EffectHost>,
54 pub process_cancel_ability: Arc<dyn crate::ProcessCancelAbility>,
55 pub termination: TerminationPolicy,
56 pub lease_timings: crate::LeaseTimings,
63}
64
65#[derive(Clone)]
66pub struct RuntimeTracingConfig {
67 pub trace_sink: Option<Arc<dyn TraceSink>>,
68 pub trace_level: TraceLevel,
69 pub trace_context: TraceContext,
70}
71
72impl RuntimeHostConfig {
73 pub fn new(
81 effect_host: Arc<dyn EffectHost>,
82 attachment_store: Arc<dyn crate::AttachmentStore>,
83 process_env_store: Arc<dyn ProcessExecutionEnvStore>,
84 ) -> Self {
85 Self {
86 durability: RuntimeDurabilityConfig {
87 attachment_store: Arc::new(crate::SessionAttachmentStore::ephemeral(
88 attachment_store,
89 )),
90 process_env_store,
91 },
92 process_engines: ProcessEngineRegistry::new(),
93 providers: RuntimeProviderConfig {
94 provider_resolver: Arc::new(crate::EmptyProviderResolver),
95 },
96 prompt: RuntimePromptConfig {
97 prompt: crate::PromptLayer::new(),
98 },
99 control: RuntimeControlConfig {
100 termination: TerminationPolicy::default(),
101 effect_host,
102 process_cancel_ability: Arc::new(crate::DefaultProcessCancelAbility),
103 lease_timings: crate::LeaseTimings::default(),
104 },
105 tracing: RuntimeTracingConfig {
106 trace_sink: None,
107 trace_level: TraceLevel::Standard,
108 trace_context: TraceContext::default(),
109 },
110 attachment_source_policy: Arc::new(crate::OpenAttachmentSourcePolicy),
111 clock: Arc::new(super::SystemClock),
112 }
113 }
114
115 pub fn with_clock(mut self, clock: Arc<dyn super::Clock>) -> Self {
119 self.clock = clock;
120 self
121 }
122
123 pub fn with_attachment_source_policy(
124 mut self,
125 policy: Arc<dyn crate::AttachmentSourcePolicy>,
126 ) -> Self {
127 self.attachment_source_policy = policy;
128 self
129 }
130
131 pub fn in_memory() -> Self {
137 Self::new(
138 Arc::new(InlineEffectHost::default()),
139 Arc::new(crate::InMemoryAttachmentStore::new()),
140 Arc::new(InMemoryProcessExecutionEnvStore::new()),
141 )
142 }
143
144 pub fn with_process_env_store(
145 mut self,
146 process_env_store: Arc<dyn ProcessExecutionEnvStore>,
147 ) -> Self {
148 self.durability.process_env_store = process_env_store;
149 self
150 }
151
152 pub fn with_process_cancel_ability(
153 mut self,
154 process_cancel_ability: Arc<dyn crate::ProcessCancelAbility>,
155 ) -> Self {
156 self.control.process_cancel_ability = process_cancel_ability;
157 self
158 }
159
160 pub fn with_process_engine(mut self, engine: Arc<dyn crate::ProcessEngine>) -> Self {
161 self.process_engines = self.process_engines.with_engine(engine);
162 self
163 }
164
165 pub fn with_lease_timings(mut self, lease_timings: crate::LeaseTimings) -> Self {
168 self.control.lease_timings = lease_timings;
169 self
170 }
171}
172
173#[derive(Clone)]
175pub struct EmbeddedRuntimeHost {
176 pub core: RuntimeHostConfig,
177 pub session_store_factory: Option<Arc<dyn SessionStoreFactory>>,
178 pub trigger_store: Option<Arc<dyn crate::TriggerStore>>,
179}
180
181impl EmbeddedRuntimeHost {
182 pub fn new(core: RuntimeHostConfig) -> Self {
183 let clock = Arc::clone(&core.clock);
184 Self {
185 core,
186 session_store_factory: None,
187 trigger_store: Some(Arc::new(crate::InMemoryTriggerStore::with_clock(clock))),
188 }
189 }
190
191 pub fn with_session_store_factory(
192 mut self,
193 session_store_factory: Arc<dyn SessionStoreFactory>,
194 ) -> Self {
195 self.session_store_factory = Some(session_store_factory);
196 self
197 }
198
199 pub fn with_trigger_store(mut self, store: Arc<dyn crate::TriggerStore>) -> Self {
200 self.trigger_store = Some(store);
201 self
202 }
203}
204
205#[derive(Clone)]
207pub struct ProcessRuntimeHost {
208 pub embedded: EmbeddedRuntimeHost,
209 pub process_registry: Arc<dyn ProcessRegistry>,
210 pub process_work_driver: Option<ProcessWorkDriver>,
211 pub queued_work_driver: Option<QueuedWorkDriver>,
212}
213
214impl ProcessRuntimeHost {
215 pub fn new(embedded: EmbeddedRuntimeHost, process_registry: Arc<dyn ProcessRegistry>) -> Self {
216 Self {
217 embedded,
218 process_registry,
219 process_work_driver: None,
220 queued_work_driver: None,
221 }
222 }
223
224 pub fn with_process_work_driver(mut self, driver: ProcessWorkDriver) -> Self {
225 self.process_work_driver = Some(driver);
226 self
227 }
228
229 pub fn with_queued_work_driver(mut self, driver: QueuedWorkDriver) -> Self {
230 self.queued_work_driver = Some(driver);
231 self
232 }
233}
234
235#[derive(Clone)]
236pub(crate) struct RuntimeHost {
237 pub core: RuntimeHostConfig,
238 pub session_store_factory: Option<Arc<dyn SessionStoreFactory>>,
239 pub trigger_store: Option<Arc<dyn crate::TriggerStore>>,
240 pub process_registry: Option<Arc<dyn ProcessRegistry>>,
241 pub process_work_driver: Option<ProcessWorkDriver>,
243 pub queued_work_driver: Option<QueuedWorkDriver>,
246}
247
248impl RuntimeHost {
249 pub(crate) fn resolve_session_policy(
250 &self,
251 session_id: &str,
252 policy: crate::SessionPolicy,
253 ) -> Result<crate::RuntimeSessionPolicy, crate::SessionError> {
254 let provider_id = policy.recorded_provider_id();
255 let mut binding = self
256 .core
257 .providers
258 .provider_resolver
259 .resolve_provider_binding(provider_id)
260 .map_err(|err| match err {
261 crate::ProviderResolutionError::MissingProviderId => {
262 crate::SessionError::ProviderUnconfigured {
263 session_id: session_id.to_string(),
264 }
265 }
266 crate::ProviderResolutionError::UnknownProvider { provider_id } => {
267 crate::SessionError::ProviderUnavailable {
268 provider_id,
269 session_id: session_id.to_string(),
270 }
271 }
272 crate::ProviderResolutionError::ProviderIdMismatch { expected, actual } => {
273 crate::SessionError::ProviderMismatch {
274 expected,
275 actual,
276 session_id: session_id.to_string(),
277 }
278 }
279 })?;
280 binding.provider = binding.provider.with_clock(Arc::clone(&self.core.clock));
281 Ok(crate::RuntimeSessionPolicy::new(policy, binding))
282 }
283}
284
285impl From<EmbeddedRuntimeHost> for RuntimeHost {
286 fn from(value: EmbeddedRuntimeHost) -> Self {
287 Self {
288 core: value.core,
289 session_store_factory: value.session_store_factory,
290 trigger_store: value.trigger_store,
291 process_registry: None,
292 process_work_driver: None,
293 queued_work_driver: None,
294 }
295 }
296}
297
298impl From<ProcessRuntimeHost> for RuntimeHost {
299 fn from(value: ProcessRuntimeHost) -> Self {
300 Self {
301 core: value.embedded.core,
302 session_store_factory: value.embedded.session_store_factory,
303 trigger_store: value.embedded.trigger_store,
304 process_registry: Some(value.process_registry),
305 process_work_driver: value.process_work_driver,
306 queued_work_driver: value.queued_work_driver,
307 }
308 }
309}