use crate::db::connection::{Collection, PersistenceError, TransactionOperation};
use serde_json::Value;
pub struct GroupedOperations {
pub entity_creates: Vec<Value>,
pub entity_updates: Vec<Value>, pub entity_deletes: Vec<Value>, pub resource_creates: Vec<Value>,
pub resource_updates: Vec<Value>,
pub resource_deletes: Vec<Value>,
}
impl GroupedOperations {
pub fn from_operations(operations: Vec<TransactionOperation>, key_field: &str) -> Self {
let mut result = Self {
entity_creates: Vec::new(),
entity_updates: Vec::new(),
entity_deletes: Vec::new(),
resource_creates: Vec::new(),
resource_updates: Vec::new(),
resource_deletes: Vec::new(),
};
for op in operations {
match op {
TransactionOperation::CreateDocument { collection, data } => {
match collection {
Collection::Entities => result.entity_creates.push(data),
Collection::Resources => result.resource_creates.push(data),
}
}
TransactionOperation::UpdateDocument {
collection,
key,
expected_current_version,
patch,
} => {
let obj = serde_json::json!({
key_field: key,
"expected": expected_current_version,
"patch": patch
});
match collection {
Collection::Entities => result.entity_updates.push(obj),
Collection::Resources => result.resource_updates.push(obj),
}
}
TransactionOperation::DeleteDocument {
collection,
key,
expected_current_version,
} => {
let obj = serde_json::json!({
key_field: key,
"expected": expected_current_version,
});
match collection {
Collection::Entities => result.entity_deletes.push(obj),
Collection::Resources => result.resource_deletes.push(obj),
}
}
}
}
result
}
pub fn extract_keys(&self, values: &[Value], key_field: &str) -> Vec<String> {
values
.iter()
.filter_map(|v| v.get(key_field).and_then(|k| k.as_str()).map(|s| s.to_string()))
.collect()
}
}
pub enum OperationType {
Update,
Delete,
}
impl OperationType {
pub fn as_str(&self) -> &'static str {
match self {
OperationType::Update => "Update",
OperationType::Delete => "Delete",
}
}
}
pub fn check_operation_success(
requested: Vec<String>,
processed: Vec<String>,
operation_type: &OperationType,
collection: &str,
) -> Result<(), PersistenceError> {
if processed.len() != requested.len() {
if let Some(conflict_key) = requested
.into_iter()
.find(|k| !processed.iter().any(|p| p == k))
{
return Err(PersistenceError::Conflict { key: conflict_key });
} else {
return Err(PersistenceError::new(format!(
"{} conflict ({})",
operation_type.as_str(), collection
)));
}
}
Ok(())
}