canic-host 0.110.19

Host-side App build and desired-state Fleet reconciliation library for Canic workspaces
Documentation
//! Host-side App build and desired-state Fleet reconciliation for Canic workspaces.

use std::{
    io,
    process::{Child, Command, Output},
    thread,
    time::Duration,
};

const EXECUTABLE_BUSY_RETRY_ATTEMPTS: usize = 8;
const EXECUTABLE_BUSY_RETRY_DELAY: Duration = Duration::from_millis(10);

mod artifact_io;
pub mod binaryen;
mod bootstrap_candid;
mod bootstrap_coordinator;
mod bootstrap_store;
mod build_profile;
pub mod build_provenance;
pub mod build_toolchain;
pub mod candid_endpoints;
pub mod canic_metadata;
pub mod canister_build;
mod canister_protocol;
mod canonical_root;
mod fleet_package;
pub use canister_protocol::{
    CanisterProtocolError, call_with_arg as call_canister_with_arg,
    query_with_arg as query_canister_with_arg,
};
pub mod canister_ready;
mod cargo_metadata;
pub mod component_operation;
pub mod component_topology;
pub mod config_discovery;
pub mod diagnostics;
pub mod durable_io;
mod entropy;
pub mod evidence_envelope;
pub mod fleet_ensure;
pub mod format;
pub mod frontend;
pub mod ic_wasm;
pub mod icp;
pub mod icp_config;
#[cfg(feature = "local-fleet")]
pub mod local_fleet;
pub mod network;
pub mod observability;
pub mod observatory;
pub mod policy_gate;
pub mod protocol_binding;
pub mod registry;
pub mod release_build;
pub mod release_set;
pub mod replica_query;
pub mod role_contract;
pub mod state_manifest;
pub mod subnet_catalog;
pub mod table;
pub mod terminal;
#[cfg(test)]
mod test_support;
mod workspace_discovery;

pub(crate) fn cargo_command() -> Command {
    let cargo = std::env::var_os("CARGO").unwrap_or_else(|| "cargo".into());
    let mut command = Command::new(cargo);

    if let Some(toolchain) = std::env::var_os("RUSTUP_TOOLCHAIN") {
        command.env("RUSTUP_TOOLCHAIN", toolchain);
    }
    command
}

fn with_executable_busy_retry<T>(mut launch: impl FnMut() -> io::Result<T>) -> io::Result<T> {
    for attempt in 0..EXECUTABLE_BUSY_RETRY_ATTEMPTS {
        match launch() {
            Err(error)
                if error.kind() == io::ErrorKind::ExecutableFileBusy
                    && attempt + 1 < EXECUTABLE_BUSY_RETRY_ATTEMPTS =>
            {
                thread::sleep(EXECUTABLE_BUSY_RETRY_DELAY);
            }
            result => return result,
        }
    }
    unreachable!("bounded executable-busy retry always returns on its final attempt")
}

pub(crate) fn output_with_executable_busy_retry(command: &mut Command) -> io::Result<Output> {
    with_executable_busy_retry(|| command.output())
}

pub(crate) fn spawn_with_executable_busy_retry(command: &mut Command) -> io::Result<Child> {
    with_executable_busy_retry(|| command.spawn())
}

pub(crate) fn should_embed_candid_metadata(build_network: canic_core::ids::BuildNetwork) -> bool {
    build_network == canic_core::ids::BuildNetwork::Local
}

#[cfg(test)]
mod tests;