diff options
author | Kegsay <kegan@matrix.org> | 2020-05-01 16:41:13 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-01 16:41:13 +0100 |
commit | 36bbb255614d289a3417194d4d2ac129e339f531 (patch) | |
tree | be8ea170d1ae2e04740b95dedbe63d4892381109 /syncapi/routing | |
parent | f7cfa758864cc9849ce8b0539895283417b75eb0 (diff) |
Fix ordering when backfilling (#1000)
* Fix ordering when backfilling
The problem was that we weren't sorting the returned events
by depth when sending them back to the caller, instead we
were sorting by prev_events which is not the same thing.
* Fixup tests
Diffstat (limited to 'syncapi/routing')
-rw-r--r-- | syncapi/routing/messages.go | 40 |
1 files changed, 31 insertions, 9 deletions
diff --git a/syncapi/routing/messages.go b/syncapi/routing/messages.go index d7e39704..270b0ee9 100644 --- a/syncapi/routing/messages.go +++ b/syncapi/routing/messages.go @@ -210,15 +210,16 @@ func (r *messagesReq) retrieveEvents() ( } // Sort the events to ensure we send them in the right order. - events = gomatrixserverlib.HeaderedReverseTopologicalOrdering( - events, - gomatrixserverlib.TopologicalOrderByPrevEvents, - ) if r.backwardOrdering { // This reverses the array from old->new to new->old - sort.SliceStable(events, func(i, j int) bool { - return true - }) + reversed := func(in []gomatrixserverlib.HeaderedEvent) []gomatrixserverlib.HeaderedEvent { + out := make([]gomatrixserverlib.HeaderedEvent, len(in)) + for i := 0; i < len(in); i++ { + out[i] = in[len(in)-i-1] + } + return out + } + events = reversed(events) } // Convert all of the events into client events. @@ -259,6 +260,7 @@ func (r *messagesReq) retrieveEvents() ( // to them by the event on their left, therefore we need to decrement the // end position we send in the response if we're going backward. end.PDUPosition-- + end.EDUTypingPosition += 1000 } // The lowest token value is 1, therefore we need to manually set it to that @@ -345,10 +347,23 @@ func (r *messagesReq) handleNonEmptyEventsSlice(streamEvents []types.StreamEvent // Append the events ve previously retrieved locally. events = append(events, r.db.StreamEventsToEvents(nil, streamEvents)...) + sort.Sort(eventsByDepth(events)) return } +type eventsByDepth []gomatrixserverlib.HeaderedEvent + +func (e eventsByDepth) Len() int { + return len(e) +} +func (e eventsByDepth) Swap(i, j int) { + e[i], e[j] = e[j], e[i] +} +func (e eventsByDepth) Less(i, j int) bool { + return e[i].Depth() < e[j].Depth() +} + // backfill performs a backfill request over the federation on another // homeserver in the room. // See: https://matrix.org/docs/spec/server_server/latest#get-matrix-federation-v1-backfill-roomid @@ -375,17 +390,24 @@ func (r *messagesReq) backfill(roomID string, fromEventIDs []string, limit int) // Currently, this can race with live events for the room and cause problems. It's also just a bit unclear // when you have multiple entry points to write events. + // we have to order these by depth, starting with the lowest because otherwise the topology tokens + // will skip over events that have the same depth but different stream positions due to the query which is: + // - anything less than the depth OR + // - anything with the same depth and a lower stream position. + sort.Sort(eventsByDepth(res.Events)) + // Store the events in the database, while marking them as unfit to show // up in responses to sync requests. for i := range res.Events { - if _, err = r.db.WriteEvent( + _, err = r.db.WriteEvent( r.ctx, &res.Events[i], []gomatrixserverlib.HeaderedEvent{}, []string{}, []string{}, nil, true, - ); err != nil { + ) + if err != nil { return nil, err } } |