mirror of
https://github.com/Start9Labs/patch-db.git
synced 2026-03-26 02:11:54 +00:00
lift result from mutate
This commit is contained in:
@@ -18,7 +18,7 @@ pub use imbl_value::Value;
|
|||||||
pub use model::{HasModel, Model, ModelExt};
|
pub use model::{HasModel, Model, ModelExt};
|
||||||
pub use patch::{DiffPatch, Dump, Revision};
|
pub use patch::{DiffPatch, Dump, Revision};
|
||||||
pub use patch_db_macro::HasModel;
|
pub use patch_db_macro::HasModel;
|
||||||
pub use store::{PatchDb, Store, TypedPatchDb};
|
pub use store::{MutateResult, PatchDb, Store, TypedPatchDb};
|
||||||
use tokio::sync::TryLockError;
|
use tokio::sync::TryLockError;
|
||||||
pub use {imbl_value as value, json_patch, json_ptr};
|
pub use {imbl_value as value, json_patch, json_ptr};
|
||||||
|
|
||||||
|
|||||||
@@ -256,6 +256,55 @@ impl Store {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub struct MutateResult<T, E> {
|
||||||
|
pub result: Result<T, E>,
|
||||||
|
pub revision: Option<Arc<Revision>>,
|
||||||
|
}
|
||||||
|
impl<T, E> MutateResult<T, E> {
|
||||||
|
pub fn map_result<T0, E0, F: FnOnce(Result<T, E>) -> Result<T0, E0>>(
|
||||||
|
self,
|
||||||
|
f: F,
|
||||||
|
) -> MutateResult<T0, E0> {
|
||||||
|
MutateResult {
|
||||||
|
result: f(self.result),
|
||||||
|
revision: self.revision,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn map_ok<T0, F: FnOnce(T) -> T0>(self, f: F) -> MutateResult<T0, E> {
|
||||||
|
MutateResult {
|
||||||
|
result: self.result.map(f),
|
||||||
|
revision: self.revision,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn map_err<E0, F: FnOnce(E) -> E0>(self, f: F) -> MutateResult<T, E0> {
|
||||||
|
MutateResult {
|
||||||
|
result: self.result.map_err(f),
|
||||||
|
revision: self.revision,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn and_then<T0, F: FnOnce(T) -> Result<T0, E>>(self, f: F) -> MutateResult<T0, E> {
|
||||||
|
MutateResult {
|
||||||
|
result: self.result.and_then(f),
|
||||||
|
revision: self.revision,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<T, E> From<Result<(T, Option<Arc<Revision>>), E>> for MutateResult<T, E> {
|
||||||
|
fn from(value: Result<(T, Option<Arc<Revision>>), E>) -> Self {
|
||||||
|
match value {
|
||||||
|
Ok((result, revision)) => Self {
|
||||||
|
result: Ok(result),
|
||||||
|
revision,
|
||||||
|
},
|
||||||
|
Err(e) => Self {
|
||||||
|
result: Err(e),
|
||||||
|
revision: None,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct PatchDb {
|
pub struct PatchDb {
|
||||||
pub(crate) store: Arc<RwLock<Store>>,
|
pub(crate) store: Arc<RwLock<Store>>,
|
||||||
@@ -311,11 +360,12 @@ impl PatchDb {
|
|||||||
let rev = store.apply(patch).await?;
|
let rev = store.apply(patch).await?;
|
||||||
Ok(rev)
|
Ok(rev)
|
||||||
}
|
}
|
||||||
pub async fn apply_function<F, T, E>(&self, f: F) -> Result<(Value, T), E>
|
pub async fn apply_function<F, T, E>(&self, f: F) -> MutateResult<(Value, T), E>
|
||||||
where
|
where
|
||||||
F: FnOnce(Value) -> Result<(Value, T), E> + UnwindSafe,
|
F: FnOnce(Value) -> Result<(Value, T), E> + UnwindSafe,
|
||||||
E: From<Error>,
|
E: From<Error>,
|
||||||
{
|
{
|
||||||
|
async {
|
||||||
let mut store = self.store.write().await;
|
let mut store = self.store.write().await;
|
||||||
let old = store.persistent.clone();
|
let old = store.persistent.clone();
|
||||||
let (new, res) = std::panic::catch_unwind(move || f(old)).map_err(|e| {
|
let (new, res) = std::panic::catch_unwind(move || f(old)).map_err(|e| {
|
||||||
@@ -326,8 +376,11 @@ impl PatchDb {
|
|||||||
)
|
)
|
||||||
})??;
|
})??;
|
||||||
let diff = diff(&store.persistent, &new);
|
let diff = diff(&store.persistent, &new);
|
||||||
store.apply(diff).await?;
|
let rev = store.apply(diff).await?;
|
||||||
Ok((new, res))
|
Ok(((new, res), rev))
|
||||||
|
}
|
||||||
|
.await
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
pub async fn run_idempotent<F, Fut, T, E>(&self, f: F) -> Result<(Value, T), E>
|
pub async fn run_idempotent<F, Fut, T, E>(&self, f: F) -> Result<(Value, T), E>
|
||||||
where
|
where
|
||||||
@@ -392,29 +445,24 @@ impl<T: HasModel, E: From<Error>> TypedPatchDb<T, E> {
|
|||||||
pub async fn mutate<U: UnwindSafe + Send>(
|
pub async fn mutate<U: UnwindSafe + Send>(
|
||||||
&self,
|
&self,
|
||||||
f: impl FnOnce(&mut T::Model) -> Result<U, E> + UnwindSafe + Send,
|
f: impl FnOnce(&mut T::Model) -> Result<U, E> + UnwindSafe + Send,
|
||||||
) -> Result<U, E> {
|
) -> MutateResult<U, E> {
|
||||||
use crate::ModelExt;
|
use crate::ModelExt;
|
||||||
Ok(self
|
self.apply_function(|mut v| {
|
||||||
.apply_function(|mut v| {
|
|
||||||
let model = T::Model::value_as_mut(&mut v);
|
let model = T::Model::value_as_mut(&mut v);
|
||||||
let res = f(model)?;
|
let res = f(model)?;
|
||||||
Ok::<_, E>((v, res))
|
Ok::<_, E>((v, res))
|
||||||
})
|
})
|
||||||
.await?
|
.await
|
||||||
.1)
|
.map_ok(|(_, v)| v)
|
||||||
}
|
}
|
||||||
pub async fn map_mutate(
|
pub async fn map_mutate(
|
||||||
&self,
|
&self,
|
||||||
f: impl FnOnce(T::Model) -> Result<T::Model, E> + UnwindSafe + Send,
|
f: impl FnOnce(T::Model) -> Result<T::Model, E> + UnwindSafe + Send,
|
||||||
) -> Result<T::Model, E> {
|
) -> MutateResult<T::Model, E> {
|
||||||
use crate::ModelExt;
|
use crate::ModelExt;
|
||||||
Ok(T::Model::from_value(
|
self.apply_function(|v| f(T::Model::from_value(v)).map(|a| (T::Model::into_value(a), ())))
|
||||||
self.apply_function(|v| {
|
.await
|
||||||
f(T::Model::from_value(v)).map(|a| (T::Model::into_value(a), ()))
|
.map_ok(|(v, _)| T::Model::from_value(v))
|
||||||
})
|
|
||||||
.await?
|
|
||||||
.0,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -430,7 +478,8 @@ impl<T: HasModel + DeserializeOwned + Serialize, E: From<Error>> TypedPatchDb<T,
|
|||||||
.map_err(Error::from)?,
|
.map_err(Error::from)?,
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
.await?;
|
.await
|
||||||
|
.result?;
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
pub async fn load_or_init<F: FnOnce() -> Fut, Fut: Future<Output = Result<T, E>>>(
|
pub async fn load_or_init<F: FnOnce() -> Fut, Fut: Future<Output = Result<T, E>>>(
|
||||||
|
|||||||
Reference in New Issue
Block a user