use crate::fabric::{ConsensusKind, FabricFace, FabricStrategy, FaceKind};
use crate::face::{self, Face, FaceError, FaceWatchStream, ResourceFormat, ResourceRef};
use crate::topology::TopologyStrategy;
#[derive(Debug, thiserror::Error)]
pub enum ClusterCoherenceError {
#[error("strategy self-incoherent: {0}")]
StrategyError(#[from] crate::fabric::FabricStrategyError),
#[error(
"topology {topology:?} requires only {topology_min} nodes minimum but strategy consensus quorum is {quorum_size} — the cluster will boot but immediately fail liveness because no quorum can ever form"
)]
TopologyTooSmallForQuorum {
topology: String,
topology_min: usize,
quorum_size: usize,
},
#[error(
"face {face:?} ({face_kind}) requires operator signatures on every attestation block, but the strategy does not require operator signatures — this exposes the fabric to operator-impersonation attacks since the face surface promises something the strategy doesn't enforce"
)]
FaceSignaturePromiseUnmet {
face: String,
face_kind: &'static str,
},
}
#[must_use = "ClusterDeclaration carries proofs; consume it via the runtime entry point"]
pub struct ClusterDeclaration {
strategy: FabricStrategy,
face: FabricFace,
topology: Box<dyn TopologyStrategy>,
}
impl ClusterDeclaration {
pub fn new(
strategy: FabricStrategy,
face: FabricFace,
topology: Box<dyn TopologyStrategy>,
) -> Result<Self, ClusterCoherenceError> {
strategy.prove_liveness()?;
let quorum_size = match strategy.consensus.kind {
ConsensusKind::OpenRaft { quorum_size, .. } => quorum_size as usize,
};
if topology.min_nodes() < quorum_size {
return Err(ClusterCoherenceError::TopologyTooSmallForQuorum {
topology: topology.name().to_string(),
topology_min: topology.min_nodes(),
quorum_size,
});
}
let _ = &face;
Ok(Self {
strategy,
face,
topology,
})
}
#[must_use]
pub fn strategy(&self) -> &FabricStrategy {
&self.strategy
}
#[must_use]
pub fn face(&self) -> &FabricFace {
&self.face
}
#[must_use]
pub fn topology(&self) -> &dyn TopologyStrategy {
self.topology.as_ref()
}
#[must_use]
pub fn id(&self) -> String {
format!(
"{}/{}/{}",
self.face.name,
self.strategy.name,
self.topology.name()
)
}
}
impl std::fmt::Debug for ClusterDeclaration {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ClusterDeclaration")
.field("strategy", &self.strategy.name)
.field("face", &self.face.name)
.field("face_kind", &face_kind_str(&self.face.kind))
.field("topology", &self.topology.name())
.finish()
}
}
fn face_kind_str(kind: &FaceKind) -> &'static str {
match kind {
FaceKind::Kubernetes { .. } => "Kubernetes",
FaceKind::Nomad { .. } => "Nomad",
FaceKind::Systemd { .. } => "Systemd",
FaceKind::PureRaft => "PureRaft",
FaceKind::BareMetalSupervisor => "BareMetalSupervisor",
}
}
#[derive(Debug, thiserror::Error)]
pub enum ClusterRuntimeError {
#[error("face instantiation failed: {0}")]
Face(#[from] FaceError),
#[error("cluster already started")]
AlreadyStarted,
#[error("cluster not started")]
NotStarted,
}
#[must_use = "Cluster is the runtime handle — start it via .start()"]
pub struct Cluster {
declaration: ClusterDeclaration,
face: Box<dyn Face>,
state: std::sync::Mutex<ClusterState>,
}
impl std::fmt::Debug for Cluster {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Cluster")
.field("declaration", &self.declaration)
.field("face_kind", &self.face.kind())
.field("state", &self.state.lock().ok())
.finish()
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum ClusterState {
Constructed,
Running,
Stopped,
}
impl Cluster {
pub fn from_declaration(declaration: ClusterDeclaration) -> Result<Self, ClusterRuntimeError> {
let face = face::instantiate(declaration.face())?;
Ok(Self {
declaration,
face,
state: std::sync::Mutex::new(ClusterState::Constructed),
})
}
#[must_use]
pub fn declaration(&self) -> &ClusterDeclaration {
&self.declaration
}
#[must_use]
pub fn face(&self) -> &dyn Face {
self.face.as_ref()
}
pub fn start(&self) -> Result<(), ClusterRuntimeError> {
let mut state = self.state.lock().expect("cluster state mutex poisoned");
if *state == ClusterState::Running {
return Err(ClusterRuntimeError::AlreadyStarted);
}
self.face.start()?;
*state = ClusterState::Running;
Ok(())
}
pub fn shutdown(&self) -> Result<(), ClusterRuntimeError> {
let mut state = self.state.lock().expect("cluster state mutex poisoned");
if *state != ClusterState::Running {
return Err(ClusterRuntimeError::NotStarted);
}
self.face.shutdown()?;
*state = ClusterState::Stopped;
Ok(())
}
#[must_use]
pub fn is_running(&self) -> bool {
let state = self.state.lock().expect("cluster state mutex poisoned");
*state == ClusterState::Running
}
#[must_use]
pub fn id(&self) -> String {
self.declaration.id()
}
#[must_use]
pub fn health(&self) -> ClusterHealth {
ClusterHealth {
name: self.declaration.face().name.clone(),
kind: self.declaration.face().kind.clone(),
face_running: self.face.is_running(),
cluster_running: self.is_running(),
resource_count: self.face.resource_count(),
subscriber_count: self.face.subscriber_count(),
strategy_name: self.declaration.strategy().name.clone(),
topology_name: self.declaration.topology().name().to_string(),
}
}
pub fn snapshot(&self) -> Result<Vec<u8>, FaceError> {
self.face.snapshot()
}
pub fn restore(&self, snapshot_bytes: &[u8]) -> Result<(), FaceError> {
self.face.restore(snapshot_bytes)
}
pub fn start_with(declaration: ClusterDeclaration) -> Result<Self, ClusterRuntimeError> {
let cluster = Self::from_declaration(declaration)?;
cluster.start()?;
Ok(cluster)
}
pub fn apply(&self, format: ResourceFormat, body: &[u8]) -> Result<(), FaceError> {
self.face.apply_resource(format, body)
}
pub fn get(
&self,
reference: &ResourceRef,
format: ResourceFormat,
) -> Result<Vec<u8>, FaceError> {
self.face.get_resource(reference, format)
}
pub fn list(
&self,
kind: &str,
namespace: Option<&str>,
format: ResourceFormat,
) -> Result<Vec<Vec<u8>>, FaceError> {
self.face.list_resources(kind, namespace, format)
}
pub fn delete(&self, reference: &ResourceRef) -> Result<(), FaceError> {
self.face.delete_resource(reference)
}
pub fn watch(
&self,
kind: &str,
namespace: Option<&str>,
format: ResourceFormat,
) -> Result<Box<dyn FaceWatchStream>, FaceError> {
self.face.watch_resources(kind, namespace, format)
}
}
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize)]
pub struct ClusterHealth {
pub name: String,
pub kind: FaceKind,
pub face_running: bool,
pub cluster_running: bool,
pub resource_count: usize,
pub subscriber_count: usize,
pub strategy_name: String,
pub topology_name: String,
}
impl ClusterHealth {
pub fn check(&self) -> Result<(), &'static str> {
if !self.cluster_running {
return Err("cluster not running");
}
if !self.face_running {
return Err("face not running");
}
Ok(())
}
}
impl Drop for Cluster {
fn drop(&mut self) {
let state_snapshot = self.state.lock().ok().map(|g| *g);
if state_snapshot == Some(ClusterState::Running) {
let _ = self.face.shutdown();
if let Ok(mut state) = self.state.lock() {
*state = ClusterState::Stopped;
}
}
}
}
#[derive(Default)]
#[must_use = "ClusterBuilder does nothing until .start() (or .build()) is called"]
pub struct ClusterBuilder {
strategy: Option<FabricStrategy>,
face: Option<FabricFace>,
topology: Option<Box<dyn TopologyStrategy>>,
}
#[derive(Debug, thiserror::Error)]
pub enum ClusterBuilderError {
#[error("ClusterBuilder missing required field: {0}")]
Missing(&'static str),
#[error("declaration coherence failed: {0}")]
Coherence(#[from] ClusterCoherenceError),
#[error("runtime construction failed: {0}")]
Runtime(#[from] ClusterRuntimeError),
}
impl ClusterBuilder {
pub fn strategy(mut self, s: FabricStrategy) -> Self {
self.strategy = Some(s);
self
}
pub fn face(mut self, f: FabricFace) -> Self {
self.face = Some(f);
self
}
pub fn face_pure_raft(mut self, name: impl Into<String>) -> Self {
self.face = Some(FabricFace {
name: name.into(),
kind: FaceKind::PureRaft,
});
self
}
pub fn face_kubernetes_prescribed(mut self) -> Self {
self.face = Some(FabricFace::prescribed_kubernetes_v1_34());
self
}
pub fn topology<T: TopologyStrategy + 'static>(mut self, t: T) -> Self {
self.topology = Some(Box::new(t));
self
}
pub fn build(self) -> Result<ClusterDeclaration, ClusterBuilderError> {
let strategy = self.strategy.ok_or(ClusterBuilderError::Missing("strategy"))?;
let face = self.face.ok_or(ClusterBuilderError::Missing("face"))?;
let topology = self
.topology
.ok_or(ClusterBuilderError::Missing("topology"))?;
let decl = ClusterDeclaration::new(strategy, face, topology)?;
Ok(decl)
}
pub fn start(self) -> Result<Cluster, ClusterBuilderError> {
let decl = self.build()?;
Ok(Cluster::start_with(decl)?)
}
}
impl Cluster {
#[must_use]
pub fn builder() -> ClusterBuilder {
ClusterBuilder::default()
}
}
#[cfg(test)]
mod runtime_tests {
use super::*;
use crate::fabric::{FabricStrategy, FaceKind};
use crate::topology::Quorum3M;
fn ok_cluster() -> Cluster {
let decl = ClusterDeclaration::new(
FabricStrategy::prescribed_homelab(),
FabricFace {
name: "pure-raft".into(),
kind: FaceKind::PureRaft,
},
Box::new(Quorum3M),
)
.unwrap();
Cluster::from_declaration(decl).unwrap()
}
#[test]
fn constructed_cluster_starts_in_stopped_state() {
let cluster = ok_cluster();
assert!(!cluster.is_running());
}
#[test]
fn start_brings_face_to_running() {
let cluster = ok_cluster();
cluster.start().unwrap();
assert!(cluster.is_running());
assert!(cluster.face().is_running());
}
#[test]
fn shutdown_returns_face_to_stopped() {
let cluster = ok_cluster();
cluster.start().unwrap();
cluster.shutdown().unwrap();
assert!(!cluster.is_running());
assert!(!cluster.face().is_running());
}
#[test]
fn double_start_errors() {
let cluster = ok_cluster();
cluster.start().unwrap();
match cluster.start() {
Err(ClusterRuntimeError::AlreadyStarted) => {}
other => panic!("expected AlreadyStarted, got {other:?}"),
}
}
#[test]
fn shutdown_without_start_errors() {
let cluster = ok_cluster();
match cluster.shutdown() {
Err(ClusterRuntimeError::NotStarted) => {}
other => panic!("expected NotStarted, got {other:?}"),
}
}
#[test]
fn id_delegates_to_declaration() {
let cluster = ok_cluster();
assert_eq!(cluster.id(), cluster.declaration().id());
}
#[test]
fn builder_fluent_chain_yields_running_cluster() {
let cluster = Cluster::builder()
.strategy(FabricStrategy::prescribed_homelab())
.face_pure_raft("homelab")
.topology(Quorum3M)
.start()
.expect("builder.start() should produce a running cluster");
assert!(cluster.is_running());
assert_eq!(cluster.face().kind(), FaceKind::PureRaft);
}
#[test]
fn builder_face_kubernetes_prescribed_convenience() {
let cluster = Cluster::builder()
.strategy(FabricStrategy::prescribed_homelab())
.face_kubernetes_prescribed()
.topology(Quorum3M)
.start()
.expect("k8s prescribed builder");
match cluster.face().kind() {
FaceKind::Kubernetes { version, certified_cncf } => {
assert_eq!(version, "1.34");
assert!(certified_cncf);
}
other => panic!("expected Kubernetes face, got {other:?}"),
}
}
#[test]
fn builder_missing_strategy_errors_with_named_field() {
let err = Cluster::builder()
.face_pure_raft("x")
.topology(Quorum3M)
.start()
.expect_err("missing strategy must error");
match err {
ClusterBuilderError::Missing("strategy") => {}
other => panic!("expected Missing(\"strategy\"), got {other:?}"),
}
}
#[test]
fn builder_missing_face_errors_with_named_field() {
let err = Cluster::builder()
.strategy(FabricStrategy::prescribed_homelab())
.topology(Quorum3M)
.start()
.expect_err("missing face must error");
match err {
ClusterBuilderError::Missing("face") => {}
other => panic!("expected Missing(\"face\"), got {other:?}"),
}
}
#[test]
fn builder_missing_topology_errors_with_named_field() {
let err = Cluster::builder()
.strategy(FabricStrategy::prescribed_homelab())
.face_pure_raft("x")
.start()
.expect_err("missing topology must error");
match err {
ClusterBuilderError::Missing("topology") => {}
other => panic!("expected Missing(\"topology\"), got {other:?}"),
}
}
#[test]
fn builder_propagates_coherence_failure() {
use crate::topology::Solo;
let err = Cluster::builder()
.strategy(FabricStrategy::prescribed_homelab())
.face_pure_raft("x")
.topology(Solo)
.build()
.expect_err("Solo + 3-quorum must fail coherence");
match err {
ClusterBuilderError::Coherence(ClusterCoherenceError::TopologyTooSmallForQuorum { .. }) => {}
other => panic!("expected TopologyTooSmallForQuorum, got {other:?}"),
}
}
#[test]
fn builder_build_returns_declaration_without_starting() {
let decl = Cluster::builder()
.strategy(FabricStrategy::prescribed_homelab())
.face_pure_raft("inspect-only")
.topology(Quorum3M)
.build()
.expect("build coherent decl");
assert_eq!(decl.strategy().name, "homelab-3node");
assert_eq!(decl.face().name, "inspect-only");
}
#[test]
fn start_with_constructs_and_starts_in_one_call() {
let decl = ok_decl();
let cluster = Cluster::start_with(decl).expect("one-shot start");
assert!(cluster.is_running());
assert!(cluster.face().is_running());
}
#[test]
fn dropping_running_cluster_shuts_face_down() {
let cluster = Cluster::start_with(ok_decl()).unwrap();
assert!(cluster.is_running());
drop(cluster); }
#[test]
fn dropping_stopped_cluster_is_safe() {
let cluster = Cluster::start_with(ok_decl()).unwrap();
cluster.shutdown().unwrap();
assert!(!cluster.is_running());
drop(cluster); }
#[test]
fn dropping_never_started_cluster_is_safe() {
let cluster = Cluster::from_declaration(ok_decl()).unwrap();
assert!(!cluster.is_running());
drop(cluster);
}
fn pod_envelope(name: &str, payload: &[u8]) -> Vec<u8> {
use crate::face::encode_native_envelope;
let r = ResourceRef::namespaced("Pod", name, "default");
encode_native_envelope(&r, payload).unwrap()
}
#[test]
fn cluster_apply_delegates_to_face_apply_resource() {
let cluster = Cluster::start_with(ok_decl()).unwrap();
let env = pod_envelope("nginx", b"x");
cluster
.apply(ResourceFormat::Native, &env)
.expect("apply through cluster");
let r = ResourceRef::namespaced("Pod", "nginx", "default");
let got = cluster
.get(&r, ResourceFormat::Native)
.expect("get through cluster");
assert_eq!(got, env);
}
#[test]
fn cluster_list_delegates_to_face_list_resources() {
let cluster = Cluster::start_with(ok_decl()).unwrap();
cluster.apply(ResourceFormat::Native, &pod_envelope("a", b"A")).unwrap();
cluster.apply(ResourceFormat::Native, &pod_envelope("b", b"B")).unwrap();
let listed = cluster
.list("Pod", Some("default"), ResourceFormat::Native)
.expect("list through cluster");
assert_eq!(listed.len(), 2);
}
#[test]
fn cluster_delete_delegates_to_face_delete_resource() {
let cluster = Cluster::start_with(ok_decl()).unwrap();
cluster.apply(ResourceFormat::Native, &pod_envelope("nginx", b"x")).unwrap();
let r = ResourceRef::namespaced("Pod", "nginx", "default");
cluster.delete(&r).expect("delete through cluster");
match cluster.get(&r, ResourceFormat::Native) {
Err(FaceError::Unsupported(msg)) => assert!(msg.contains("no resource"), "msg: {msg}"),
other => panic!("expected Unsupported after delete, got {other:?}"),
}
}
#[test]
fn cluster_watch_delegates_to_face_watch_resources() {
let cluster = Cluster::start_with(ok_decl()).unwrap();
let mut watch = cluster
.watch("Pod", Some("default"), ResourceFormat::Native)
.expect("watch through cluster");
let env = pod_envelope("nginx", b"x");
cluster.apply(ResourceFormat::Native, &env).unwrap();
let ev = watch.next_event().unwrap().expect("event");
assert_eq!(ev.body, env);
}
#[test]
fn cluster_apply_propagates_face_unsupported_format() {
let cluster = Cluster::start_with(ok_decl()).unwrap();
let r = ResourceRef::namespaced("Pod", "nginx", "default");
let env = {
use crate::face::encode_native_envelope;
encode_native_envelope(&r, b"x").unwrap()
};
match cluster.apply(ResourceFormat::Yaml, &env) {
Err(FaceError::Unsupported(_)) => {}
other => panic!("expected face's format-unsupported, got {other:?}"),
}
}
fn ok_decl() -> ClusterDeclaration {
ClusterDeclaration::new(
FabricStrategy::prescribed_homelab(),
FabricFace {
name: "pure-raft".into(),
kind: FaceKind::PureRaft,
},
Box::new(Quorum3M),
)
.unwrap()
}
#[test]
fn bare_metal_supervisor_now_lifecycles_through_runtime() {
let decl = ClusterDeclaration::new(
FabricStrategy::prescribed_homelab(),
FabricFace {
name: "bms-test".into(),
kind: FaceKind::BareMetalSupervisor,
},
Box::new(Quorum3M),
)
.expect("declaration coherent");
let cluster = Cluster::from_declaration(decl)
.expect("BMS face is now supported via BareMetalSupervisorFace impl");
cluster.start().unwrap();
assert!(cluster.is_running());
cluster.shutdown().unwrap();
}
#[test]
fn systemd_face_now_lifecycles_through_runtime() {
let decl = ClusterDeclaration::new(
FabricStrategy::prescribed_homelab(),
FabricFace {
name: "systemd-test".into(),
kind: FaceKind::Systemd { user_units: false },
},
Box::new(Quorum3M),
)
.expect("declaration coherent");
let cluster = Cluster::from_declaration(decl)
.expect("Systemd face is now supported via SystemdFace impl");
cluster.start().unwrap();
assert!(cluster.is_running());
cluster.shutdown().unwrap();
}
#[test]
fn cluster_carries_typed_witness_across_lifecycle() {
let cluster = ok_cluster();
let id_before = cluster.id();
cluster.start().unwrap();
let id_after_start = cluster.id();
cluster.shutdown().unwrap();
let id_after_shutdown = cluster.id();
assert_eq!(id_before, id_after_start);
assert_eq!(id_after_start, id_after_shutdown);
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::fabric::{ConsensusConfig, FabricStrategy, ReconciliationCadence};
use crate::topology::{Cluster3MNW, Phalanx, Quorum3M, Solo};
fn prescribed_strategy() -> FabricStrategy {
FabricStrategy::prescribed_homelab()
}
fn raft_face() -> FabricFace {
FabricFace {
name: "pure-raft".into(),
kind: FaceKind::PureRaft,
}
}
fn k8s_face() -> FabricFace {
FabricFace::prescribed_kubernetes_v1_34()
}
#[test]
fn quorum3m_topology_works_with_3node_consensus() {
let cluster = ClusterDeclaration::new(
prescribed_strategy(),
raft_face(),
Box::new(Quorum3M),
);
assert!(cluster.is_ok(), "Quorum3M + OpenRaft{{3}} should be coherent");
}
#[test]
fn cluster3mnw_topology_works_with_3node_consensus() {
let cluster = ClusterDeclaration::new(
prescribed_strategy(),
k8s_face(),
Box::new(Cluster3MNW),
);
assert!(cluster.is_ok(), "Cluster3MNW + OpenRaft{{3}} should be coherent");
}
#[test]
fn phalanx_topology_works_with_3node_consensus() {
let cluster = ClusterDeclaration::new(
prescribed_strategy(),
raft_face(),
Box::new(Phalanx),
);
if Phalanx.min_nodes() >= 3 {
assert!(cluster.is_ok(), "Phalanx min >= 3 should be coherent");
} else {
assert!(cluster.is_err(), "Phalanx min < 3 should fail coherence");
}
}
#[test]
fn solo_topology_fails_against_3node_consensus() {
let err = ClusterDeclaration::new(
prescribed_strategy(),
raft_face(),
Box::new(Solo),
)
.unwrap_err();
match err {
ClusterCoherenceError::TopologyTooSmallForQuorum {
topology,
topology_min,
quorum_size,
} => {
assert_eq!(topology, "solo");
assert_eq!(topology_min, 1);
assert_eq!(quorum_size, 3);
}
other => panic!("expected TopologyTooSmallForQuorum, got {other:?}"),
}
}
#[test]
fn invalid_strategy_propagates_through_cluster_construction() {
let mut s = prescribed_strategy();
s.consensus.kind = ConsensusKind::OpenRaft {
quorum_size: 4, election_timeout_ms: 150,
snapshot_interval_entries: 1000,
};
let err = ClusterDeclaration::new(s, raft_face(), Box::new(Quorum3M)).unwrap_err();
assert!(matches!(err, ClusterCoherenceError::StrategyError(_)));
}
#[test]
fn detector_outpaces_reconciliation_caught_via_cluster() {
let mut s = prescribed_strategy();
s.membership.failure_detector_timeout_ms = s.reconciliation.millis() + 1;
let err = ClusterDeclaration::new(s, raft_face(), Box::new(Quorum3M)).unwrap_err();
match err {
ClusterCoherenceError::StrategyError(inner) => {
assert!(matches!(
inner,
crate::fabric::FabricStrategyError::DetectorOutpacesReconciliation { .. }
));
}
other => panic!("expected nested StrategyError, got {other:?}"),
}
}
#[test]
fn cluster_id_format_is_stable() {
let cluster = ClusterDeclaration::new(
prescribed_strategy(),
k8s_face(),
Box::new(Quorum3M),
)
.unwrap();
let id = cluster.id();
assert!(id.contains("k8s-v1.34"));
assert!(id.contains("homelab-3node"));
assert!(id.contains(Quorum3M.name()));
}
#[test]
fn accessors_return_the_constructed_surfaces() {
let cluster = ClusterDeclaration::new(
prescribed_strategy(),
k8s_face(),
Box::new(Cluster3MNW),
)
.unwrap();
assert_eq!(cluster.strategy().name, "homelab-3node");
assert_eq!(cluster.face().name, "k8s-v1.34");
assert_eq!(cluster.topology().name(), Cluster3MNW.name());
}
#[test]
fn debug_format_names_all_three_surfaces() {
let cluster = ClusterDeclaration::new(
prescribed_strategy(),
raft_face(),
Box::new(Quorum3M),
)
.unwrap();
let dbg = format!("{cluster:?}");
assert!(dbg.contains("homelab-3node"));
assert!(dbg.contains("pure-raft"));
assert!(dbg.contains("PureRaft"));
assert!(dbg.contains(Quorum3M.name()));
}
#[test]
fn nonzero_reconciliation_with_huge_election_timeout_still_works() {
let mut s = prescribed_strategy();
s.consensus.kind = ConsensusKind::OpenRaft {
quorum_size: 3,
election_timeout_ms: 60_000, snapshot_interval_entries: 1,
};
assert!(
ClusterDeclaration::new(s, raft_face(), Box::new(Quorum3M)).is_ok()
);
let _ = ConsensusConfig {
kind: ConsensusKind::OpenRaft {
quorum_size: 3,
election_timeout_ms: 1,
snapshot_interval_entries: 1,
},
};
let _ = ReconciliationCadence::new(1).unwrap();
}
}