harmos_runtime/observers/
mod.rs1mod driver;
21
22#[cfg(feature = "plugin-sidecar")]
23mod native;
24
25pub use crate::operations::resident::Staged as ObserverRegistration;
28pub use driver::ObserverActivation;
29
30pub(crate) use driver::Backend;
31#[cfg(feature = "plugin-sidecar")]
32pub(crate) use driver::ChildSettlement;
33#[cfg(feature = "plugin-sidecar")]
34pub(crate) use native::Native;
35
36use std::collections::BTreeSet;
40use std::future::Future;
41use std::sync::Arc;
42use std::time::Duration;
43use crate::{Error, Result};
47use harmos_domain::inventory::StreamDeclaration;
48
49#[derive(Clone, Debug)]
58pub struct ObserverDefinition {
59 pub id: String,
60 pub interval: Duration,
61 pub streams: Vec<StreamDeclaration>,
62 pub demand_keys: Vec<String>,
63}
64
65pub trait ObserverBackend: Send + Sync + 'static {
70 type Resources: Send + Sync + 'static;
71 fn definition(&self) -> crate::Result<ObserverDefinition>;
72 fn run(&self, resources: Arc<Self::Resources>, activation: ObserverActivation) -> impl Future<Output = crate::Result<()>> + Send;
73}
74
75pub(crate) fn validate(definition: &ObserverDefinition) -> Result<()> {
82 if definition.id.trim().is_empty() || definition.id.chars().any(char::is_control) {
83 return Err(Error::InvalidInput { field: "observer identity", reason: "must be nonempty and contain no control characters" });
84 }
85 if definition.interval.is_zero() {
86 return Err(Error::InvalidInput { field: "observer interval", reason: "must be positive" });
87 }
88 let mut names = BTreeSet::new();
89 for stream in &definition.streams {
90 if stream.id.is_empty() || stream.schema == 0 || stream.window == 0 || !names.insert(stream.id.as_str()) {
91 return Err(Error::InvalidInput {
92 field: "observer streams",
93 reason: "stream identities must be unique and schema/window must be positive",
94 });
95 }
96 }
97 for key in &definition.demand_keys {
98 if key.is_empty() || !names.insert(key.as_str()) {
99 return Err(Error::InvalidInput {
100 field: "observer demand",
101 reason: "demand keys must be nonempty, unique, and distinct from streams",
102 });
103 }
104 }
105 Ok(())
106}
107
108