pub(super) fn run<'b>(
        &mut self,
        query: UserQuery,
        metrics: &'b QueryHandlerMetrics,
        measurement_scope: &MeasurementScope<'b>,
    ) -> Result<WasmResult, UserError> {
        let canister_id = query.receiver;
        debug!(self.log, "Executing query for {}", canister_id);
        let old_canister = self.get_canister_from_state(&canister_id)?;
        let call_origin = CallOrigin::Query(query.source);
        // EXC-500: Contain the usage of inter-canister query calls to the subnets
        // that currently use it until we decide on the future of this feature and
        // get a proper spec for it.
        let cross_canister_query_calls_enabled = self.own_subnet_type == SubnetType::System
            || self.own_subnet_type == SubnetType::VerifiedApplication;
        let query_kind = if ENABLE_QUERY_OPTIMIZATION || !cross_canister_query_calls_enabled {
            NonReplicatedQueryKind::Pure
        } else {
            NonReplicatedQueryKind::Stateful
        };

        // First try to run the query as `Pure` assuming that it is not going to
        // call other queries. `Pure` queries are about 2x faster than `Stateful`.
        let (mut canister, mut result) = {
            let measurement_scope =
                MeasurementScope::nested(&metrics.query_initial_call, measurement_scope);
            self.execute_query(
                old_canister,
                call_origin.clone(),
                query.method_name.as_str(),
                query.method_payload.as_slice(),
                query.source.get(),
                query_kind.clone(),
                &measurement_scope,
            )
        };

        // An attempt to call another query will result in `ContractViolation`.
        // If that's the case then retry query execution as `Stateful`.
        if query_kind == NonReplicatedQueryKind::Pure && cross_canister_query_calls_enabled {
            if let Err(HypervisorError::ContractViolation(..)) = result {
                let measurement_scope =
                    MeasurementScope::nested(&metrics.query_retry_call, measurement_scope);
                let old_canister = self.get_canister_from_state(&canister_id)?;
                let (new_canister, new_result) = self.execute_query(
                    old_canister,
                    call_origin,
                    query.method_name.as_str(),
                    query.method_payload.as_slice(),
                    query.source.get(),
                    NonReplicatedQueryKind::Stateful,
                    &measurement_scope,
                );
                canister = new_canister;
                result = new_result;
            };
        }

        match result {
            // If the canister produced a result or if execution failed then it
            // does not matter whether or not it produced any outgoing requests.
            // We can simply return the response we have.
            Err(err) => Err(err.into_user_error(&canister_id)),
            Ok(Some(wasm_result)) => Ok(wasm_result),

            Ok(None) => match self.enqueue_requests(&mut canister) {
                EnqueueRequestsResult::LoopDetected => Err(UserError::new(
                    ErrorCode::InterCanisterQueryLoopDetected,
                    LOOP_DETECTED_ERROR_MSG.to_string(),
                )),

                // The canister did not produce a response and did not enqueue
                // any requests either. As this is the very first canister in
                // the call graph, we can declare that the query execution
                // finished without producing an output.
                EnqueueRequestsResult::NoMessages => Err(UserError::new(
                    ErrorCode::CanisterDidNotReply,
                    format!(
                        "Canister {} did not reply to the call",
                        canister.canister_id()
                    ),
                )),

                EnqueueRequestsResult::MessagesEnqueued => {
                    self.canisters.insert(canister.canister_id(), canister);
                    self.run_loop(canister_id, metrics, measurement_scope)
                }
            },
        }
    }
/// Executes the given Query sent by an end user.
///
/// - If it produces a response return the response.
///
/// - If it does not produce a response and does not send further queries,
/// then return a response indicating that the canister did not reply.
///
/// - If it does not produce a response and produces additional
/// inter-canister queries, process them till there is a response or the
/// call graph finishes with no reply.
Executes the given Query sent by an end user.
If it produces a response return the response.

If it does not produce a response and does not send further queries,
then return a response indicating that the canister did not reply.

If it does not produce a response and produces additional
inter-canister queries, process them till there is a response or the
call graph finishes with no reply.
Executes the given Query sent by an end user . If it produces a response return the response . If it does not produce a response and does not send further queries then return a response indicating that the canister did not reply . If it does not produce a response and produces additional inter - canister queries process them till there is a response or the call graph finishes with no reply .
pub(super) fn run<'b>(
        &mut self,
        query: UserQuery,
        metrics: &'b QueryHandlerMetrics,
        measurement_scope: &MeasurementScope<'b>,
    ) -> Result<WasmResult, UserError> {
        let canister_id = query.receiver;
        debug!(self.log, "Executing query for {}", canister_id);
        let old_canister = self.get_canister_from_state(&canister_id)?;
        let call_origin = CallOrigin::Query(query.source);
        // EXC-500: Contain the usage of inter-canister query calls to the subnets
        // that currently use it until we decide on the future of this feature and
        // get a proper spec for it.
        let cross_canister_query_calls_enabled = self.own_subnet_type == SubnetType::System
            || self.own_subnet_type == SubnetType::VerifiedApplication;
        let query_kind = if ENABLE_QUERY_OPTIMIZATION || !cross_canister_query_calls_enabled {
            NonReplicatedQueryKind::Pure
        } else {
            NonReplicatedQueryKind::Stateful
        };
        // First try to run the query as `Pure` assuming that it is not going to
        // call other queries. `Pure` queries are about 2x faster than `Stateful`.
        let (mut canister, mut result) = {
            let measurement_scope =
                MeasurementScope::nested(&metrics.query_initial_call, measurement_scope);
            self.execute_query(
                old_canister,
                call_origin.clone(),
                query.method_name.as_str(),
                query.method_payload.as_slice(),
                query.source.get(),
                query_kind.clone(),
                &measurement_scope,
            )
        };
        // An attempt to call another query will result in `ContractViolation`.
        // If that's the case then retry query execution as `Stateful`.
        if query_kind == NonReplicatedQueryKind::Pure && cross_canister_query_calls_enabled {
            if let Err(HypervisorError::ContractViolation(..)) = result {
                let measurement_scope =
                    MeasurementScope::nested(&metrics.query_retry_call, measurement_scope);
                let old_canister = self.get_canister_from_state(&canister_id)?;
                let (new_canister, new_result) = self.execute_query(
                    old_canister,
                    call_origin,
                    query.method_name.as_str(),
                    query.method_payload.as_slice(),
                    query.source.get(),
                    NonReplicatedQueryKind::Stateful,
                    &measurement_scope,
                );
                canister = new_canister;
                result = new_result;
            };
        }
        match result {
            // If the canister produced a result or if execution failed then it
            // does not matter whether or not it produced any outgoing requests.
            // We can simply return the response we have.
            Err(err) => Err(err.into_user_error(&canister_id)),
            Ok(Some(wasm_result)) => Ok(wasm_result),
            Ok(None) => match self.enqueue_requests(&mut canister) {
                EnqueueRequestsResult::LoopDetected => Err(UserError::new(
                    ErrorCode::InterCanisterQueryLoopDetected,
                    LOOP_DETECTED_ERROR_MSG.to_string(),
                )),
                // The canister did not produce a response and did not enqueue
                // any requests either. As this is the very first canister in
                // the call graph, we can declare that the query execution
                // finished without producing an output.
                EnqueueRequestsResult::NoMessages => Err(UserError::new(
                    ErrorCode::CanisterDidNotReply,
                    format!(
                        "Canister {} did not reply to the call",
                        canister.canister_id()
                    ),
                )),
                EnqueueRequestsResult::MessagesEnqueued => {
                    self.canisters.insert(canister.canister_id(), canister);
                    self.run_loop(canister_id, metrics, measurement_scope)
                }
            },
        }
    }
pub ( super ) fn run < ' b > ( & mut self , query : UserQuery , metrics : & ' b QueryHandlerMetrics , measurement_scope : & MeasurementScope < ' b > , ) -> Result < WasmResult , UserError > { let canister_id = query . receiver ; debug ! ( self log " " canister_id ) ; let old_canister = self . get_canister_from_state ( & canister_id ) ? ; let call_origin = CallOrigin :: Query ( query . source ) ; // EXC-500: Contain the usage of inter-canister query calls to the subnets // that currently use it until we decide on the future of this feature and // get a proper spec for it. let cross_canister_query_calls_enabled = self . own_subnet_type == SubnetType :: System || self . own_subnet_type == SubnetType :: VerifiedApplication ; let query_kind = if ENABLE_QUERY_OPTIMIZATION || ! cross_canister_query_calls_enabled { NonReplicatedQueryKind :: Pure } else { NonReplicatedQueryKind :: Stateful } ; // First try to run the query as `Pure` assuming that it is not going to // call other queries. `Pure` queries are about 2x faster than `Stateful`. let ( mut canister , mut result ) = { let measurement_scope = MeasurementScope :: nested ( & metrics . query_initial_call , measurement_scope ) ; self . execute_query ( old_canister , call_origin . clone ( ) , query . method_name . as_str ( ) , query . method_payload . as_slice ( ) , query . source . get ( ) , query_kind . clone ( ) , & measurement_scope , ) } ; // An attempt to call another query will result in `ContractViolation`. // If that's the case then retry query execution as `Stateful`. if query_kind == NonReplicatedQueryKind :: Pure && cross_canister_query_calls_enabled { if let Err ( HypervisorError :: ContractViolation ( .. ) ) = result { let measurement_scope = MeasurementScope :: nested ( & metrics . query_retry_call , measurement_scope ) ; let old_canister = self . get_canister_from_state ( & canister_id ) ? ; let ( new_canister , new_result ) = self . execute_query ( old_canister , call_origin , query . method_name . as_str ( ) , query . method_payload . as_slice ( ) , query . source . get ( ) , NonReplicatedQueryKind :: Stateful , & measurement_scope , ) ; canister = new_canister ; result = new_result ; } ; } match result { // If the canister produced a result or if execution failed then it // does not matter whether or not it produced any outgoing requests. // We can simply return the response we have. Err ( err ) => Err ( err . into_user_error ( & canister_id ) ) , Ok ( Some ( wasm_result ) ) => Ok ( wasm_result ) , Ok ( None ) => match self . enqueue_requests ( & mut canister ) { EnqueueRequestsResult :: LoopDetected => Err ( UserError :: new ( ErrorCode :: InterCanisterQueryLoopDetected , LOOP_DETECTED_ERROR_MSG . to_string ( ) , ) ) , // The canister did not produce a response and did not enqueue // any requests either. As this is the very first canister in // the call graph, we can declare that the query execution // finished without producing an output. EnqueueRequestsResult :: NoMessages => Err ( UserError :: new ( ErrorCode :: CanisterDidNotReply , format ! ( " " canister canister_id ( ) ) , ) ) , EnqueueRequestsResult :: MessagesEnqueued => { self . canisters . insert ( canister . canister_id ( ) , canister ) ; self . run_loop ( canister_id , metrics , measurement_scope ) } } , } }
Executes the given Query sent by an end user.
Executes the given Query sent by an end user .
&mut self
query
UserQuery
metrics
&'b QueryHandlerMetrics
measurement_scope
&MeasurementScope<'b>
&mut self
query
UserQuery
metrics
&'b QueryHandlerMetrics
measurement_scope
&MeasurementScope<'b>