aboutsummaryrefslogtreecommitdiff
path: root/syncapi/routing
diff options
context:
space:
mode:
authorKegsay <kegan@matrix.org>2020-05-01 16:41:13 +0100
committerGitHub <noreply@github.com>2020-05-01 16:41:13 +0100
commit36bbb255614d289a3417194d4d2ac129e339f531 (patch)
treebe8ea170d1ae2e04740b95dedbe63d4892381109 /syncapi/routing
parentf7cfa758864cc9849ce8b0539895283417b75eb0 (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.go40
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
}
}