use crate::error::{LrefError, LrefResult};
use crate::tracking::{ChangeTracker, EntityEntry};
use std::sync::Arc;
#[derive(Debug, Clone)]
pub struct SaveChangesContext {
entries: Vec<EntityEntry>,
added_count: usize,
modified_count: usize,
deleted_count: usize,
}
impl SaveChangesContext {
pub fn from_tracker(tracker: &ChangeTracker) -> Self {
let entries = tracker.entries();
let added_count = tracker.count_by_state(crate::entity::EntityState::Added);
let modified_count = tracker.count_by_state(crate::entity::EntityState::Modified);
let deleted_count = tracker.count_by_state(crate::entity::EntityState::Deleted);
Self {
entries,
added_count,
modified_count,
deleted_count,
}
}
pub fn entries(&self) -> &[EntityEntry] {
&self.entries
}
pub fn added_count(&self) -> usize {
self.added_count
}
pub fn modified_count(&self) -> usize {
self.modified_count
}
pub fn deleted_count(&self) -> usize {
self.deleted_count
}
pub fn total_count(&self) -> usize {
self.entries.len()
}
}
#[derive(Debug, Clone)]
pub struct SaveChangesResultContext {
pub added: usize,
pub updated: usize,
pub deleted: usize,
}
impl SaveChangesResultContext {
pub fn total(&self) -> usize {
self.added + self.updated + self.deleted
}
}
#[async_trait::async_trait]
pub trait ISaveChangesInterceptor: Send + Sync {
async fn on_saving(&self, _ctx: &SaveChangesContext) -> LrefResult<()> {
Ok(())
}
async fn on_saved(
&self,
_ctx: &SaveChangesContext,
_result: &SaveChangesResultContext,
) -> LrefResult<()> {
Ok(())
}
async fn on_save_failed(&self, _ctx: &SaveChangesContext, _error: &LrefError) {
}
}
pub(crate) struct InterceptorPipeline {
interceptors: Vec<Arc<dyn ISaveChangesInterceptor>>,
}
impl InterceptorPipeline {
pub fn new(interceptors: Vec<Arc<dyn ISaveChangesInterceptor>>) -> Self {
Self { interceptors }
}
pub async fn on_saving(&self, ctx: &SaveChangesContext) -> LrefResult<()> {
for interceptor in &self.interceptors {
interceptor.on_saving(ctx).await?;
}
Ok(())
}
pub async fn on_saved(
&self,
ctx: &SaveChangesContext,
result: &SaveChangesResultContext,
) -> LrefResult<()> {
for interceptor in &self.interceptors {
interceptor.on_saved(ctx, result).await?;
}
Ok(())
}
pub async fn on_save_failed(&self, ctx: &SaveChangesContext, error: &LrefError) {
for interceptor in &self.interceptors {
interceptor.on_save_failed(ctx, error).await;
}
}
}