state-res: refactor tiebreaking logic for clarity
This commit is contained in:
parent
97e2fb6df1
commit
e31b9dd3a4
@ -1,6 +1,6 @@
|
||||
use std::{
|
||||
borrow::Borrow,
|
||||
cmp::Reverse,
|
||||
cmp::{Ordering, Reverse},
|
||||
collections::{BinaryHeap, HashMap, HashSet},
|
||||
hash::Hash,
|
||||
};
|
||||
@ -289,14 +289,44 @@ where
|
||||
Fut: Future<Output = Result<(Int, MilliSecondsSinceUnixEpoch)>> + Send,
|
||||
Id: Borrow<EventId> + Clone + Eq + Hash + Ord + Send,
|
||||
{
|
||||
#[derive(Eq, Ord, PartialEq, PartialOrd)]
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct TieBreaker<'a, Id> {
|
||||
inv_power_level: Int,
|
||||
age: MilliSecondsSinceUnixEpoch,
|
||||
power_level: Int,
|
||||
origin_server_ts: MilliSecondsSinceUnixEpoch,
|
||||
event_id: &'a Id,
|
||||
}
|
||||
|
||||
impl<'a, Id> Ord for TieBreaker<'a, Id>
|
||||
where
|
||||
Id: Ord,
|
||||
{
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
// NOTE: the power level comparison is "backwards" intentionally.
|
||||
// See the "Mainline ordering" section of the Matrix specification
|
||||
// around where it says the following:
|
||||
//
|
||||
// > for events `x` and `y`, `x < y` if [...]
|
||||
//
|
||||
// <https://spec.matrix.org/v1.12/rooms/v11/#definitions>
|
||||
other
|
||||
.power_level
|
||||
.cmp(&self.power_level)
|
||||
.then(self.origin_server_ts.cmp(&other.origin_server_ts))
|
||||
.then(self.event_id.cmp(other.event_id))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Id> PartialOrd for TieBreaker<'a, Id>
|
||||
where
|
||||
Id: Ord,
|
||||
{
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
debug!("starting lexicographical topological sort");
|
||||
|
||||
// NOTE: an event that has no incoming edges happened most recently,
|
||||
// and an event that has no outgoing edges happened least recently.
|
||||
|
||||
@ -317,12 +347,12 @@ where
|
||||
|
||||
for (node, edges) in graph {
|
||||
if edges.is_empty() {
|
||||
let (power_level, age) = key_fn(node.clone()).await?;
|
||||
let (power_level, origin_server_ts) = key_fn(node.clone()).await?;
|
||||
// The `Reverse` is because rusts `BinaryHeap` sorts largest -> smallest we need
|
||||
// smallest -> largest
|
||||
zero_outdegree.push(Reverse(TieBreaker {
|
||||
inv_power_level: -power_level,
|
||||
age,
|
||||
power_level,
|
||||
origin_server_ts,
|
||||
event_id: node,
|
||||
}));
|
||||
}
|
||||
@ -350,12 +380,8 @@ where
|
||||
// Only push on the heap once older events have been cleared
|
||||
out.remove(node.borrow());
|
||||
if out.is_empty() {
|
||||
let (power_level, age) = key_fn(parent.clone()).await?;
|
||||
heap.push(Reverse(TieBreaker {
|
||||
inv_power_level: -power_level,
|
||||
age,
|
||||
event_id: parent,
|
||||
}));
|
||||
let (power_level, origin_server_ts) = key_fn(parent.clone()).await?;
|
||||
heap.push(Reverse(TieBreaker { power_level, origin_server_ts, event_id: parent }));
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user