fn handle_request(
        &mut self,
        request: Request,
        measurement_scope: &MeasurementScope,
    ) -> Option<UserError> {
        // we are always prioritising responses over requests so when we execute
        // a request, there should not be any outstanding responses.
        if self.outstanding_response.is_some() {
            fatal!(
                self.log,
                "[EXC-BUG] Prioritising responses invariant failed. Handling a request when outstanding responses exist."
            );
        }

        let canister_id = request.receiver;
        // As we do not support loops in the call graph, the canister that we
        // want to execute a request on should not already be loaded.
        if self.canisters.contains_key(&canister_id) {
            error!(self.log, "[EXC-BUG] The canister that we want to execute a request on should not already be loaded.");
        }

        let canister = match self.get_canister_from_state(&request.receiver) {
            Ok(canister) => canister,
            Err(err) => {
                let payload = Payload::Reject(RejectContext::from(err));
                self.outstanding_response = Some(generate_response(request, payload));
                return None;
            }
        };

        let call_origin = CallOrigin::CanisterQuery(request.sender, request.sender_reply_callback);
        let (mut canister, result) = self.execute_query(
            canister,
            call_origin,
            request.method_name.as_str(),
            request.method_payload.as_slice(),
            request.sender.get(),
            NonReplicatedQueryKind::Stateful,
            measurement_scope,
        );

        match result {
            // Execution of the message failed. We do not need to bother with
            // any outstanding requests and we can return a response.
            Err(err) => {
                let err = err.into_user_error(&request.receiver);
                let payload = Payload::Reject(RejectContext::from(err));
                let response = generate_response(request, payload);
                self.outstanding_response = Some(response);
                None
            }

            Ok(opt_result) => {
                match opt_result {
                    // The canister produced a response. We do not need to
                    // handle any outgoing requests as we have the response we
                    // needed and we can return it.
                    Some(wasm_result) => {
                        let payload = match wasm_result {
                            WasmResult::Reply(data) => Payload::Data(data),
                            WasmResult::Reject(string) => Payload::Reject(RejectContext::new(
                                RejectCode::CanisterReject,
                                string,
                            )),
                        };
                        self.outstanding_response = Some(generate_response(request, payload));
                        None
                    }
                    None => match self.enqueue_requests(&mut canister) {
                        EnqueueRequestsResult::LoopDetected => Some(UserError::new(
                            ErrorCode::InterCanisterQueryLoopDetected,
                            LOOP_DETECTED_ERROR_MSG.to_string(),
                        )),

                        // The canister did not produce a response and did not
                        // produce any outgoing requests. So produce a "did not
                        // reply" response on its behalf.
                        EnqueueRequestsResult::NoMessages => {
                            let error_msg = format!("Canister {} did not reply", request.receiver);
                            let payload = Payload::Reject(RejectContext::new(
                                RejectCode::CanisterReject,
                                error_msg,
                            ));
                            self.outstanding_response = Some(generate_response(request, payload));
                            None
                        }

                        // Canister did not produce a response but did produce
                        // outgoing request(s). Save the canister for when the
                        // response(s) come back in.
                        EnqueueRequestsResult::MessagesEnqueued => {
                            self.canisters.insert(canister.canister_id(), canister);
                            None
                        }
                    },
                }
            }
        }
    }
// Executes a query sent from one canister to another. If a loop in the call
// graph is detected, then an error is returned.
Executes a query sent from one canister to another. If a loop in the call
graph is detected, then an error is returned.
Executes a query sent from one canister to another . If a loop in the call graph is detected then an error is returned .
fn handle_request(
        &mut self,
        request: Request,
        measurement_scope: &MeasurementScope,
    ) -> Option<UserError> {
        // we are always prioritising responses over requests so when we execute
        // a request, there should not be any outstanding responses.
        if self.outstanding_response.is_some() {
            fatal!(
                self.log,
                "[EXC-BUG] Prioritising responses invariant failed. Handling a request when outstanding responses exist."
            );
        }
        let canister_id = request.receiver;
        // As we do not support loops in the call graph, the canister that we
        // want to execute a request on should not already be loaded.
        if self.canisters.contains_key(&canister_id) {
            error!(self.log, "[EXC-BUG] The canister that we want to execute a request on should not already be loaded.");
        }
        let canister = match self.get_canister_from_state(&request.receiver) {
            Ok(canister) => canister,
            Err(err) => {
                let payload = Payload::Reject(RejectContext::from(err));
                self.outstanding_response = Some(generate_response(request, payload));
                return None;
            }
        };
        let call_origin = CallOrigin::CanisterQuery(request.sender, request.sender_reply_callback);
        let (mut canister, result) = self.execute_query(
            canister,
            call_origin,
            request.method_name.as_str(),
            request.method_payload.as_slice(),
            request.sender.get(),
            NonReplicatedQueryKind::Stateful,
            measurement_scope,
        );
        match result {
            // Execution of the message failed. We do not need to bother with
            // any outstanding requests and we can return a response.
            Err(err) => {
                let err = err.into_user_error(&request.receiver);
                let payload = Payload::Reject(RejectContext::from(err));
                let response = generate_response(request, payload);
                self.outstanding_response = Some(response);
                None
            }
            Ok(opt_result) => {
                match opt_result {
                    // The canister produced a response. We do not need to
                    // handle any outgoing requests as we have the response we
                    // needed and we can return it.
                    Some(wasm_result) => {
                        let payload = match wasm_result {
                            WasmResult::Reply(data) => Payload::Data(data),
                            WasmResult::Reject(string) => Payload::Reject(RejectContext::new(
                                RejectCode::CanisterReject,
                                string,
                            )),
                        };
                        self.outstanding_response = Some(generate_response(request, payload));
                        None
                    }
                    None => match self.enqueue_requests(&mut canister) {
                        EnqueueRequestsResult::LoopDetected => Some(UserError::new(
                            ErrorCode::InterCanisterQueryLoopDetected,
                            LOOP_DETECTED_ERROR_MSG.to_string(),
                        )),
                        // The canister did not produce a response and did not
                        // produce any outgoing requests. So produce a "did not
                        // reply" response on its behalf.
                        EnqueueRequestsResult::NoMessages => {
                            let error_msg = format!("Canister {} did not reply", request.receiver);
                            let payload = Payload::Reject(RejectContext::new(
                                RejectCode::CanisterReject,
                                error_msg,
                            ));
                            self.outstanding_response = Some(generate_response(request, payload));
                            None
                        }
                        // Canister did not produce a response but did produce
                        // outgoing request(s). Save the canister for when the
                        // response(s) come back in.
                        EnqueueRequestsResult::MessagesEnqueued => {
                            self.canisters.insert(canister.canister_id(), canister);
                            None
                        }
                    },
                }
            }
        }
    }
fn handle_request ( & mut self , request : Request , measurement_scope : & MeasurementScope , ) -> Option < UserError > { // we are always prioritising responses over requests so when we execute // a request, there should not be any outstanding responses. if self . outstanding_response . is_some ( ) { fatal ! ( self log " " ) ; } let canister_id = request . receiver ; // As we do not support loops in the call graph, the canister that we // want to execute a request on should not already be loaded. if self . canisters . contains_key ( & canister_id ) { error ! ( self log " " ) ; } let canister = match self . get_canister_from_state ( & request . receiver ) { Ok ( canister ) => canister , Err ( err ) => { let payload = Payload :: Reject ( RejectContext :: from ( err ) ) ; self . outstanding_response = Some ( generate_response ( request , payload ) ) ; return None ; } } ; let call_origin = CallOrigin :: CanisterQuery ( request . sender , request . sender_reply_callback ) ; let ( mut canister , result ) = self . execute_query ( canister , call_origin , request . method_name . as_str ( ) , request . method_payload . as_slice ( ) , request . sender . get ( ) , NonReplicatedQueryKind :: Stateful , measurement_scope , ) ; match result { // Execution of the message failed. We do not need to bother with // any outstanding requests and we can return a response. Err ( err ) => { let err = err . into_user_error ( & request . receiver ) ; let payload = Payload :: Reject ( RejectContext :: from ( err ) ) ; let response = generate_response ( request , payload ) ; self . outstanding_response = Some ( response ) ; None } Ok ( opt_result ) => { match opt_result { // The canister produced a response. We do not need to // handle any outgoing requests as we have the response we // needed and we can return it. Some ( wasm_result ) => { let payload = match wasm_result { WasmResult :: Reply ( data ) => Payload :: Data ( data ) , WasmResult :: Reject ( string ) => Payload :: Reject ( RejectContext :: new ( RejectCode :: CanisterReject , string , ) ) , } ; self . outstanding_response = Some ( generate_response ( request , payload ) ) ; None } None => match self . enqueue_requests ( & mut canister ) { EnqueueRequestsResult :: LoopDetected => Some ( UserError :: new ( ErrorCode :: InterCanisterQueryLoopDetected , LOOP_DETECTED_ERROR_MSG . to_string ( ) , ) ) , // The canister did not produce a response and did not // produce any outgoing requests. So produce a "did not // reply" response on its behalf. EnqueueRequestsResult :: NoMessages => { let error_msg = format ! ( " " request receiver ) ; let payload = Payload :: Reject ( RejectContext :: new ( RejectCode :: CanisterReject , error_msg , ) ) ; self . outstanding_response = Some ( generate_response ( request , payload ) ) ; None } // Canister did not produce a response but did produce // outgoing request(s). Save the canister for when the // response(s) come back in. EnqueueRequestsResult :: MessagesEnqueued => { self . canisters . insert ( canister . canister_id ( ) , canister ) ; None } } , } } } }
Executes a query sent from one canister to another.
Executes a query sent from one canister to another .
&mut self
request
Request
measurement_scope
&MeasurementScope
&mut self
request
Request
measurement_scope
&MeasurementScope