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