actrpc-orchestrator 0.1.0

Configuration and orchestration utilities for ActRPC.
Documentation
use crate::{
    action::{ActionHandlerFuture, TypedActionHandler},
    error::ActionExecutionError,
    runtime::InFlightMessageState,
};
use actrpc_core::{
    DescribeParams,
    action::{ActionSpec, NoOk, RequestedAction, ResolvedAction},
    interception::InterceptionRequest,
    json_rpc::{JsonRpcError, JsonRpcMessage, JsonRpcResponse, JsonRpcSingleMessage},
};
use serde::{Deserialize, Serialize};
use std::sync::Arc;

#[derive(Debug, Clone, Serialize, Deserialize, DescribeParams)]
pub struct ModifyErrorParams {
    pub error: JsonRpcError,
}

pub struct ModifyError;

impl ActionSpec for ModifyError {
    type Params = ModifyErrorParams;
    type Result = NoOk;

    const KIND: &'static str = "modify_error";
}

pub struct ModifyErrorHandler {
    in_flight_message: Arc<InFlightMessageState>,
}

impl ModifyErrorHandler {
    pub fn new(in_flight_message: Arc<InFlightMessageState>) -> Self {
        Self { in_flight_message }
    }
}

impl TypedActionHandler<ModifyError> for ModifyErrorHandler {
    fn handle_typed<'a>(
        &'a self,
        _request: &'a InterceptionRequest,
        action: RequestedAction<ModifyError>,
    ) -> ActionHandlerFuture<'a, Result<ResolvedAction<ModifyError>, ActionExecutionError>>
    where
        Self: 'a,
    {
        Box::pin(async move {
            let current = self.in_flight_message.snapshot().ok_or_else(|| {
                ActionExecutionError::InvalidState {
                    message: "no in-flight message is currently set".to_owned(),
                }
            })?;

            let updated = match current {
                JsonRpcMessage::Single(JsonRpcSingleMessage::Response(JsonRpcResponse::Error(
                    mut error_response,
                ))) => {
                    error_response.error = action.params.error.clone();
                    JsonRpcMessage::Single(JsonRpcSingleMessage::Response(JsonRpcResponse::Error(
                        error_response,
                    )))
                }
                _ => {
                    return Err(ActionExecutionError::InvalidParams {
                        action: ModifyError::action_kind(),
                    });
                }
            };

            if !self.in_flight_message.replace_message(updated) {
                return Err(ActionExecutionError::InvalidState {
                    message: "no in-flight message is currently set".to_owned(),
                });
            }

            Ok(ResolvedAction {
                params: action.params,
                result: Ok(NoOk),
            })
        })
    }
}