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