caretta-sync/lazy-supplements-core/src/data/syncable.rs

79 lines
3.1 KiB
Rust
Raw Normal View History

use sea_orm::{prelude::*, query::*, sea_query::SimpleExpr, *};
#[cfg(feature="macros")]
2025-06-26 08:14:27 +09:00
pub use lazy_supplements_macros::SyncableModel;
2025-06-25 07:31:49 +09:00
pub trait SyncableModel: ModelTrait<Entity = Self::SyncableEntity> {
type SyncableEntity: SyncableEntity<SyncableModel = Self>;
2025-06-26 08:14:27 +09:00
fn get_timestamp(&self) -> DateTimeUtc;
fn get_id(&self) -> Uuid;
fn get_author_id(&self) -> Uuid;
2025-06-25 07:31:49 +09:00
}
pub trait SyncableEntity: EntityTrait<
Model = Self::SyncableModel,
ActiveModel = Self::SyncableActiveModel,
Column = Self::SyncableColumn,
>{
type SyncableModel: SyncableModel<SyncableEntity = Self> + FromQueryResult;
type SyncableActiveModel: SyncableActiveModel<SyncableEntity= Self>;
type SyncableColumn: SyncableColumn;
async fn get_updated(from: DateTimeUtc,until: DateTimeUtc, db: &DatabaseConnection) -> Result<Vec<<Self as EntityTrait>::Model>, SyncableError> {
2025-06-25 07:31:49 +09:00
let result: Vec<Self::SyncableModel> = <Self as EntityTrait>::find()
.filter(Self::SyncableColumn::timestamp_between(from, until))
.all(db)
.await.unwrap();
Ok(result)
}
async fn get_updated_by_author(from: DateTimeUtc, author: Uuid, db: &DatabaseConnection) -> Result<Vec<<Self as EntityTrait>::Model>, SyncableError> {
let result: Vec<Self::SyncableModel> = <Self as EntityTrait>::find()
.filter(Self::SyncableColumn::timestamp_between(from, until))
.filter(Self::SyncableColumn::author_eq(author))
2025-06-25 07:31:49 +09:00
.all(db)
.await.unwrap();
Ok(result)
}
fn apply_updated(models: Vec<<Self as EntityTrait>::Model>, db: &DatabaseConnection) {
todo!()
}
}
pub trait SyncableActiveModel: ActiveModelTrait<Entity = Self::SyncableEntity> {
type SyncableEntity: SyncableEntity<SyncableActiveModel = Self>;
fn get_id(&self) -> Option<Uuid>;
2025-06-26 08:14:27 +09:00
fn get_timestamp(&self) -> Option<DateTimeUtc>;
fn get_author_id(&self) -> Option<DateTimeUtc>;
2025-06-25 07:31:49 +09:00
fn try_merge(&mut self, other: <Self::SyncableEntity as SyncableEntity>::SyncableModel) -> Result<(), SyncableError> {
if self.get_uuid().ok_or(SyncableError::MissingField("uuid"))? != other.get_uuid() {
return Err(SyncableError::MismatchUuid)
}
2025-06-26 08:14:27 +09:00
if self.get_timestamp().ok_or(SyncableError::MissingField("updated_at"))? < other.get_timestamp() {
2025-06-25 07:31:49 +09:00
for column in <<<Self as ActiveModelTrait>::Entity as EntityTrait>::Column as Iterable>::iter() {
if column.should_sync(){
self.take(column).set_if_not_equals(other.get(column));
}
2025-06-25 07:31:49 +09:00
}
}
Ok(())
}
}
pub trait SyncableColumn: ColumnTrait {
fn is_id(&self) -> bool;
2025-06-26 08:14:27 +09:00
fn is_timestamp(&self) -> bool;
fn should_sync(&self) -> bool;
fn timestamp_between(from: DateTimeUtc, to: DateTimeUtc) -> SimpleExpr;
fn author_eq(author_id: Uuid) -> SimpleExpr;
fn is_author_id(&self) -> bool;
2025-06-25 07:31:49 +09:00
}
#[derive(Debug, thiserror::Error)]
pub enum SyncableError {
#[error("Invalid UUID")]
MismatchUuid,
#[error("mandatory field {0} is missing")]
MissingField(&'static str),
}