canic_core/ops/orchestration/cascade/
mod.rs

1//! Cascade propagation.
2//!
3//! Pushes environment/topology/state changes from root to child canisters.
4//! This is orchestration logic (fanout), not storage and not placement strategy.
5
6pub mod state;
7pub mod topology;
8
9use crate::{Error, ThisError, log, log::Topic, ops::orchestration::OrchestrationOpsError};
10use candid::Principal;
11
12const SYNC_CALL_WARN_THRESHOLD: usize = 10;
13
14///
15/// CascadeOpsError
16/// Errors raised during synchronization
17///
18
19#[derive(Debug, ThisError)]
20pub enum CascadeOpsError {
21    #[error("canister not found")]
22    CanisterNotFound(Principal),
23
24    #[error("root canister not found")]
25    RootNotFound,
26
27    #[error("invalid parent chain: empty")]
28    InvalidParentChain,
29
30    #[error("parent chain does not start with self ({0})")]
31    ParentChainMissingSelf(Principal),
32
33    #[error("cycle detected in parent chain at {0}")]
34    ParentChainCycle(Principal),
35
36    #[error("parent chain length {0} exceeds registry size")]
37    ParentChainTooLong(usize),
38
39    #[error("parent chain did not terminate at root (stopped at {0})")]
40    ParentChainNotRootTerminated(Principal),
41
42    #[error("next hop {0} not found in parent chain")]
43    NextHopNotFound(Principal),
44}
45
46impl From<CascadeOpsError> for Error {
47    fn from(err: CascadeOpsError) -> Self {
48        OrchestrationOpsError::from(err).into()
49    }
50}
51
52///
53/// Helpers
54///
55
56fn warn_if_large(label: &str, count: usize) {
57    if count > SYNC_CALL_WARN_THRESHOLD {
58        log!(
59            Topic::Sync,
60            Warn,
61            "sync: large {}: {} entries",
62            label,
63            count
64        );
65    }
66}