mirror of
https://github.com/matrix-org/dendrite
synced 2024-12-14 23:33:51 +01:00
Ensure that all state event IDs are included in the added
section when rewriting state (#2725)
This should hopefully fix an entire class of problems where components downstream from the roomserver (i.e. the sync API) could just lose a whole bunch of state after a rewrite operation like a federated join. The root of the bug is that we set `RewritesState` in the output event which instructs downstream components to purge their copy of any room state, but then didn't send the entire state snapshot in `adds_state_event_ids` so the downstream state ends up being incomplete as a result.
This commit is contained in:
parent
a5f8c07184
commit
fc1d8e479b
1 changed files with 21 additions and 10 deletions
|
@ -264,16 +264,27 @@ func (u *latestEventsUpdater) latestState() error {
|
||||||
return fmt.Errorf("roomState.CalculateAndStoreStateAfterEvents: %w", err)
|
return fmt.Errorf("roomState.CalculateAndStoreStateAfterEvents: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that we have a new state snapshot based on the latest events,
|
// Include information about what changed in the state transition. If the
|
||||||
// we can compare that new snapshot to the previous one and see what
|
// event rewrites the state (i.e. is a federated join) then we will simply
|
||||||
// has changed. This gives us one list of removed state events and
|
// include the entire state snapshot as added events, as the "RewritesState"
|
||||||
// another list of added ones. Replacing a value for a state-key tuple
|
// flag in the output event signals downstream components to purge their
|
||||||
// will result one removed (the old event) and one added (the new event).
|
// room state first. If it doesn't rewrite the state then we will work out
|
||||||
u.removed, u.added, err = roomState.DifferenceBetweeenStateSnapshots(
|
// what the difference is between the state snapshots and send that. In all
|
||||||
ctx, u.oldStateNID, u.newStateNID,
|
// cases where a state event is being replaced, the old state event will
|
||||||
)
|
// appear in "removed" and the replacement will appear in "added".
|
||||||
if err != nil {
|
if u.rewritesState {
|
||||||
return fmt.Errorf("roomState.DifferenceBetweenStateSnapshots: %w", err)
|
u.removed = []types.StateEntry{}
|
||||||
|
u.added, err = roomState.LoadStateAtSnapshot(ctx, u.newStateNID)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("roomState.LoadStateAtSnapshot: %w", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
u.removed, u.added, err = roomState.DifferenceBetweeenStateSnapshots(
|
||||||
|
ctx, u.oldStateNID, u.newStateNID,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("roomState.DifferenceBetweenStateSnapshots: %w", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if removed := len(u.removed) - len(u.added); !u.rewritesState && removed > 0 {
|
if removed := len(u.removed) - len(u.added); !u.rewritesState && removed > 0 {
|
||||||
|
|
Loading…
Reference in a new issue