( ctx context.Context, roomVersion gomatrixserverlib.RoomVersion, prevStates []types.StateAtEvent, )
| 707 | } |
| 708 | |
| 709 | func (v *StateResolution) calculateStateAfterManyEvents( |
| 710 | ctx context.Context, roomVersion gomatrixserverlib.RoomVersion, |
| 711 | prevStates []types.StateAtEvent, |
| 712 | ) (state []types.StateEntry, algorithm string, conflictLength int, err error) { |
| 713 | span, ctx := opentracing.StartSpanFromContext(ctx, "StateResolution.calculateStateAfterManyEvents") |
| 714 | defer span.Finish() |
| 715 | |
| 716 | var combined []types.StateEntry |
| 717 | // Conflict resolution. |
| 718 | // First stage: load the state after each of the prev events. |
| 719 | combined, err = v.LoadCombinedStateAfterEvents(ctx, prevStates) |
| 720 | if err != nil { |
| 721 | err = fmt.Errorf("v.LoadCombinedStateAfterEvents: %w", err) |
| 722 | algorithm = "_load_combined_state" |
| 723 | return |
| 724 | } |
| 725 | |
| 726 | // Collect all the entries with the same type and key together. |
| 727 | // This is done so findDuplicateStateKeys can work in groups. |
| 728 | // We remove duplicates (same type, state key and event NID) too. |
| 729 | combined = combined[:util.SortAndUnique(stateEntrySorter(combined))] |
| 730 | |
| 731 | // Find the conflicts |
| 732 | if conflicts := findDuplicateStateKeys(combined); len(conflicts) > 0 { |
| 733 | conflictMap := stateEntryMap(conflicts) |
| 734 | conflictLength = len(conflicts) |
| 735 | |
| 736 | // 5) There are conflicting state events, for each conflict workout |
| 737 | // what the appropriate state event is. |
| 738 | |
| 739 | // Work out which entries aren't conflicted. |
| 740 | var notConflicted []types.StateEntry |
| 741 | for _, entry := range combined { |
| 742 | if _, ok := conflictMap.lookup(entry.StateKeyTuple); !ok { |
| 743 | notConflicted = append(notConflicted, entry) |
| 744 | } |
| 745 | } |
| 746 | |
| 747 | var resolved []types.StateEntry |
| 748 | resolved, err = v.resolveConflicts(ctx, roomVersion, notConflicted, conflicts) |
| 749 | if err != nil { |
| 750 | err = fmt.Errorf("v.resolveConflits: %w", err) |
| 751 | algorithm = "_resolve_conflicts" |
| 752 | return |
| 753 | } |
| 754 | algorithm = "full_state_with_conflicts" |
| 755 | state = resolved |
| 756 | } else { |
| 757 | algorithm = "full_state_no_conflicts" |
| 758 | // 6) There weren't any conflicts |
| 759 | state = combined |
| 760 | } |
| 761 | return |
| 762 | } |
| 763 | |
| 764 | func (v *StateResolution) resolveConflicts( |
| 765 | ctx context.Context, version gomatrixserverlib.RoomVersion, |
no test coverage detected