actrpc-orchestrator 0.1.0

Configuration and orchestration utilities for ActRPC.
Documentation
use crate::{
    action::{ActionHandlerFuture, TypedActionHandler},
    error::ActionExecutionError,
    interceptor::WorkingInterceptorPipeline,
};
use actrpc_core::{
    DescribeParams,
    action::{ActionSpec, NoOk, RequestedAction, ResolvedAction},
    interception::InterceptionRequest,
};
use serde::{Deserialize, Serialize};
use std::{collections::HashSet, sync::Arc};

#[derive(Debug, Clone, Serialize, Deserialize, DescribeParams)]
pub struct ExcludeInterceptorsParams {
    pub names: Vec<String>,
}

pub struct ExcludeInterceptors;

impl ActionSpec for ExcludeInterceptors {
    type Params = ExcludeInterceptorsParams;
    type Result = NoOk;

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

pub struct ExcludeInterceptorsHandler {
    pipeline: Arc<WorkingInterceptorPipeline>,
}

impl ExcludeInterceptorsHandler {
    pub fn new(pipeline: Arc<WorkingInterceptorPipeline>) -> Self {
        Self { pipeline }
    }
}

impl TypedActionHandler<ExcludeInterceptors> for ExcludeInterceptorsHandler {
    fn handle_typed<'a>(
        &'a self,
        _request: &'a InterceptionRequest,
        action: RequestedAction<ExcludeInterceptors>,
    ) -> ActionHandlerFuture<'a, Result<ResolvedAction<ExcludeInterceptors>, ActionExecutionError>>
    where
        Self: 'a,
    {
        Box::pin(async move {
            if action.params.names.is_empty() {
                return Err(ActionExecutionError::InvalidParams {
                    action: ExcludeInterceptors::action_kind(),
                });
            }

            let mut seen = HashSet::new();
            let mut names = Vec::new();

            for name in &action.params.names {
                let trimmed = name.trim();

                if trimmed.is_empty() {
                    return Err(ActionExecutionError::InvalidParams {
                        action: ExcludeInterceptors::action_kind(),
                    });
                }

                if seen.insert(trimmed.to_owned()) {
                    names.push(trimmed.to_owned());
                }
            }

            self.pipeline.exclude_named(&names);

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