canic_host/canister_ready/
mod.rs1use crate::{
8 icp::{IcpCli, IcpCommandError, IcpJsonResponseError, decode_json_result_response},
9 icp_config::IcpConfigError,
10 protocol_binding::ResolvedProtocolBinding,
11 replica_query::{self, ReplicaQueryError},
12};
13use candid::{CandidType, Deserialize};
14use canic_core::{
15 dto::runtime::{CanicReadinessStatus, ReadinessStatus},
16 protocol::CANIC_STATUS,
17};
18use std::path::Path;
19use thiserror::Error as ThisError;
20
21const ICP_JSON_OUTPUT: &str = "json";
22
23#[derive(CandidType, Deserialize)]
24enum RoleStatusResponse {
25 Readiness(CanicReadinessStatus),
26}
27
28#[derive(Debug, ThisError)]
33pub enum CanisterReadyQueryError {
34 #[error(transparent)]
35 IcpConfig(#[from] IcpConfigError),
36
37 #[error(transparent)]
38 Icp(#[from] IcpCommandError),
39
40 #[error(transparent)]
41 Replica(#[from] ReplicaQueryError),
42
43 #[error(transparent)]
44 Response(#[from] IcpJsonResponseError),
45}
46
47pub fn query_canister_ready(
49 icp: &IcpCli,
50 canister_id: &str,
51 environment: &str,
52 icp_root: Option<&Path>,
53 binding: &ResolvedProtocolBinding,
54) -> Result<bool, CanisterReadyQueryError> {
55 if replica_query::uses_local_replica_transport(Some(environment), icp_root)? {
56 return query_local_canister_ready(environment, canister_id, icp_root).map_err(Into::into);
57 }
58
59 query_canister_ready_with_icp(icp, canister_id, binding)
60}
61
62pub fn query_local_canister_ready(
64 environment: &str,
65 canister_id: &str,
66 icp_root: Option<&Path>,
67) -> Result<bool, ReplicaQueryError> {
68 replica_query::query_ready(Some(environment), canister_id, icp_root)
69}
70
71fn query_canister_ready_with_icp(
72 icp: &IcpCli,
73 canister_id: &str,
74 binding: &ResolvedProtocolBinding,
75) -> Result<bool, CanisterReadyQueryError> {
76 let output = icp.canister_query_arg_output_with_candid(
77 canister_id,
78 CANIC_STATUS,
79 "(variant { Readiness })",
80 Some(ICP_JSON_OUTPUT),
81 Some(&binding.candid_path),
82 )?;
83 let response = decode_json_result_response::<RoleStatusResponse>(&output)?;
84 let RoleStatusResponse::Readiness(response) = response;
85 Ok(response.status == ReadinessStatus::Ready)
86}