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