use sea_orm::{*, prelude::*, query::*}; pub use lazy_supplements_macros::SyncableModel; pub trait SyncableModel: ModelTrait { type SyncableEntity: SyncableEntity; fn get_timestamp(&self) -> DateTimeUtc; fn get_uuid(&self) -> Uuid; } pub trait SyncableEntity: EntityTrait< Model = Self::SyncableModel, ActiveModel = Self::SyncableActiveModel, Column = Self::SyncableColumn, >{ type SyncableModel: SyncableModel + FromQueryResult; type SyncableActiveModel: SyncableActiveModel; type SyncableColumn: SyncableColumn; async fn get_updated_after(date: DateTimeUtc, db: &DatabaseConnection) -> Result::Model>, SyncableError> { let result: Vec = ::find() .filter(Self::SyncableColumn::updated_at().gte(date)) .all(db) .await.unwrap(); Ok(result) } fn apply_updated(models: Vec<::Model>, db: &DatabaseConnection) { todo!() } } pub trait SyncableActiveModel: ActiveModelTrait { type SyncableEntity: SyncableEntity; fn get_uuid(&self) -> Option; fn get_timestamp(&self) -> Option; fn try_merge(&mut self, other: ::SyncableModel) -> Result<(), SyncableError> { if self.get_uuid().ok_or(SyncableError::MissingField("uuid"))? != other.get_uuid() { return Err(SyncableError::MismatchUuid) } if self.get_timestamp().ok_or(SyncableError::MissingField("updated_at"))? < other.get_timestamp() { for column in <<::Entity as EntityTrait>::Column as Iterable>::iter() { self.take(column).set_if_not_equals(other.get(column)); } } Ok(()) } } pub trait SyncableColumn: ColumnTrait { fn is_uuid(&self) -> bool; fn is_timestamp(&self) -> bool; fn updated_at() -> Self; fn should_skipped(&self); } #[derive(Debug, thiserror::Error)] pub enum SyncableError { #[error("Invalid UUID")] MismatchUuid, #[error("mandatory field {0} is missing")] MissingField(&'static str), }