signer-daemon 0.2.5

Signer daemon package.
Documentation
use sea_orm::{
  ActiveModelTrait as _, ActiveValue::Set, ColumnTrait, DatabaseTransaction,
  EntityTrait, ModelTrait, QueryFilter,
};

use crate::{SignerDaemon, entity::chat, model::deltaobject::chat_do::ChatDO};

use super::{CrdtType, crdt::CrdtDelta};

impl CrdtType for ChatDO {
  // ( chat_key, chat_variant )
  type PrimaryKey = (String, String);

  async fn put(
    &self,
    daemon: &SignerDaemon,
    tx: &DatabaseTransaction,
  ) -> anyhow::Result<CrdtDelta<Self>> {
    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(daemon, &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(
    _daemon: &SignerDaemon,
    key: &Self::PrimaryKey,
    tx: &DatabaseTransaction,
  ) -> anyhow::Result<CrdtDelta<Self>> {
    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),
    }
  }
}