use sea_orm::{
ActiveModelTrait as _, ActiveValue::Set, ColumnTrait, DatabaseTransaction, EntityTrait,
ModelTrait, QueryFilter,
};
use crate::{SignerMeta, crdt::errors::CrdtError, delta::chat_do::ChatDO, entity::chat};
use super::{CrdtType, crdt::CrdtDelta};
impl CrdtType for ChatDO {
type PrimaryKey = (String, String);
async fn put(
&self,
core: &SignerMeta,
tx: &DatabaseTransaction,
) -> Result<CrdtDelta<Self>, CrdtError> {
let r = chat::Entity::find()
.filter(
chat::Column::ChatKey
.eq(&self.chat_key)
.and(chat::Column::ChatVariant.eq(&self.chat_variant)),
)
.one(tx)
.await?;
if let Some(val) = &r {
let vo = serde_json::from_str(&val.view_object)?;
if !self.has_changed(&vo) {
return Ok(CrdtDelta::Skip);
}
}
let m = chat::ActiveModel {
chat_key: Set(self.chat_key.clone()),
chat_variant: Set(self.chat_variant.clone()),
view_object: Set(serde_json::to_string(&self.view_object.unwrap_ref())?),
};
match r {
Some(val) => {
let e = m.update(tx).await?;
let from = serde_json::from_str(&e.view_object)?;
let to = serde_json::from_str(&val.view_object)?;
let chat_do = ChatDO::new(core, &from, &to).await?;
Ok(CrdtDelta::Put(chat_do))
}
None => {
let e = m.insert(tx).await?;
Ok(CrdtDelta::Del((e.chat_variant, e.chat_key)))
}
}
}
async fn del(
_core: &SignerMeta,
key: &Self::PrimaryKey,
tx: &DatabaseTransaction,
) -> Result<CrdtDelta<Self>, CrdtError> {
let r = chat::Entity::find()
.filter(
chat::Column::ChatKey
.eq(&key.1)
.and(chat::Column::ChatVariant.eq(&key.0)),
)
.one(tx)
.await?;
match r {
Some(val) => {
let vo = serde_json::from_str(&val.view_object)?;
let chat_do = ChatDO::from(vo);
val.delete(tx).await?;
Ok(CrdtDelta::Put(chat_do))
}
None => Ok(CrdtDelta::Skip),
}
}
}