allora_runtime/spec/aggregator_spec.rs
1//! `AggregatorSpec`: specification for a single EIP Aggregator instance.
2//!
3//! An aggregator is declared in `allora.yaml` by id; it references consumer-supplied
4//! implementations of [`allora_core::patterns::aggregator::CompletionCondition`],
5//! [`allora_core::patterns::aggregator::AggregationStrategy`], and
6//! [`allora_core::patterns::aggregator::GroupStore`] **by name** — those names resolve
7//! through the runtime [`crate::dsl::PatternRegistry`] at build time.
8//!
9//! # Field Semantics
10//!
11//! * `id` (optional) — explicit identifier for referencing the built aggregator from
12//! consumer code. If absent, [`crate::dsl::build_aggregators_from_spec`] generates
13//! a deterministic `aggregator:auto.N` id.
14//! * `correlation_header` (required, non-empty) — header key used to group messages
15//! (e.g. `"block_hash"` for the chain's finality quorum).
16//! * `completion` (required, non-empty) — registry name of the
17//! [`allora_core::patterns::aggregator::CompletionCondition`] to use. *No defaults* —
18//! the chain's quorum logic is registry-supplied, and that's the canonical use case.
19//! * `strategy` (optional, non-empty if present) — registry name of the
20//! [`allora_core::patterns::aggregator::AggregationStrategy`]. Defaults to
21//! `allora.concat_text` (matching `Aggregator::new`'s default behavior) at build time.
22//! * `store` (optional, non-empty if present) — registry name of the
23//! [`allora_core::patterns::aggregator::GroupStore`]. Defaults to an
24//! `InMemoryGroupStore` instance at build time.
25//!
26//! # Uniqueness & Validation
27//! YAML parser ([`crate::spec::AggregatorSpecYamlParser`]) enforces presence + type +
28//! non-empty strings. Uniqueness of `id` is deferred to the collection builder
29//! ([`crate::dsl::build_aggregators_from_spec`]).
30//!
31//! # Construction Helpers
32//! * `new(correlation_header, completion)` — minimal spec.
33//! * `with_id(id, correlation_header, completion)` — explicit id.
34//! * `set_strategy(name)` / `set_store(name)` — chainable setters (return `self`).
35//! * `set_id(id)` — internal use (builder assigning auto-generated id).
36//! * Accessors: `id()`, `correlation_header()`, `completion()`, `strategy()`, `store()`.
37
38#[derive(Debug, Clone)]
39pub struct AggregatorSpec {
40 id: Option<String>,
41 correlation_header: String,
42 completion: String,
43 strategy: Option<String>,
44 store: Option<String>,
45}
46
47impl AggregatorSpec {
48 pub fn new<H: Into<String>, C: Into<String>>(correlation_header: H, completion: C) -> Self {
49 Self {
50 id: None,
51 correlation_header: correlation_header.into(),
52 completion: completion.into(),
53 strategy: None,
54 store: None,
55 }
56 }
57
58 pub fn with_id<I, H, C>(id: I, correlation_header: H, completion: C) -> Self
59 where
60 I: Into<String>,
61 H: Into<String>,
62 C: Into<String>,
63 {
64 Self {
65 id: Some(id.into()),
66 correlation_header: correlation_header.into(),
67 completion: completion.into(),
68 strategy: None,
69 store: None,
70 }
71 }
72
73 pub fn set_strategy<S: Into<String>>(mut self, strategy: S) -> Self {
74 self.strategy = Some(strategy.into());
75 self
76 }
77
78 pub fn set_store<S: Into<String>>(mut self, store: S) -> Self {
79 self.store = Some(store.into());
80 self
81 }
82
83 pub fn id(&self) -> Option<&str> {
84 self.id.as_deref()
85 }
86 pub fn correlation_header(&self) -> &str {
87 &self.correlation_header
88 }
89 pub fn completion(&self) -> &str {
90 &self.completion
91 }
92 pub fn strategy(&self) -> Option<&str> {
93 self.strategy.as_deref()
94 }
95 pub fn store(&self) -> Option<&str> {
96 self.store.as_deref()
97 }
98
99 /// Internal: builder assigns an auto-generated id.
100 pub fn set_id(&mut self, id: String) {
101 self.id = Some(id);
102 }
103}