state-res: Replace unwraps with expect or errors

This commit is contained in:
Devin Ragotzy 2021-07-15 14:42:34 -04:00 committed by Jonas Platte
parent 01515aea41
commit 318f3186ad
No known key found for this signature in database
GPG Key ID: CC154DE0E30B7C67
5 changed files with 37 additions and 29 deletions

View File

@ -46,7 +46,7 @@ fn lexico_topo_sort(c: &mut Criterion) {
}; };
b.iter(|| { b.iter(|| {
let _ = StateResolution::lexicographical_topological_sort(&graph, |id| { let _ = StateResolution::lexicographical_topological_sort(&graph, |id| {
(0, MilliSecondsSinceUnixEpoch(uint!(0)), id.clone()) Ok((0, MilliSecondsSinceUnixEpoch(uint!(0)), id.clone()))
}); });
}) })
}); });

View File

@ -136,7 +136,7 @@ impl StateResolution {
&control_events, &control_events,
&all_conflicted, &all_conflicted,
&fetch_event, &fetch_event,
); )?;
debug!("sorted control events: {}", sorted_control_levels.len()); debug!("sorted control events: {}", sorted_control_levels.len());
trace!("{:?}", sorted_control_levels); trace!("{:?}", sorted_control_levels);
@ -174,7 +174,7 @@ impl StateResolution {
debug!("power event: {:?}", power_event); debug!("power event: {:?}", power_event);
let sorted_left_events = let sorted_left_events =
StateResolution::mainline_sort(&events_to_resolve, power_event, &fetch_event); StateResolution::mainline_sort(&events_to_resolve, power_event, &fetch_event)?;
trace!("events left, sorted: {:?}", sorted_left_events.iter().collect::<Vec<_>>()); trace!("events left, sorted: {:?}", sorted_left_events.iter().collect::<Vec<_>>());
@ -249,7 +249,7 @@ impl StateResolution {
events_to_sort: &[EventId], events_to_sort: &[EventId],
auth_diff: &HashSet<EventId>, auth_diff: &HashSet<EventId>,
fetch_event: F, fetch_event: F,
) -> Vec<EventId> ) -> Result<Vec<EventId>>
where where
E: Event, E: Event,
F: Fn(&EventId) -> Option<Arc<E>>, F: Fn(&EventId) -> Option<Arc<E>>,
@ -284,15 +284,15 @@ impl StateResolution {
} }
StateResolution::lexicographical_topological_sort(&graph, |event_id| { StateResolution::lexicographical_topological_sort(&graph, |event_id| {
let ev = fetch_event(event_id).unwrap(); let ev = fetch_event(event_id).ok_or_else(|| Error::NotFound("".into()))?;
let pl = event_to_pl.get(event_id).unwrap(); let pl = event_to_pl.get(event_id).ok_or_else(|| Error::NotFound("".into()))?;
debug!("{:?}", (-*pl, ev.origin_server_ts(), &ev.event_id())); debug!("{:?}", (-*pl, ev.origin_server_ts(), &ev.event_id()));
// This return value is the key used for sorting events, // This return value is the key used for sorting events,
// events are then sorted by power level, time, // events are then sorted by power level, time,
// and lexically by event_id. // and lexically by event_id.
(-*pl, ev.origin_server_ts(), ev.event_id().clone()) Ok((-*pl, ev.origin_server_ts(), ev.event_id().clone()))
}) })
} }
@ -302,9 +302,9 @@ impl StateResolution {
pub fn lexicographical_topological_sort<F>( pub fn lexicographical_topological_sort<F>(
graph: &HashMap<EventId, HashSet<EventId>>, graph: &HashMap<EventId, HashSet<EventId>>,
key_fn: F, key_fn: F,
) -> Vec<EventId> ) -> Result<Vec<EventId>>
where where
F: Fn(&EventId) -> (i64, MilliSecondsSinceUnixEpoch, EventId), F: Fn(&EventId) -> Result<(i64, MilliSecondsSinceUnixEpoch, EventId)>,
{ {
info!("starting lexicographical topological sort"); info!("starting lexicographical topological sort");
// NOTE: an event that has no incoming edges happened most recently, // NOTE: an event that has no incoming edges happened most recently,
@ -314,12 +314,12 @@ impl StateResolution {
// outgoing edges, c.f. // outgoing edges, c.f.
// https://en.wikipedia.org/wiki/Topological_sorting#Kahn's_algorithm // https://en.wikipedia.org/wiki/Topological_sorting#Kahn's_algorithm
// TODO make the HashSet conversion cleaner ??
// outdegree_map is an event referring to the events before it, the // outdegree_map is an event referring to the events before it, the
// more outdegree's the more recent the event. // more outdegree's the more recent the event.
let mut outdegree_map = graph.clone(); let mut outdegree_map = graph.clone();
// The number of events that depend on the given event (the eventId key) // The number of events that depend on the given event (the EventId key)
// How many events reference this event in the DAG as a parent
let mut reverse_graph = HashMap::new(); let mut reverse_graph = HashMap::new();
// Vec of nodes that have zero out degree, least recent events. // Vec of nodes that have zero out degree, least recent events.
@ -329,7 +329,7 @@ impl StateResolution {
if edges.is_empty() { if edges.is_empty() {
// The `Reverse` is because rusts `BinaryHeap` sorts largest -> smallest we need // The `Reverse` is because rusts `BinaryHeap` sorts largest -> smallest we need
// smallest -> largest // smallest -> largest
zero_outdegree.push(Reverse((key_fn(node), node))); zero_outdegree.push(Reverse((key_fn(node)?, node)));
} }
reverse_graph.entry(node).or_insert(hashset![]); reverse_graph.entry(node).or_insert(hashset![]);
@ -345,14 +345,17 @@ impl StateResolution {
// Destructure the `Reverse` and take the smallest `node` each time // Destructure the `Reverse` and take the smallest `node` each time
while let Some(Reverse((_, node))) = heap.pop() { while let Some(Reverse((_, node))) = heap.pop() {
let node: &EventId = node; let node: &EventId = node;
for parent in reverse_graph.get(node).unwrap() { for parent in reverse_graph.get(node).expect("EventId in heap is also in reverse_graph")
{
// The number of outgoing edges this node has // The number of outgoing edges this node has
let out = outdegree_map.get_mut(parent).unwrap(); let out = outdegree_map
.get_mut(parent)
.expect("outdegree_map knows of all referenced EventIds");
// Only push on the heap once older events have been cleared // Only push on the heap once older events have been cleared
out.remove(node); out.remove(node);
if out.is_empty() { if out.is_empty() {
heap.push(Reverse((key_fn(parent), parent))); heap.push(Reverse((key_fn(parent)?, parent)));
} }
} }
@ -360,7 +363,7 @@ impl StateResolution {
sorted.push(node.clone()); sorted.push(node.clone());
} }
sorted Ok(sorted)
} }
/// Find the power level for the sender of `event_id` or return a default value of zero. /// Find the power level for the sender of `event_id` or return a default value of zero.
@ -516,7 +519,7 @@ impl StateResolution {
to_sort: &[EventId], to_sort: &[EventId],
resolved_power_level: Option<&EventId>, resolved_power_level: Option<&EventId>,
fetch_event: F, fetch_event: F,
) -> Vec<EventId> ) -> Result<Vec<EventId>>
where where
E: Event, E: Event,
F: Fn(&EventId) -> Option<Arc<E>>, F: Fn(&EventId) -> Option<Arc<E>>,
@ -525,7 +528,7 @@ impl StateResolution {
// There are no EventId's to sort, bail. // There are no EventId's to sort, bail.
if to_sort.is_empty() { if to_sort.is_empty() {
return vec![]; return Ok(vec![]);
} }
let mut mainline = vec![]; let mut mainline = vec![];
@ -533,11 +536,13 @@ impl StateResolution {
while let Some(p) = pl { while let Some(p) = pl {
mainline.push(p.clone()); mainline.push(p.clone());
let event = fetch_event(&p).unwrap(); let event =
fetch_event(&p).ok_or_else(|| Error::NotFound(format!("Failed to find {}", p)))?;
let auth_events = &event.auth_events(); let auth_events = &event.auth_events();
pl = None; pl = None;
for aid in auth_events { for aid in auth_events {
let ev = fetch_event(aid).unwrap(); let ev = fetch_event(aid)
.ok_or_else(|| Error::NotFound(format!("Failed to find {}", aid)))?;
if is_type_and_key(&ev, EventType::RoomPowerLevels, "") { if is_type_and_key(&ev, EventType::RoomPowerLevels, "") {
pl = Some(aid.clone()); pl = Some(aid.clone());
break; break;
@ -582,7 +587,7 @@ impl StateResolution {
let mut sort_event_ids = order_map.keys().map(|&k| k.clone()).collect::<Vec<_>>(); let mut sort_event_ids = order_map.keys().map(|&k| k.clone()).collect::<Vec<_>>();
sort_event_ids.sort_by_key(|sort_id| order_map.get(sort_id).unwrap()); sort_event_ids.sort_by_key(|sort_id| order_map.get(sort_id).unwrap());
sort_event_ids Ok(sort_event_ids)
} }
/// Get the mainline depth from the `mainline_map` or finds a power_level event /// Get the mainline depth from the `mainline_map` or finds a power_level event

View File

@ -32,10 +32,9 @@ fn test_event_sort() {
let sorted_power_events = let sorted_power_events =
StateResolution::reverse_topological_power_sort(&power_events, &auth_chain, |id| { StateResolution::reverse_topological_power_sort(&power_events, &auth_chain, |id| {
events.get(id).map(Arc::clone) events.get(id).map(Arc::clone)
}); })
.unwrap();
// This is a TODO in conduit
// TODO we may be able to skip this since they are resolved according to spec
let resolved_power = StateResolution::iterative_auth_check( let resolved_power = StateResolution::iterative_auth_check(
&RoomVersion::version_6(), &RoomVersion::version_6(),
&sorted_power_events, &sorted_power_events,
@ -53,7 +52,8 @@ fn test_event_sort() {
let sorted_event_ids = StateResolution::mainline_sort(&events_to_sort, power_level, |id| { let sorted_event_ids = StateResolution::mainline_sort(&events_to_sort, power_level, |id| {
events.get(id).map(Arc::clone) events.get(id).map(Arc::clone)
}); })
.unwrap();
assert_eq!( assert_eq!(
vec![ vec![

View File

@ -286,8 +286,9 @@ fn test_lexicographical_sort() {
}; };
let res = StateResolution::lexicographical_topological_sort(&graph, |id| { let res = StateResolution::lexicographical_topological_sort(&graph, |id| {
(0, MilliSecondsSinceUnixEpoch(uint!(0)), id.clone()) Ok((0, MilliSecondsSinceUnixEpoch(uint!(0)), id.clone()))
}); })
.unwrap();
assert_eq!( assert_eq!(
vec!["o", "l", "n", "m", "p"], vec!["o", "l", "n", "m", "p"],

View File

@ -80,8 +80,10 @@ pub fn do_check(
// Resolve the current state and add it to the state_at_event map then continue // Resolve the current state and add it to the state_at_event map then continue
// on in "time" // on in "time"
for node in StateResolution::lexicographical_topological_sort(&graph, |id| { for node in StateResolution::lexicographical_topological_sort(&graph, |id| {
(0, MilliSecondsSinceUnixEpoch(uint!(0)), id.clone()) Ok((0, MilliSecondsSinceUnixEpoch(uint!(0)), id.clone()))
}) { })
.unwrap()
{
let fake_event = fake_event_map.get(&node).unwrap(); let fake_event = fake_event_map.get(&node).unwrap();
let event_id = fake_event.event_id().clone(); let event_id = fake_event.event_id().clone();