ic-query 0.80.0

Internet Computer query library for CloudEngine, NNS, SNS, ICRC, system canisters, and public network metadata
Documentation
use crate::nns::inventory::{
    NnsInventoryInputKind, NnsInventoryResolveError, resolve_nns_inventory_row,
};

use super::{
    NNS_DATA_CENTER_INFO_REPORT_SCHEMA_VERSION, NnsDataCenterHostError, NnsDataCenterInfoReport,
    NnsDataCenterListReport, NnsInventoryInfoRequest, NnsInventoryListRequest,
    cache::{load_cached_nns_data_center_report, nns_data_center_cache_path},
    refresh::refresh_nns_data_center_report_with_source,
    source::NnsDataCenterSource,
};
use crate::nns::{LiveNnsSource, inventory::load_or_refresh_nns_inventory_report};
use crate::{QueryProgress, progress::IgnoreQueryProgress};

pub async fn build_nns_data_center_list_report(
    request: &NnsInventoryListRequest,
) -> Result<NnsDataCenterListReport, NnsDataCenterHostError> {
    build_nns_data_center_list_report_with_source(request, &LiveNnsSource::default()).await
}

pub async fn build_nns_data_center_info_report(
    request: &NnsInventoryInfoRequest,
) -> Result<NnsDataCenterInfoReport, NnsDataCenterHostError> {
    build_nns_data_center_info_report_with_source(request, &LiveNnsSource::default()).await
}

/// Build the report while reporting authorized cache refreshes.
pub async fn build_nns_data_center_list_report_with_progress(
    request: &NnsInventoryListRequest,
    progress: &mut dyn QueryProgress,
) -> Result<NnsDataCenterListReport, NnsDataCenterHostError> {
    build_nns_data_center_list_report_with_source_and_progress(
        request,
        &LiveNnsSource::default(),
        progress,
    )
    .await
}

pub async fn build_nns_data_center_list_report_with_source(
    request: &NnsInventoryListRequest,
    source: &dyn NnsDataCenterSource,
) -> Result<NnsDataCenterListReport, NnsDataCenterHostError> {
    build_nns_data_center_list_report_with_source_and_progress(
        request,
        source,
        &mut IgnoreQueryProgress,
    )
    .await
}

/// Build the report with a caller-owned source and progress sink.
pub async fn build_nns_data_center_list_report_with_source_and_progress(
    request: &NnsInventoryListRequest,
    source: &dyn NnsDataCenterSource,
    progress: &mut dyn QueryProgress,
) -> Result<NnsDataCenterListReport, NnsDataCenterHostError> {
    load_or_refresh_nns_inventory_report(
        request,
        nns_data_center_cache_path(&request.cache.cache_root, &request.cache.network),
        progress,
        |cache| load_cached_nns_data_center_report(cache).map(|cached| cached.report),
        async |refresh_request| {
            refresh_nns_data_center_report_with_source(refresh_request, source)
                .await
                .map(|_| ())
        },
    )
    .await
}

/// Build the report while reporting authorized cache refreshes.
pub async fn build_nns_data_center_info_report_with_progress(
    request: &NnsInventoryInfoRequest,
    progress: &mut dyn QueryProgress,
) -> Result<NnsDataCenterInfoReport, NnsDataCenterHostError> {
    build_nns_data_center_info_report_with_source_and_progress(
        request,
        &LiveNnsSource::default(),
        progress,
    )
    .await
}

pub async fn build_nns_data_center_info_report_with_source(
    request: &NnsInventoryInfoRequest,
    source: &dyn NnsDataCenterSource,
) -> Result<NnsDataCenterInfoReport, NnsDataCenterHostError> {
    build_nns_data_center_info_report_with_source_and_progress(
        request,
        source,
        &mut IgnoreQueryProgress,
    )
    .await
}

/// Build the report with a caller-owned source and progress sink.
pub async fn build_nns_data_center_info_report_with_source_and_progress(
    request: &NnsInventoryInfoRequest,
    source: &dyn NnsDataCenterSource,
    progress: &mut dyn QueryProgress,
) -> Result<NnsDataCenterInfoReport, NnsDataCenterHostError> {
    let list_request = request.to_list_request();
    let mut report =
        build_nns_data_center_list_report_with_source_and_progress(&list_request, source, progress)
            .await?;
    let (index, resolved_from) = resolve_data_center(&report, &request.input)?;
    let data_center = report.data_centers.swap_remove(index);
    Ok(NnsDataCenterInfoReport {
        schema_version: NNS_DATA_CENTER_INFO_REPORT_SCHEMA_VERSION,
        input: request.input.clone(),
        resolved_from,
        network: report.network,
        registry_canister_id: report.registry_canister_id,
        registry_version: report.registry_version,
        fetched_at: report.fetched_at,
        source_endpoint: report.source_endpoint,
        fetched_by: report.fetched_by,
        data_center,
    })
}

pub(super) fn resolve_data_center(
    report: &NnsDataCenterListReport,
    input: &str,
) -> Result<(usize, String), NnsDataCenterHostError> {
    resolve_nns_inventory_row(
        &report.data_centers,
        |row| row.data_center_id.as_str(),
        input,
        NnsInventoryInputKind::Text,
        "data_center_id",
    )
    .map_err(|error| match error {
        NnsInventoryResolveError::NotFound { input } => {
            NnsDataCenterHostError::DataCenterNotFound { input }
        }
        NnsInventoryResolveError::Ambiguous { prefix, matches } => {
            NnsDataCenterHostError::AmbiguousDataCenterPrefix { prefix, matches }
        }
    })
}