use crate::comm::{ExecuteContext, ExecuteResult};
use crate::interceptor::blocking::AkitaInterceptor;
use crate::interceptor::shared::{
check_depth_limit, should_skip_interceptor, sort_interceptors_by_order, InterceptorBase,
};
use crate::interceptor::*;
use crate::prelude::AkitaError;
use crate::prelude::Result;
use akita_core::InterceptorType;
use std::collections::HashSet;
use std::sync::Arc;
#[derive(Clone)]
pub struct InterceptorChain {
interceptors: Vec<Arc<dyn AkitaInterceptor>>,
enabled_types: HashSet<InterceptorType>,
config: InterceptorConfig,
}
impl Default for InterceptorChain {
fn default() -> Self {
Self::new()
}
}
impl InterceptorChain {
pub fn new() -> Self {
Self {
interceptors: Vec::new(),
enabled_types: HashSet::new(),
config: InterceptorConfig::default(),
}
}
pub fn deep_clone(&self) -> Self {
Self {
interceptors: self.interceptors.clone(),
enabled_types: self.enabled_types.clone(),
config: self.config.clone(),
}
}
pub fn with_config(config: InterceptorConfig) -> Self {
Self {
interceptors: Vec::new(),
enabled_types: HashSet::new(),
config,
}
}
pub fn add_interceptor(&mut self, interceptor: Arc<dyn AkitaInterceptor>) -> &mut Self {
let interceptor_type = interceptor.interceptor_type();
self.interceptors.push(interceptor);
self.enabled_types.insert(interceptor_type);
let mut base_refs: Vec<Arc<dyn InterceptorBase>> = self
.interceptors
.iter()
.map(|i| i.clone() as Arc<dyn InterceptorBase>)
.collect();
sort_interceptors_by_order(&mut base_refs);
self
}
pub fn before_query(&self, ctx: &mut ExecuteContext) -> Result<()> {
let mut depth = 0;
for interceptor in &self.interceptors {
if ctx.stop_propagation {
break;
}
check_depth_limit(&mut depth, &self.config)?;
if should_skip_interceptor(interceptor.as_ref() as &dyn InterceptorBase, ctx) {
continue;
}
interceptor.before_execute(ctx)?;
ctx.executed_interceptors_mut()
.push(interceptor.interceptor_type());
}
Ok(())
}
pub fn after_query(
&self,
ctx: &mut ExecuteContext,
result: &mut std::result::Result<ExecuteResult, AkitaError>,
) -> Result<()> {
for interceptor in self.interceptors.iter().rev() {
if should_skip_interceptor(interceptor.as_ref() as &dyn InterceptorBase, ctx) {
continue;
}
interceptor.after_execute(ctx, result)?;
}
Ok(())
}
pub fn on_error(&self, ctx: &ExecuteContext, error: &mut AkitaError) -> Result<()> {
for interceptor in self.interceptors.iter().rev() {
if should_skip_interceptor(interceptor.as_ref() as &dyn InterceptorBase, ctx) {
continue;
}
interceptor.on_error(ctx, error)?;
}
Ok(())
}
pub fn is_interceptor_enabled(&self, interceptor_type: &InterceptorType) -> bool {
self.enabled_types.contains(interceptor_type)
}
pub fn len(&self) -> usize {
self.interceptors.len()
}
pub fn is_empty(&self) -> bool {
self.interceptors.is_empty()
}
}