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