1
0
Fork 0
mirror of https://github.com/matrix-org/dendrite.git synced 2025-03-28 12:34:27 -05:00

Ensure that all state event IDs are included in the added section when rewriting state ()

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:
Neil Alexander 2022-09-16 10:35:32 +01:00 committed by GitHub
parent a5f8c07184
commit fc1d8e479b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -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 {