merger notification process order testing
This commit is contained in:
@ -1213,21 +1213,6 @@
|
||||
" '00000000-0000-0000-0000-000000000000'",
|
||||
")"
|
||||
],
|
||||
[
|
||||
"SELECT pg_notify('entity', '{",
|
||||
" \"complete\":{",
|
||||
" \"created_at\":\"{{timestamp}}\",",
|
||||
" \"created_by\":\"00000000-0000-0000-0000-000000000000\",",
|
||||
" \"date_of_birth\":\"2000-01-01\",",
|
||||
" \"first_name\":\"Bob\",",
|
||||
" \"id\":\"{{uuid:customer_id}}\",",
|
||||
" \"last_name\":\"Smith\",",
|
||||
" \"modified_at\":\"{{timestamp}}\",",
|
||||
" \"modified_by\":\"00000000-0000-0000-0000-000000000000\",",
|
||||
" \"type\":\"person\"",
|
||||
" }",
|
||||
"}')"
|
||||
],
|
||||
[
|
||||
"INSERT INTO agreego.\"entity\" (",
|
||||
" \"created_at\",",
|
||||
@ -1295,6 +1280,21 @@
|
||||
" \"type\":\"order\"",
|
||||
" }",
|
||||
"}')"
|
||||
],
|
||||
[
|
||||
"SELECT pg_notify('entity', '{",
|
||||
" \"complete\":{",
|
||||
" \"created_at\":\"{{timestamp}}\",",
|
||||
" \"created_by\":\"00000000-0000-0000-0000-000000000000\",",
|
||||
" \"date_of_birth\":\"2000-01-01\",",
|
||||
" \"first_name\":\"Bob\",",
|
||||
" \"id\":\"{{uuid:customer_id}}\",",
|
||||
" \"last_name\":\"Smith\",",
|
||||
" \"modified_at\":\"{{timestamp}}\",",
|
||||
" \"modified_by\":\"00000000-0000-0000-0000-000000000000\",",
|
||||
" \"type\":\"person\"",
|
||||
" }",
|
||||
"}')"
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
@ -21,9 +21,40 @@ impl Merger {
|
||||
}
|
||||
|
||||
pub fn merge(&self, data: Value) -> crate::drop::Drop {
|
||||
match self.merge_internal(data) {
|
||||
let mut val_resolved = Value::Null;
|
||||
let mut notifications_queue = Vec::new();
|
||||
|
||||
let result = self.merge_internal(data, &mut notifications_queue);
|
||||
|
||||
match result {
|
||||
Ok(val) => {
|
||||
let stripped_val = match val {
|
||||
val_resolved = val;
|
||||
}
|
||||
Err(msg) => {
|
||||
return crate::drop::Drop::with_errors(vec![crate::drop::Error {
|
||||
code: "MERGE_FAILED".to_string(),
|
||||
message: msg,
|
||||
details: crate::drop::ErrorDetails {
|
||||
path: "".to_string(),
|
||||
},
|
||||
}]);
|
||||
}
|
||||
};
|
||||
|
||||
// Execute the globally collected, pre-ordered notifications last!
|
||||
for notify_sql in notifications_queue {
|
||||
if let Err(e) = self.db.execute(¬ify_sql, None) {
|
||||
return crate::drop::Drop::with_errors(vec![crate::drop::Error {
|
||||
code: "MERGE_FAILED".to_string(),
|
||||
message: format!("Executor Error in pre-ordered notify: {:?}", e),
|
||||
details: crate::drop::ErrorDetails {
|
||||
path: "".to_string(),
|
||||
},
|
||||
}]);
|
||||
}
|
||||
}
|
||||
|
||||
let stripped_val = match val_resolved {
|
||||
Value::Object(mut map) => {
|
||||
let mut out = serde_json::Map::new();
|
||||
if let Some(id) = map.remove("id") {
|
||||
@ -50,34 +81,27 @@ impl Merger {
|
||||
};
|
||||
crate::drop::Drop::success_with_val(stripped_val)
|
||||
}
|
||||
Err(msg) => crate::drop::Drop::with_errors(vec![crate::drop::Error {
|
||||
code: "MERGE_FAILED".to_string(),
|
||||
message: msg,
|
||||
details: crate::drop::ErrorDetails {
|
||||
path: "".to_string(),
|
||||
},
|
||||
}]),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn merge_internal(&self, data: Value) -> Result<Value, String> {
|
||||
pub(crate) fn merge_internal(&self, data: Value, notifications: &mut Vec<String>) -> Result<Value, String> {
|
||||
match data {
|
||||
Value::Array(items) => self.merge_array(items),
|
||||
Value::Object(map) => self.merge_object(map),
|
||||
Value::Array(items) => self.merge_array(items, notifications),
|
||||
Value::Object(map) => self.merge_object(map, notifications),
|
||||
_ => Err("Invalid merge payload: root must be an Object or Array".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
fn merge_array(&self, items: Vec<Value>) -> Result<Value, String> {
|
||||
fn merge_array(&self, items: Vec<Value>, notifications: &mut Vec<String>) -> Result<Value, String> {
|
||||
let mut resolved_items = Vec::new();
|
||||
for item in items {
|
||||
let resolved = self.merge_internal(item)?;
|
||||
let resolved = self.merge_internal(item, notifications)?;
|
||||
resolved_items.push(resolved);
|
||||
}
|
||||
Ok(Value::Array(resolved_items))
|
||||
}
|
||||
|
||||
fn merge_object(&self, obj: serde_json::Map<String, Value>) -> Result<Value, String> {
|
||||
fn merge_object(&self, obj: serde_json::Map<String, Value>, notifications: &mut Vec<String>) -> Result<Value, String> {
|
||||
let queue_start = notifications.len();
|
||||
|
||||
let type_name = match obj.get("type").and_then(|v| v.as_str()) {
|
||||
Some(t) => t.to_string(),
|
||||
None => return Err("Missing required 'type' field on object".to_string()),
|
||||
@ -147,7 +171,7 @@ impl Merger {
|
||||
}
|
||||
}
|
||||
|
||||
let merged_relative = match self.merge_internal(Value::Object(relative))? {
|
||||
let merged_relative = match self.merge_internal(Value::Object(relative), notifications)? {
|
||||
Value::Object(m) => m,
|
||||
_ => continue,
|
||||
};
|
||||
@ -174,7 +198,7 @@ impl Merger {
|
||||
&entity_fields,
|
||||
);
|
||||
|
||||
let merged_relative = match self.merge_internal(Value::Object(relative))? {
|
||||
let merged_relative = match self.merge_internal(Value::Object(relative), notifications)? {
|
||||
Value::Object(m) => m,
|
||||
_ => continue,
|
||||
};
|
||||
@ -242,7 +266,7 @@ impl Merger {
|
||||
&entity_fields,
|
||||
);
|
||||
|
||||
let merged_relative = match self.merge_internal(Value::Object(relative_item))? {
|
||||
let merged_relative = match self.merge_internal(Value::Object(relative_item), notifications)? {
|
||||
Value::Object(m) => m,
|
||||
_ => continue,
|
||||
};
|
||||
@ -255,7 +279,7 @@ impl Merger {
|
||||
}
|
||||
|
||||
// 7. Perform change tracking
|
||||
self.merge_entity_change(
|
||||
let notify_sql = self.merge_entity_change(
|
||||
&entity_fields,
|
||||
entity_fetched.as_ref(),
|
||||
entity_change_kind.as_deref(),
|
||||
@ -263,6 +287,10 @@ impl Merger {
|
||||
×tamp,
|
||||
)?;
|
||||
|
||||
if let Some(sql) = notify_sql {
|
||||
notifications.insert(queue_start, sql);
|
||||
}
|
||||
|
||||
// Produce the full tree response
|
||||
let mut final_response = serde_json::Map::new();
|
||||
if let Some(fetched) = entity_fetched {
|
||||
@ -614,10 +642,10 @@ impl Merger {
|
||||
entity_change_kind: Option<&str>,
|
||||
user_id: &str,
|
||||
timestamp: &str,
|
||||
) -> Result<(), String> {
|
||||
) -> Result<Option<String>, String> {
|
||||
let change_kind = match entity_change_kind {
|
||||
Some(k) => k,
|
||||
None => return Ok(()),
|
||||
None => return Ok(None),
|
||||
};
|
||||
|
||||
let id_str = entity_fields.get("id").unwrap();
|
||||
@ -697,12 +725,8 @@ impl Merger {
|
||||
.db
|
||||
.execute(&change_sql, None)
|
||||
.map_err(|e| format!("Executor Error in change: {:?}", e))?;
|
||||
self
|
||||
.db
|
||||
.execute(¬ify_sql, None)
|
||||
.map_err(|e| format!("Executor Error in notify: {:?}", e))?;
|
||||
|
||||
Ok(())
|
||||
Ok(Some(notify_sql))
|
||||
}
|
||||
|
||||
fn compare_entities(
|
||||
|
||||
Reference in New Issue
Block a user