use super::{
MongodbConfigStore,
serde::{now_as_datetime, try_to_object_id, try_to_uuid},
};
use crate::storage::Error;
use mongodb::{ClientSession, Collection, bson::Document, results::UpdateResult};
use pbbson::bson::{Bson, doc};
use std::fmt::Debug;
use std::str::FromStr;
pub async fn delete<B: Clone + Debug + FromStr + Send + Sync + ToString>(
this: &MongodbConfigStore<B>,
mut session: Option<&mut ClientSession>,
bucket: B,
id: &str,
by_account_id: Option<String>,
) -> Result<(), Error> {
let id: Bson = match try_to_object_id(id) {
Ok(id) => id.into(),
Err(_e) => try_to_uuid(id)?.into(),
};
let coll: Collection<Document> = this.db.collection(&bucket.to_string());
let filter = doc! { "_id": &id };
let now = now_as_datetime();
let mut set = doc! {"deletedAt": now};
if let Some(ref account_id) = by_account_id
&& let Ok(deleted_by_account_id) = try_to_object_id(account_id)
{
set.insert("deletedByAccountId", deleted_by_account_id);
}
let existing = this.find_in_session(&mut session, bucket.clone(), &id.clone()).await?;
let update = doc! {"$set": set};
let res: UpdateResult = {
let op = coll.update_one(filter, update);
if let Some(ref mut session) = session {
op.session(&mut **session).await?
} else {
op.await?
}
};
if res.matched_count == 0 {
return Err(Error::not_found("No such record"));
}
for belongs_to in this
.belongs_tos_by_bucket
.get(&bucket.to_string())
.cloned()
.unwrap_or_default()
{
match belongs_to.inverse {
None => continue,
Some(inverse) => {
let local_value = existing.get(&belongs_to.local);
match local_value {
Some(Bson::ObjectId(id_)) => {
let pull = doc! {&inverse: id.clone()};
let mut set = doc! {"updatedAt": now};
if let Some(ref account_id) = by_account_id {
let updated_by_account_id = try_to_object_id(account_id)?;
set.insert("updatedByAccountId", updated_by_account_id);
}
let update = doc! {"$pull": pull, "$set": set};
let remote_coll: Collection<Document> = this.db.collection(&belongs_to.remote.to_string());
let filter = doc! { "_id": id_ };
let res: UpdateResult = {
let op = remote_coll.update_one(filter, update);
if let Some(ref mut session) = session {
op.session(&mut **session).await?
} else {
op.await?
}
};
if res.matched_count == 0 {
}
}
_ => {
log::error!("Unknown fk type: {local_value:?}");
}
}
}
}
}
for has_many in this
.has_manys_by_bucket
.get(&bucket.to_string())
.cloned()
.unwrap_or_default()
{
let local_value = existing.get(&has_many.local);
match local_value {
Some(Bson::Array(array)) => {
match has_many.inverse {
None => {
}
Some(inverse) => {
let remote_coll: Collection<Document> = this.db.collection(&has_many.remote.to_string());
for id in array.iter() {
if let Bson::String(id_) = id {
let mut set = doc! {&inverse: Bson::Null, "updatedAt": now};
if let Some(ref account_id) = by_account_id {
let updated_by_account_id = try_to_object_id(account_id)?;
set.insert("updatedByAccountId", updated_by_account_id);
}
let update = doc! {"$set": set};
let filter = doc! { "_id": try_to_object_id(id_)? };
let res: UpdateResult = {
let op = remote_coll.update_one(filter, update);
if let Some(ref mut session) = session {
op.session(&mut **session).await?
} else {
op.await?
}
};
if res.matched_count == 0 {
}
}
}
}
}
}
_ => {
log::error!("Unknown fk type: {local_value:?}");
}
}
}
Ok(())
}