shared-framework 0.0.17

Reusable building blocks for HTTP services — Hyper routing, SeaORM data layer, validation, OpenAPI docs, jobs, queues, cache.
Documentation
//! Shared result and helper types for data operations.
//!
//! Provides the [`PaginatedResult`] page alias, the [`ChangeResultModel`]
//! update summary, the [`EntityProjection`] column selector, the [`Position`]
//! ordering helper, and the [`StatelessChangeEffector`]/[`QueueConsumerHandler`]
//! handler traits.
use serde::{Deserialize, Serialize};

/// Page of rows; alias for [`crate::data::query::PageResult`].
///
/// `T` is the row model type.
pub type PaginatedResult<T> = crate::data::query::PageResult<T>;

/// Summary of an update run: how many rows changed and which ones.
///
/// `T` is the affected model type.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChangeResultModel<T> {
    /// Number of persisted rows.
    pub affected_count: usize,
    /// Pre-save models that were persisted.
    pub affected_entities: Vec<T>,
}

impl<T> ChangeResultModel<T> {
    /// Creates a summary from the persisted entities, counting them.
    pub fn new(entities: Vec<T>) -> Self {
        Self {
            affected_count: entities.len(),
            affected_entities: entities,
        }
    }

    /// Creates an empty summary with zero affected rows.
    pub fn empty() -> Self {
        Self {
            affected_count: 0,
            affected_entities: Vec::new(),
        }
    }
}

/// Column selector holding the field names to fetch.
///
/// An empty list means no columns; [`EntityProjection::all`] selects all columns.
#[derive(Debug, Clone)]
pub struct EntityProjection {
    /// Field names to select (`["*"]` means all columns).
    pub fields: Vec<String>,
}

impl EntityProjection {
    /// Creates a projection for the given field names.
    pub fn new(fields: Vec<String>) -> Self { Self { fields } }
    /// Creates a projection selecting all columns (`["*"]`).
    pub fn all() -> Self { Self { fields: vec!["*".to_string()] } }
}

/// Sort direction for ordering helpers.
#[derive(Debug, Clone, Copy)]
pub enum Position {
    /// Ascending order.
    Asc,
    /// Descending order.
    Desc,
}

/// Synchronous mutation applied to an entity.
///
/// `E` is the entity type. Returns true when the entity should be persisted.
pub trait StatelessChangeEffector<E>: Send + Sync {
    /// Mutates `entity`; returns true when the change should be saved.
    fn apply(&self, entity: &mut E) -> bool;
}

/// Async consumer of queued payloads.
///
/// `T` is the incoming payload type; `R` is the result type.
/// `redelivered` reports whether the payload is being delivered again.
#[async_trait::async_trait]
pub trait QueueConsumerHandler<T, R>: Send + Sync {
    /// Handles one payload and returns the processing result or an error.
    async fn handle(&self, data: T, redelivered: bool) -> anyhow::Result<R>;
}