Resolve state after event against current room state when determining latest state changes (#1479)
* Resolve state after event against current room state when determining latest state changes * Update sytest-whitelist * Update sytest-whitelist, blacklist
This commit is contained in:
parent
4e6b7f726d
commit
2e71d2708f
|
@ -215,10 +215,27 @@ func (u *latestEventsUpdater) latestState() error {
|
|||
var err error
|
||||
roomState := state.NewStateResolution(u.api.DB, *u.roomInfo)
|
||||
|
||||
// Get a list of the current latest events.
|
||||
latestStateAtEvents := make([]types.StateAtEvent, len(u.latest))
|
||||
// Get a list of the current room state events if available.
|
||||
var currentState []types.StateEntry
|
||||
if u.roomInfo.StateSnapshotNID != 0 {
|
||||
currentState, _ = roomState.LoadStateAtSnapshot(u.ctx, u.roomInfo.StateSnapshotNID)
|
||||
}
|
||||
|
||||
// Get a list of the current latest events. This will include both
|
||||
// the current room state and the latest events after the input event.
|
||||
// The idea is that we will perform state resolution on this set and
|
||||
// any conflicting events will be resolved properly.
|
||||
latestStateAtEvents := make([]types.StateAtEvent, len(u.latest)+len(currentState))
|
||||
offset := 0
|
||||
for i := range currentState {
|
||||
latestStateAtEvents[i] = types.StateAtEvent{
|
||||
BeforeStateSnapshotNID: u.roomInfo.StateSnapshotNID,
|
||||
StateEntry: currentState[i],
|
||||
}
|
||||
offset++
|
||||
}
|
||||
for i := range u.latest {
|
||||
latestStateAtEvents[i] = u.latest[i].StateAtEvent
|
||||
latestStateAtEvents[offset+i] = u.latest[i].StateAtEvent
|
||||
}
|
||||
|
||||
// Takes the NIDs of the latest events and creates a state snapshot
|
||||
|
|
|
@ -118,7 +118,7 @@ func (v StateResolution) LoadCombinedStateAfterEvents(
|
|||
// the snapshot of the room state before them was the same.
|
||||
stateBlockNIDLists, err := v.db.StateBlockNIDs(ctx, uniqueStateSnapshotNIDs(stateNIDs))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("v.db.StateBlockNIDs: %w", err)
|
||||
}
|
||||
|
||||
var stateBlockNIDs []types.StateBlockNID
|
||||
|
@ -131,7 +131,7 @@ func (v StateResolution) LoadCombinedStateAfterEvents(
|
|||
// multiple snapshots.
|
||||
stateEntryLists, err := v.db.StateEntries(ctx, uniqueStateBlockNIDs(stateBlockNIDs))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("v.db.StateEntries: %w", err)
|
||||
}
|
||||
stateBlockNIDsMap := stateBlockNIDListMap(stateBlockNIDLists)
|
||||
stateEntriesMap := stateEntryListMap(stateEntryLists)
|
||||
|
@ -623,7 +623,7 @@ func (v StateResolution) calculateAndStoreStateAfterManyEvents(
|
|||
v.calculateStateAfterManyEvents(ctx, v.roomInfo.RoomVersion, prevStates)
|
||||
metrics.algorithm = algorithm
|
||||
if err != nil {
|
||||
return metrics.stop(0, err)
|
||||
return metrics.stop(0, fmt.Errorf("v.calculateStateAfterManyEvents: %w", err))
|
||||
}
|
||||
|
||||
// TODO: Check if we can encode the new state as a delta against the
|
||||
|
@ -642,6 +642,7 @@ func (v StateResolution) calculateStateAfterManyEvents(
|
|||
// First stage: load the state after each of the prev events.
|
||||
combined, err = v.LoadCombinedStateAfterEvents(ctx, prevStates)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("v.LoadCombinedStateAfterEvents: %w", err)
|
||||
algorithm = "_load_combined_state"
|
||||
return
|
||||
}
|
||||
|
@ -672,6 +673,7 @@ func (v StateResolution) calculateStateAfterManyEvents(
|
|||
var resolved []types.StateEntry
|
||||
resolved, err = v.resolveConflicts(ctx, roomVersion, notConflicted, conflicts)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("v.resolveConflits: %w", err)
|
||||
algorithm = "_resolve_conflicts"
|
||||
return
|
||||
}
|
||||
|
|
|
@ -52,4 +52,9 @@ Inbound federation accepts a second soft-failed event
|
|||
Outbound federation requests missing prev_events and then asks for /state_ids and resolves the state
|
||||
|
||||
# We don't implement lazy membership loading yet.
|
||||
The only membership state included in a gapped incremental sync is for senders in the timeline
|
||||
The only membership state included in a gapped incremental sync is for senders in the timeline
|
||||
|
||||
# Blacklisted out of flakiness after #1479
|
||||
Invited user can reject local invite after originator leaves
|
||||
Invited user can reject invite for empty room
|
||||
If user leaves room, remote user changes device and rejoins we see update in /sync and /keys/changes
|
|
@ -400,8 +400,6 @@ Uninvited users cannot join the room
|
|||
Users cannot invite themselves to a room
|
||||
Users cannot invite a user that is already in the room
|
||||
Invited user can reject invite
|
||||
Invited user can reject invite for empty room
|
||||
Invited user can reject local invite after originator leaves
|
||||
PUT /rooms/:room_id/typing/:user_id sets typing notification
|
||||
Typing notification sent to local room members
|
||||
Typing notifications also sent to remote room members
|
||||
|
@ -431,7 +429,6 @@ A prev_batch token can be used in the v1 messages API
|
|||
We don't send redundant membership state across incremental syncs by default
|
||||
Typing notifications don't leak
|
||||
Users cannot kick users from a room they are not in
|
||||
Users cannot kick users who have already left a room
|
||||
User appears in user directory
|
||||
User directory correctly update on display name change
|
||||
User in shared private room does appear in user directory
|
||||
|
@ -451,7 +448,6 @@ Banned servers cannot backfill
|
|||
Inbound /v1/send_leave rejects leaves from other servers
|
||||
Guest users can accept invites to private rooms over federation
|
||||
AS user (not ghost) can join room without registering
|
||||
If user leaves room, remote user changes device and rejoins we see update in /sync and /keys/changes
|
||||
Can search public room list
|
||||
Can get remote public room list
|
||||
Asking for a remote rooms list, but supplying the local server's name, returns the local rooms list
|
||||
|
|
Loading…
Reference in a new issue