Skip to main content

canic_host/subnet_registry/
mod.rs

1//! Module: subnet_registry
2//!
3//! Responsibility: query one root canister's maintained subnet registry.
4//! Does not own: registry state, endpoint DTOs, or deployment discovery policy.
5//! Boundary: selects one transport and returns validated canonical host entries.
6
7use crate::{
8    icp::{IcpCli, IcpCommandError},
9    registry::{RegistryEntry, RegistryParseError, parse_registry_entries},
10    replica_query::{self, ReplicaQueryError},
11};
12use std::path::Path;
13use thiserror::Error as ThisError;
14
15const CANIC_SUBNET_REGISTRY_METHOD: &str = "canic_subnet_registry";
16const ICP_JSON_OUTPUT: &str = "json";
17
18///
19/// SubnetRegistryQuery
20///
21
22#[derive(Clone, Debug, Eq, PartialEq)]
23pub struct SubnetRegistryQuery {
24    pub(crate) source: SubnetRegistryQuerySource,
25    pub entries: Vec<RegistryEntry>,
26}
27
28///
29/// SubnetRegistryQuerySource
30///
31
32#[derive(Clone, Copy, Debug, Eq, PartialEq)]
33pub(crate) enum SubnetRegistryQuerySource {
34    IcpCli,
35    LocalReplica,
36}
37
38///
39/// SubnetRegistryQueryError
40///
41
42#[derive(Debug, ThisError)]
43pub enum SubnetRegistryQueryError {
44    #[error(transparent)]
45    Icp(#[from] IcpCommandError),
46
47    #[error(transparent)]
48    Registry(#[from] RegistryParseError),
49
50    #[error(transparent)]
51    Replica(#[from] ReplicaQueryError),
52}
53
54/// Query `canic_subnet_registry`, using the local replica API for local targets.
55pub fn query_subnet_registry(
56    icp: &IcpCli,
57    root: &str,
58    environment: &str,
59    icp_root: Option<&Path>,
60    candid_path: Option<&Path>,
61) -> Result<SubnetRegistryQuery, SubnetRegistryQueryError> {
62    if replica_query::should_use_local_replica_query(Some(environment)) {
63        return query_local_subnet_registry(root, environment, icp_root);
64    }
65
66    let output = icp.canister_query_output_with_candid(
67        root,
68        CANIC_SUBNET_REGISTRY_METHOD,
69        Some(ICP_JSON_OUTPUT),
70        candid_path,
71    )?;
72    Ok(SubnetRegistryQuery {
73        source: SubnetRegistryQuerySource::IcpCli,
74        entries: parse_registry_entries(&output)?,
75    })
76}
77
78fn query_local_subnet_registry(
79    root: &str,
80    environment: &str,
81    icp_root: Option<&Path>,
82) -> Result<SubnetRegistryQuery, SubnetRegistryQueryError> {
83    let entries = replica_query::query_subnet_registry_entries(Some(environment), root, icp_root)?;
84    Ok(SubnetRegistryQuery {
85        source: SubnetRegistryQuerySource::LocalReplica,
86        entries,
87    })
88}