vv_agent/runtime/backends/distributed/
backend.rs1use std::sync::Arc;
2use std::time::Duration;
3
4use crate::runtime::state::StateStore;
5
6use super::super::RuntimeRecipe;
7use super::dispatch::CycleDispatcher;
8use super::{DEFAULT_CYCLE_NAME, DEFAULT_LEASE_DURATION_MS};
9
10#[derive(Clone)]
11pub struct DistributedBackend {
12 pub(super) runtime_recipe: Option<RuntimeRecipe>,
13 pub(super) state_store: Option<Arc<dyn StateStore>>,
14 pub(super) cycle_dispatcher: Option<Arc<dyn CycleDispatcher>>,
15 pub(super) cycle_name: String,
16 pub(super) dispatch_timeout: Duration,
17 pub(super) lease_duration_ms: u64,
18}
19
20impl std::fmt::Debug for DistributedBackend {
21 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22 formatter
23 .debug_struct("DistributedBackend")
24 .field("runtime_recipe", &self.runtime_recipe)
25 .field("has_state_store", &self.state_store.is_some())
26 .field("has_cycle_dispatcher", &self.cycle_dispatcher.is_some())
27 .field("cycle_name", &self.cycle_name)
28 .field("dispatch_timeout", &self.dispatch_timeout)
29 .field("lease_duration_ms", &self.lease_duration_ms)
30 .finish()
31 }
32}
33
34impl DistributedBackend {
35 pub fn inline_fallback() -> Self {
36 Self {
37 runtime_recipe: None,
38 state_store: None,
39 cycle_dispatcher: None,
40 cycle_name: DEFAULT_CYCLE_NAME.to_string(),
41 dispatch_timeout: Duration::from_secs(10 * 60),
42 lease_duration_ms: DEFAULT_LEASE_DURATION_MS,
43 }
44 }
45
46 pub fn distributed(runtime_recipe: RuntimeRecipe) -> Self {
47 Self {
48 runtime_recipe: Some(runtime_recipe),
49 state_store: None,
50 cycle_dispatcher: None,
51 cycle_name: DEFAULT_CYCLE_NAME.to_string(),
52 dispatch_timeout: Duration::from_secs(10 * 60),
53 lease_duration_ms: DEFAULT_LEASE_DURATION_MS,
54 }
55 }
56
57 pub fn distributed_with_dispatcher(
58 runtime_recipe: RuntimeRecipe,
59 state_store: Arc<dyn StateStore>,
60 cycle_dispatcher: Arc<dyn CycleDispatcher>,
61 ) -> Self {
62 Self {
63 runtime_recipe: Some(runtime_recipe),
64 state_store: Some(state_store),
65 cycle_dispatcher: Some(cycle_dispatcher),
66 cycle_name: DEFAULT_CYCLE_NAME.to_string(),
67 dispatch_timeout: Duration::from_secs(10 * 60),
68 lease_duration_ms: DEFAULT_LEASE_DURATION_MS,
69 }
70 }
71
72 pub fn with_cycle_name(mut self, cycle_name: impl Into<String>) -> Self {
73 self.cycle_name = cycle_name.into();
74 self
75 }
76
77 pub fn with_dispatch_timeout(mut self, timeout: Duration) -> Self {
78 assert!(!timeout.is_zero(), "dispatch timeout must be positive");
79 self.dispatch_timeout = timeout;
80 self
81 }
82
83 pub fn with_lease_duration(mut self, duration: Duration) -> Self {
84 let duration_ms = u64::try_from(duration.as_millis())
85 .expect("lease duration milliseconds must fit in u64");
86 assert!(duration_ms > 0, "lease duration must be positive");
87 self.lease_duration_ms = duration_ms;
88 self
89 }
90
91 pub fn runtime_recipe(&self) -> Option<&RuntimeRecipe> {
92 self.runtime_recipe.as_ref()
93 }
94
95 pub fn state_store(&self) -> Option<&Arc<dyn StateStore>> {
96 self.state_store.as_ref()
97 }
98
99 pub fn cycle_name(&self) -> &str {
100 &self.cycle_name
101 }
102
103 pub fn parallel_map<T, R, F>(&self, function: F, items: Vec<T>) -> Vec<R>
104 where
105 F: Fn(T) -> R,
106 {
107 items.into_iter().map(function).collect()
108 }
109}