/sync: Handle missing state events and return events in the correct order (#72)

main
Kegsay 2017-04-20 11:18:26 +01:00 committed by GitHub
parent 92a0325266
commit fad7e9541b
1 changed files with 38 additions and 11 deletions

View File

@ -146,19 +146,15 @@ func (s *outputRoomEventsStatements) StateBetween(txn *sql.Tx, oldPos, newPos ty
eventIDToEvent[ev.EventID()] = ev eventIDToEvent[ev.EventID()] = ev
} }
stateBetween, missingEvents := mapEventIDsToEvents(eventIDToEvent, stateNeeded) return s.fetchStateEvents(txn, stateNeeded, eventIDToEvent)
if len(missingEvents) > 0 {
return nil, fmt.Errorf("error StateBetween: TODO missing events")
}
return stateBetween, nil
} }
// convert the set of event IDs into a set of events. Mark any which are missing. // fetchStateEvents converts the set of event IDs into a set of events. It will fetch any which are missing from the database.
func mapEventIDsToEvents(eventIDToEvent map[string]gomatrixserverlib.Event, stateNeeded map[string]map[string]bool) (map[string][]gomatrixserverlib.Event, map[string][]string) { // Returns a map of room ID to list of events.
func (s *outputRoomEventsStatements) fetchStateEvents(txn *sql.Tx, roomIDToEventIDSet map[string]map[string]bool, eventIDToEvent map[string]gomatrixserverlib.Event) (map[string][]gomatrixserverlib.Event, error) {
stateBetween := make(map[string][]gomatrixserverlib.Event) stateBetween := make(map[string][]gomatrixserverlib.Event)
missingEvents := make(map[string][]string) missingEvents := make(map[string][]string)
for roomID, ids := range stateNeeded { for roomID, ids := range roomIDToEventIDSet {
events := stateBetween[roomID] events := stateBetween[roomID]
for id, need := range ids { for id, need := range ids {
if !need { if !need {
@ -175,7 +171,25 @@ func mapEventIDsToEvents(eventIDToEvent map[string]gomatrixserverlib.Event, stat
} }
stateBetween[roomID] = events stateBetween[roomID] = events
} }
return stateBetween, missingEvents
if len(missingEvents) > 0 {
// This happens when add_state_ids has an event ID which is not in the provided range.
// We need to explicitly fetch them.
allMissingEventIDs := []string{}
for _, missingEvIDs := range missingEvents {
allMissingEventIDs = append(allMissingEventIDs, missingEvIDs...)
}
evs, err := s.Events(txn, allMissingEventIDs)
if err != nil {
return nil, err
}
// we know we got them all otherwise an error would've been returned, so just loop the events
for _, ev := range evs {
roomID := ev.RoomID()
stateBetween[roomID] = append(stateBetween[roomID], ev)
}
}
return stateBetween, nil
} }
// MaxID returns the ID of the last inserted event in this table. 'txn' is optional. If it is not supplied, // MaxID returns the ID of the last inserted event in this table. 'txn' is optional. If it is not supplied,
@ -210,7 +224,13 @@ func (s *outputRoomEventsStatements) RecentEventsInRoom(txn *sql.Tx, roomID stri
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
return rowsToEvents(rows) events, err := rowsToEvents(rows)
if err != nil {
return nil, err
}
// reverse the order because [0] is the newest event due to the ORDER BY in SQL-land. The reverse order makes [0] the oldest event,
// which is correct for /sync responses.
return reverseEvents(events), nil
} }
// Events returns the events for the given event IDs. Returns an error if any one of the event IDs given are missing // Events returns the events for the given event IDs. Returns an error if any one of the event IDs given are missing
@ -248,3 +268,10 @@ func rowsToEvents(rows *sql.Rows) ([]gomatrixserverlib.Event, error) {
} }
return result, nil return result, nil
} }
func reverseEvents(input []gomatrixserverlib.Event) (output []gomatrixserverlib.Event) {
for i := len(input) - 1; i >= 0; i-- {
output = append(output, input[i])
}
return
}