Add docs and rename _get_event -> get_or_load_event
This commit is contained in:
parent
d22d83522b
commit
ccc75313c5
67
src/lib.rs
67
src/lib.rs
@ -45,6 +45,19 @@ pub struct StateResolution;
|
|||||||
impl StateResolution {
|
impl StateResolution {
|
||||||
/// Resolve sets of state events as they come in. Internally `StateResolution` builds a graph
|
/// Resolve sets of state events as they come in. Internally `StateResolution` builds a graph
|
||||||
/// and an auth chain to allow for state conflict resolution.
|
/// and an auth chain to allow for state conflict resolution.
|
||||||
|
///
|
||||||
|
/// ## Arguments
|
||||||
|
///
|
||||||
|
/// * `state_sets` - The incoming state to resolve. Each `StateMap` represents a possible fork
|
||||||
|
/// in the state of a room.
|
||||||
|
///
|
||||||
|
/// * `event_map` - The `EventMap` acts as a local cache of state, any event that is not found
|
||||||
|
/// in the `event_map` will be fetched from the `StateStore` and cached in the `event_map`. There
|
||||||
|
/// is no state kept from separate `resolve` calls, although this could be a potential optimization
|
||||||
|
/// in the future.
|
||||||
|
///
|
||||||
|
/// * `store` - Any type that implements `StateStore` acts as the database. When an event is not
|
||||||
|
/// found in the `event_map` it will be retrieved from the `store`.
|
||||||
pub fn resolve(
|
pub fn resolve(
|
||||||
&self,
|
&self,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
@ -134,7 +147,7 @@ impl StateResolution {
|
|||||||
let mut sorted_power_levels = self.reverse_topological_power_sort(
|
let mut sorted_power_levels = self.reverse_topological_power_sort(
|
||||||
room_id,
|
room_id,
|
||||||
&power_events,
|
&power_events,
|
||||||
&mut event_map, // TODO use event_map
|
&mut event_map,
|
||||||
store,
|
store,
|
||||||
&all_conflicted,
|
&all_conflicted,
|
||||||
);
|
);
|
||||||
@ -217,7 +230,6 @@ impl StateResolution {
|
|||||||
// add unconflicted state to the resolved state
|
// add unconflicted state to the resolved state
|
||||||
resolved_state.extend(clean);
|
resolved_state.extend(clean);
|
||||||
|
|
||||||
// TODO return something not a place holder
|
|
||||||
Ok(ResolutionResult::Resolved(resolved_state))
|
Ok(ResolutionResult::Resolved(resolved_state))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,7 +287,7 @@ impl StateResolution {
|
|||||||
(unconflicted_state, conflicted_state)
|
(unconflicted_state, conflicted_state)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a Vec of deduped EventIds that appear in some chains but no others.
|
/// Returns a Vec of deduped EventIds that appear in some chains but not others.
|
||||||
pub fn get_auth_chain_diff(
|
pub fn get_auth_chain_diff(
|
||||||
&self,
|
&self,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
@ -298,6 +310,12 @@ impl StateResolution {
|
|||||||
.map_err(Error::TempString)
|
.map_err(Error::TempString)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Events are sorted from "earliest" to "latest". They are compared using
|
||||||
|
/// the negative power level, the origin server timestamp and incase of a
|
||||||
|
/// tie the `EventId`s are compared lexicographically.
|
||||||
|
///
|
||||||
|
/// The power level is negative because a higher power level is equated to an
|
||||||
|
/// earlier (further back in time) origin server timestamp.
|
||||||
pub fn reverse_topological_power_sort(
|
pub fn reverse_topological_power_sort(
|
||||||
&self,
|
&self,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
@ -426,6 +444,7 @@ impl StateResolution {
|
|||||||
sorted
|
sorted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Find the power level for the sender of `event_id` or return a default value of zero.
|
||||||
fn get_power_level_for_sender(
|
fn get_power_level_for_sender(
|
||||||
&self,
|
&self,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
@ -433,14 +452,15 @@ impl StateResolution {
|
|||||||
event_map: &mut EventMap<StateEvent>,
|
event_map: &mut EventMap<StateEvent>,
|
||||||
store: &dyn StateStore,
|
store: &dyn StateStore,
|
||||||
) -> i64 {
|
) -> i64 {
|
||||||
tracing::info!("fetch event senders ({}) power level", event_id.to_string());
|
tracing::info!("fetch event ({}) senders power level", event_id.to_string());
|
||||||
let event = self._get_event(room_id, event_id, event_map, store);
|
|
||||||
|
let event = self.get_or_load_event(room_id, event_id, event_map, store);
|
||||||
let mut pl = None;
|
let mut pl = None;
|
||||||
|
|
||||||
// TODO store.auth_event_ids returns "self" with the event ids is this ok
|
// TODO store.auth_event_ids returns "self" with the event ids is this ok
|
||||||
// event.auth_event_ids does not include its own event id ?
|
// event.auth_event_ids does not include its own event id ?
|
||||||
for aid in event.as_ref().unwrap().auth_events() {
|
for aid in event.as_ref().unwrap().auth_events() {
|
||||||
if let Some(aev) = self._get_event(room_id, &aid, event_map, store) {
|
if let Some(aev) = self.get_or_load_event(room_id, &aid, event_map, store) {
|
||||||
if aev.is_type_and_key(EventType::RoomPowerLevels, "") {
|
if aev.is_type_and_key(EventType::RoomPowerLevels, "") {
|
||||||
pl = Some(aev);
|
pl = Some(aev);
|
||||||
break;
|
break;
|
||||||
@ -492,7 +512,7 @@ impl StateResolution {
|
|||||||
room_version: &RoomVersionId,
|
room_version: &RoomVersionId,
|
||||||
power_events: &[EventId],
|
power_events: &[EventId],
|
||||||
unconflicted_state: &StateMap<EventId>,
|
unconflicted_state: &StateMap<EventId>,
|
||||||
event_map: &mut EventMap<StateEvent>, // TODO use event_map over store ??
|
event_map: &mut EventMap<StateEvent>,
|
||||||
store: &dyn StateStore,
|
store: &dyn StateStore,
|
||||||
) -> Result<StateMap<EventId>> {
|
) -> Result<StateMap<EventId>> {
|
||||||
tracing::info!("starting iterative auth check");
|
tracing::info!("starting iterative auth check");
|
||||||
@ -509,12 +529,12 @@ impl StateResolution {
|
|||||||
|
|
||||||
for (idx, event_id) in power_events.iter().enumerate() {
|
for (idx, event_id) in power_events.iter().enumerate() {
|
||||||
let event = self
|
let event = self
|
||||||
._get_event(room_id, event_id, event_map, store)
|
.get_or_load_event(room_id, event_id, event_map, store)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut auth_events = BTreeMap::new();
|
let mut auth_events = BTreeMap::new();
|
||||||
for aid in event.auth_events() {
|
for aid in event.auth_events() {
|
||||||
if let Some(ev) = self._get_event(room_id, &aid, event_map, store) {
|
if let Some(ev) = self.get_or_load_event(room_id, &aid, event_map, store) {
|
||||||
// TODO what to do when no state_key is found ??
|
// TODO what to do when no state_key is found ??
|
||||||
// TODO synapse check "rejected_reason", I'm guessing this is redacted_because for ruma ??
|
// TODO synapse check "rejected_reason", I'm guessing this is redacted_because for ruma ??
|
||||||
auth_events.insert((ev.kind(), ev.state_key()), ev);
|
auth_events.insert((ev.kind(), ev.state_key()), ev);
|
||||||
@ -530,7 +550,7 @@ impl StateResolution {
|
|||||||
event.content().clone(),
|
event.content().clone(),
|
||||||
) {
|
) {
|
||||||
if let Some(ev_id) = resolved_state.get(&key) {
|
if let Some(ev_id) = resolved_state.get(&key) {
|
||||||
if let Some(event) = self._get_event(room_id, ev_id, event_map, store) {
|
if let Some(event) = self.get_or_load_event(room_id, ev_id, event_map, store) {
|
||||||
// TODO synapse checks `rejected_reason` is None here
|
// TODO synapse checks `rejected_reason` is None here
|
||||||
auth_events.insert(key.clone(), event);
|
auth_events.insert(key.clone(), event);
|
||||||
}
|
}
|
||||||
@ -588,11 +608,15 @@ impl StateResolution {
|
|||||||
while let Some(p) = pl {
|
while let Some(p) = pl {
|
||||||
mainline.push(p.clone());
|
mainline.push(p.clone());
|
||||||
|
|
||||||
let event = self._get_event(room_id, &p, event_map, store).unwrap();
|
let event = self
|
||||||
|
.get_or_load_event(room_id, &p, event_map, store)
|
||||||
|
.unwrap();
|
||||||
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 = self._get_event(room_id, &aid, event_map, store).unwrap();
|
let ev = self
|
||||||
|
.get_or_load_event(room_id, &aid, event_map, store)
|
||||||
|
.unwrap();
|
||||||
if ev.is_type_and_key(EventType::RoomPowerLevels, "") {
|
if ev.is_type_and_key(EventType::RoomPowerLevels, "") {
|
||||||
pl = Some(aid.clone());
|
pl = Some(aid.clone());
|
||||||
break;
|
break;
|
||||||
@ -616,7 +640,7 @@ impl StateResolution {
|
|||||||
|
|
||||||
let mut order_map = BTreeMap::new();
|
let mut order_map = BTreeMap::new();
|
||||||
for (idx, ev_id) in to_sort.iter().enumerate() {
|
for (idx, ev_id) in to_sort.iter().enumerate() {
|
||||||
let event = self._get_event(room_id, ev_id, event_map, store);
|
let event = self.get_or_load_event(room_id, ev_id, event_map, store);
|
||||||
let depth = self.get_mainline_depth(room_id, event, &mainline_map, event_map, store);
|
let depth = self.get_mainline_depth(room_id, event, &mainline_map, event_map, store);
|
||||||
order_map.insert(
|
order_map.insert(
|
||||||
ev_id,
|
ev_id,
|
||||||
@ -663,7 +687,9 @@ impl StateResolution {
|
|||||||
let auth_events = sort_ev.auth_events();
|
let auth_events = sort_ev.auth_events();
|
||||||
event = None;
|
event = None;
|
||||||
for aid in auth_events {
|
for aid in auth_events {
|
||||||
let aev = self._get_event(room_id, &aid, event_map, store).unwrap();
|
let aev = self
|
||||||
|
.get_or_load_event(room_id, &aid, event_map, store)
|
||||||
|
.unwrap();
|
||||||
if aev.is_type_and_key(EventType::RoomPowerLevels, "") {
|
if aev.is_type_and_key(EventType::RoomPowerLevels, "") {
|
||||||
event = Some(aev.clone());
|
event = Some(aev.clone());
|
||||||
break;
|
break;
|
||||||
@ -691,7 +717,7 @@ impl StateResolution {
|
|||||||
// prefer the store to event as the store filters dedups the events
|
// prefer the store to event as the store filters dedups the events
|
||||||
// otherwise it seems we can loop forever
|
// otherwise it seems we can loop forever
|
||||||
for aid in self
|
for aid in self
|
||||||
._get_event(room_id, &eid, event_map, store)
|
.get_or_load_event(room_id, &eid, event_map, store)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.auth_events()
|
.auth_events()
|
||||||
{
|
{
|
||||||
@ -707,8 +733,13 @@ impl StateResolution {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO update self if we go that route just as event_map will be updated
|
// TODO having the event_map as a field of self would allow us to keep
|
||||||
fn _get_event(
|
// cached state from `resolve` to `resolve` calls, good idea or not?
|
||||||
|
/// Uses the `event_map` to return the full PDU or fetches from the `StateStore` implementation
|
||||||
|
/// if the event_map does not have the PDU.
|
||||||
|
///
|
||||||
|
/// If the PDU is missing from the `event_map` it is added.
|
||||||
|
fn get_or_load_event(
|
||||||
&self,
|
&self,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
ev_id: &EventId,
|
ev_id: &EventId,
|
||||||
@ -729,6 +760,6 @@ impl StateResolution {
|
|||||||
pub fn is_power_event(event_id: &EventId, event_map: &EventMap<StateEvent>) -> bool {
|
pub fn is_power_event(event_id: &EventId, event_map: &EventMap<StateEvent>) -> bool {
|
||||||
match event_map.get(event_id) {
|
match event_map.get(event_id) {
|
||||||
Some(state) => state.is_power_event(),
|
Some(state) => state.is_power_event(),
|
||||||
_ => false, // TODO this shouldn't eat errors?
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user