Page MenuHomePhabricator

D8986.id30723.diff
No OneTemporary

D8986.id30723.diff

diff --git a/services/reports/src/email/template/mod.rs b/services/reports/src/email/template/mod.rs
--- a/services/reports/src/email/template/mod.rs
+++ b/services/reports/src/email/template/mod.rs
@@ -1,7 +1,7 @@
-use maud::{html, Markup, Render};
+use maud::{html, Markup, PreEscaped, Render};
use tracing::error;
-use crate::{config::SERVICE_PUBLIC_URL, report_types::*};
+use crate::{config::SERVICE_PUBLIC_URL, report_types::*, report_utils};
mod html_layout;
@@ -65,6 +65,10 @@
li { "Time: " b { (time) } }
li { "Report ID: " b { (report_id) } }
}
+
+ @if report.report_type.is_inconsistency() {
+ (inconsistency_details(report))
+ }
(further_actions(report_id, report.report_type.is_error()))
(display_contents(report, report_id))
}
@@ -107,6 +111,39 @@
.unwrap_or("completed")
}
+fn inconsistency_details(report: &ReportInput) -> Markup {
+ let (subjects, ids) = match report.report_type {
+ ReportType::ThreadInconsistency => (
+ "Thread IDs",
+ report_utils::inconsistent_thread_ids(&report.report_content),
+ ),
+ ReportType::UserInconsistency => (
+ "User IDs",
+ report_utils::inconsistent_user_ids(&report.report_content),
+ ),
+ ReportType::EntryInconsistency => (
+ "Entries",
+ report_utils::inconsistent_entry_ids(&report.report_content),
+ ),
+ _ => return html!(),
+ };
+
+ let formatted_ids = if ids.is_empty() {
+ html! { em { "[None found]" } }.into_string()
+ } else {
+ ids
+ .into_iter()
+ .map(|id| html! { code { (id) } }.into_string())
+ .collect::<Vec<_>>()
+ .join(", ")
+ };
+
+ html! {
+ h3 { "Inconsistency details" }
+ p { (subjects) " that are inconsistent: " (PreEscaped(formatted_ids))}
+ }
+}
+
fn further_actions(
report_id: &ReportID,
display_download_link: bool,
diff --git a/services/reports/src/main.rs b/services/reports/src/main.rs
--- a/services/reports/src/main.rs
+++ b/services/reports/src/main.rs
@@ -4,6 +4,7 @@
pub mod email;
pub mod http;
pub mod report_types;
+pub mod report_utils;
pub mod service;
use anyhow::Result;
diff --git a/services/reports/src/report_utils.rs b/services/reports/src/report_utils.rs
new file mode 100644
--- /dev/null
+++ b/services/reports/src/report_utils.rs
@@ -0,0 +1,79 @@
+use serde_json::Value;
+use std::collections::{HashMap, HashSet};
+
+type ReportContent = HashMap<String, Value>;
+
+/// Returns a set of keys which differ for both objects
+pub fn find_inconsistent_object_keys(
+ first: &serde_json::Map<String, Value>,
+ second: &serde_json::Map<String, Value>,
+) -> HashSet<String> {
+ let mut non_matching_ids = HashSet::new();
+ for (k, v) in first {
+ if !second.get(k).is_some_and(|it| v == it) {
+ non_matching_ids.insert(k.to_string());
+ }
+ }
+ for k in second.keys() {
+ if !first.contains_key(k) {
+ non_matching_ids.insert(k.to_string());
+ }
+ }
+ non_matching_ids
+}
+
+pub fn inconsistent_thread_ids(content: &ReportContent) -> HashSet<String> {
+ let Some(push_result) = content
+ .get("pushResult")
+ .and_then(Value::as_object) else { return HashSet::new(); };
+ let Some(before_action) = content
+ .get("beforeAction")
+ .and_then(Value::as_object) else { return HashSet::new(); };
+
+ find_inconsistent_object_keys(push_result, before_action)
+}
+
+pub fn inconsistent_user_ids(content: &ReportContent) -> HashSet<String> {
+ let Some(before) = content
+ .get("beforeStateCheck")
+ .and_then(Value::as_object) else { return HashSet::new(); };
+ let Some(after) = content
+ .get("afterStateCheck")
+ .and_then(Value::as_object) else { return HashSet::new(); };
+
+ find_inconsistent_object_keys(before, after)
+}
+
+pub fn inconsistent_entry_ids(_content: &ReportContent) -> HashSet<String> {
+ HashSet::from(["--Unimplemented--".to_string()])
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use serde_json::json;
+
+ #[test]
+ fn test_inconsistent_object_keys() {
+ let obj_a = json!({
+ "foo": "bar",
+ "a": 2,
+ "b": "x",
+ "c": false,
+ });
+ let obj_b = json!({
+ "foo": "bar",
+ "a": 2,
+ "b": "y",
+ "D": true,
+ });
+
+ let expected_keys =
+ HashSet::from(["b".to_string(), "c".to_string(), "D".to_string()]);
+ let inconsistent_keys = find_inconsistent_object_keys(
+ obj_a.as_object().unwrap(),
+ obj_b.as_object().unwrap(),
+ );
+ assert_eq!(&expected_keys, &inconsistent_keys);
+ }
+}

File Metadata

Mime Type
text/plain
Expires
Fri, Nov 29, 6:21 PM (21 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2597768
Default Alt Text
D8986.id30723.diff (4 KB)

Event Timeline