Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3363167
D8986.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
4 KB
Referenced Files
None
Subscribers
None
D8986.diff
View Options
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
Details
Attached
Mime Type
text/plain
Expires
Tue, Nov 26, 12:34 AM (20 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2581801
Default Alt Text
D8986.diff (4 KB)
Attached To
Mode
D8986: [reports-service] E-mail: inconsistency report details
Attached
Detach File
Event Timeline
Log In to Comment