use vantage_core::Result;
use vantage_types::Record;
use ciborium::Value as CborValue;
use crate::dio::{Dio, DioEvent, DioInner};
use crate::ops::WriteOp;
impl Dio {
pub async fn write_optimistic(&self, op: WriteOp) -> Result<()> {
let Some(id) = op.id().map(str::to_string) else {
return crate::dio::worker::run_write_through(self, op).await;
};
let pre = self.inner.cache.get_value(&id).await?;
apply_to_cache(&self.inner, &op, pre.as_ref()).await?;
let _ = self
.inner
.event_bus
.send(DioEvent::WritePending { id: id.clone() });
match crate::dio::worker::run_write_through(self, op).await {
Ok(()) => {
let _ = self.inner.event_bus.send(DioEvent::RecordChanged { id });
Ok(())
}
Err(err) => {
match &pre {
Some(prev) => self.inner.cache.insert_value(&id, prev).await?,
None => self.inner.cache.delete_value(&id).await?,
}
let _ = self.inner.event_bus.send(DioEvent::WriteReverted {
id,
error: err.to_string(),
});
Err(err)
}
}
}
pub async fn patch_optimistic(
&self,
id: impl Into<String>,
partial: Record<CborValue>,
) -> Result<()> {
self.write_optimistic(WriteOp::Patch {
id: id.into(),
partial,
})
.await
}
}
async fn apply_to_cache(
inner: &DioInner,
op: &WriteOp,
pre: Option<&Record<CborValue>>,
) -> Result<()> {
match op {
WriteOp::Insert { id, record } | WriteOp::Replace { id, record } => {
inner.cache.insert_value(id, record).await
}
WriteOp::Patch { id, partial } => {
let mut merged = pre.cloned().unwrap_or_default();
for (k, v) in partial {
merged.insert(k.clone(), v.clone());
}
inner.cache.insert_value(id, &merged).await
}
WriteOp::Delete { id } => inner.cache.delete_value(id).await,
WriteOp::DeleteAll => Ok(()),
}
}