mirror of
https://github.com/hoernschen/dendrite.git
synced 2024-12-29 08:18:27 +00:00
Handle case where we get no events from the database and prevent end token < 1
This commit is contained in:
parent
89aeb21ef7
commit
38475d1489
3 changed files with 125 additions and 38 deletions
|
@ -182,6 +182,40 @@ func retrieveEvents(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var backwardExtremity bool
|
||||||
|
var events []gomatrixserverlib.Event
|
||||||
|
|
||||||
|
// There can be two reasons for streamEvents to be empty: either we've
|
||||||
|
// reached the oldest event in the room (or the most recent one, depending
|
||||||
|
// on the ordering), or we've reached a backward extremity.
|
||||||
|
if len(streamEvents) == 0 {
|
||||||
|
var evs []storage.StreamEvent
|
||||||
|
var laterPosition types.StreamPosition
|
||||||
|
if backwardOrdering {
|
||||||
|
laterPosition = from.Position + 1
|
||||||
|
} else {
|
||||||
|
laterPosition = to.Position + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
evs, err = db.EventsAtTopologicalPosition(ctx, roomID, laterPosition)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
backwardExtremity, err = containsBackwardExtremity(ctx, db, evs, backwardOrdering)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if backwardExtremity {
|
||||||
|
events, err = backfill(ctx, db, roomID, evs[0].EventID(), limit, queryAPI, cfg, federation)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return []gomatrixserverlib.ClientEvent{}, from, to, nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
// Check if we have enough events.
|
// Check if we have enough events.
|
||||||
isSetLargeEnough := true
|
isSetLargeEnough := true
|
||||||
if len(streamEvents) < limit {
|
if len(streamEvents) < limit {
|
||||||
|
@ -197,15 +231,13 @@ func retrieveEvents(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the slice contains a backward extremity.
|
// Check if the slice contains a backward extremity.
|
||||||
backwardExtremity, err := containsBackwardExtremity(
|
backwardExtremity, err = containsBackwardExtremity(
|
||||||
ctx, db, streamEvents, backwardOrdering,
|
ctx, db, streamEvents, backwardOrdering,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var events []gomatrixserverlib.Event
|
|
||||||
|
|
||||||
// Backfill is needed if we've reached a backward extremity and need more
|
// Backfill is needed if we've reached a backward extremity and need more
|
||||||
// events. It's only needed if the direction is backward.
|
// events. It's only needed if the direction is backward.
|
||||||
if backwardExtremity && !isSetLargeEnough && backwardOrdering {
|
if backwardExtremity && !isSetLargeEnough && backwardOrdering {
|
||||||
|
@ -225,6 +257,8 @@ func retrieveEvents(
|
||||||
|
|
||||||
// Append the events ve previously retrieved locally.
|
// Append the events ve previously retrieved locally.
|
||||||
events = append(events, storage.StreamEventsToEvents(nil, streamEvents)...)
|
events = append(events, storage.StreamEventsToEvents(nil, streamEvents)...)
|
||||||
|
}
|
||||||
|
|
||||||
// Sort the events to ensure we send them in the right order. We currently
|
// Sort the events to ensure we send them in the right order. We currently
|
||||||
// do that based on the event's timestamp.
|
// do that based on the event's timestamp.
|
||||||
if backwardOrdering {
|
if backwardOrdering {
|
||||||
|
@ -250,6 +284,10 @@ func retrieveEvents(
|
||||||
types.PaginationTokenTypeTopology, streamEvents[len(streamEvents)-1].StreamPosition,
|
types.PaginationTokenTypeTopology, streamEvents[len(streamEvents)-1].StreamPosition,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if end.Position == types.StreamPosition(0) {
|
||||||
|
end.Position = types.StreamPosition(1)
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,7 +324,7 @@ func containsBackwardExtremity(
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
// Check if we have all of the events we requested. If not, it means we've
|
// Check if we have all of the events we requested. If not, it means we've
|
||||||
// reached a backard extremity.
|
// reached a backward extremity.
|
||||||
var eventInDB bool
|
var eventInDB bool
|
||||||
var id string
|
var id string
|
||||||
// Iterate over the IDs we used in the request.
|
// Iterate over the IDs we used in the request.
|
||||||
|
|
|
@ -59,12 +59,17 @@ const selectMaxPositionInTopologySQL = "" +
|
||||||
"SELECT MAX(topological_position) FROM syncapi_output_room_events_topology" +
|
"SELECT MAX(topological_position) FROM syncapi_output_room_events_topology" +
|
||||||
" WHERE room_id = $1"
|
" WHERE room_id = $1"
|
||||||
|
|
||||||
|
const selectEventIDsFromPositionSQL = "" +
|
||||||
|
"SELECT event_id FROM syncapi_output_room_events_topology" +
|
||||||
|
" WHERE room_id = $1 AND topological_position = $2"
|
||||||
|
|
||||||
type outputRoomEventsTopologyStatements struct {
|
type outputRoomEventsTopologyStatements struct {
|
||||||
insertEventInTopologyStmt *sql.Stmt
|
insertEventInTopologyStmt *sql.Stmt
|
||||||
selectEventIDsInRangeASCStmt *sql.Stmt
|
selectEventIDsInRangeASCStmt *sql.Stmt
|
||||||
selectEventIDsInRangeDESCStmt *sql.Stmt
|
selectEventIDsInRangeDESCStmt *sql.Stmt
|
||||||
selectPositionInTopologyStmt *sql.Stmt
|
selectPositionInTopologyStmt *sql.Stmt
|
||||||
selectMaxPositionInTopologyStmt *sql.Stmt
|
selectMaxPositionInTopologyStmt *sql.Stmt
|
||||||
|
selectEventIDsFromPositionStmt *sql.Stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *outputRoomEventsTopologyStatements) prepare(db *sql.DB) (err error) {
|
func (s *outputRoomEventsTopologyStatements) prepare(db *sql.DB) (err error) {
|
||||||
|
@ -87,6 +92,9 @@ func (s *outputRoomEventsTopologyStatements) prepare(db *sql.DB) (err error) {
|
||||||
if s.selectMaxPositionInTopologyStmt, err = db.Prepare(selectMaxPositionInTopologySQL); err != nil {
|
if s.selectMaxPositionInTopologyStmt, err = db.Prepare(selectMaxPositionInTopologySQL); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if s.selectEventIDsFromPositionStmt, err = db.Prepare(selectEventIDsFromPositionSQL); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,3 +161,27 @@ func (s *outputRoomEventsTopologyStatements) selectMaxPositionInTopology(
|
||||||
err = s.selectMaxPositionInTopologyStmt.QueryRowContext(ctx, roomID).Scan(&pos)
|
err = s.selectMaxPositionInTopologyStmt.QueryRowContext(ctx, roomID).Scan(&pos)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// selectEventIDsFromPosition returns the IDs of all events that have a given
|
||||||
|
// position in the topology of a given room.
|
||||||
|
func (s *outputRoomEventsTopologyStatements) selectEventIDsFromPosition(
|
||||||
|
ctx context.Context, roomID string, pos types.StreamPosition,
|
||||||
|
) (eventIDs []string, err error) {
|
||||||
|
// Query the event IDs.
|
||||||
|
rows, err := s.selectEventIDsFromPositionStmt.QueryContext(ctx, roomID, pos)
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
// If no event matched the request, return an empty slice.
|
||||||
|
return []string{}, nil
|
||||||
|
} else if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Return the IDs.
|
||||||
|
var eventID string
|
||||||
|
for rows.Next() {
|
||||||
|
if err = rows.Scan(&eventID); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
eventIDs = append(eventIDs, eventID)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -269,6 +269,19 @@ func (d *SyncServerDatabase) MaxTopologicalPosition(
|
||||||
return d.topology.selectMaxPositionInTopology(ctx, roomID)
|
return d.topology.selectMaxPositionInTopology(ctx, roomID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EventsAtTopologicalPosition returns all of the events matching a given
|
||||||
|
// position in the topology of a given room.
|
||||||
|
func (d *SyncServerDatabase) EventsAtTopologicalPosition(
|
||||||
|
ctx context.Context, roomID string, pos types.StreamPosition,
|
||||||
|
) ([]StreamEvent, error) {
|
||||||
|
eIDs, err := d.topology.selectEventIDsFromPosition(ctx, roomID, pos)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return d.events.selectEvents(ctx, nil, eIDs)
|
||||||
|
}
|
||||||
|
|
||||||
// SyncStreamPosition returns the latest position in the sync stream. Returns 0 if there are no events yet.
|
// SyncStreamPosition returns the latest position in the sync stream. Returns 0 if there are no events yet.
|
||||||
func (d *SyncServerDatabase) SyncStreamPosition(ctx context.Context) (types.StreamPosition, error) {
|
func (d *SyncServerDatabase) SyncStreamPosition(ctx context.Context) (types.StreamPosition, error) {
|
||||||
return d.syncStreamPositionTx(ctx, nil)
|
return d.syncStreamPositionTx(ctx, nil)
|
||||||
|
@ -397,6 +410,8 @@ func (d *SyncServerDatabase) CompleteSync(
|
||||||
}
|
}
|
||||||
if backwardTopologyPos-1 <= 0 {
|
if backwardTopologyPos-1 <= 0 {
|
||||||
backwardTopologyPos = types.StreamPosition(1)
|
backwardTopologyPos = types.StreamPosition(1)
|
||||||
|
} else {
|
||||||
|
backwardTopologyPos = backwardTopologyPos - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't include a device here as we don't need to send down
|
// We don't include a device here as we don't need to send down
|
||||||
|
@ -405,7 +420,7 @@ func (d *SyncServerDatabase) CompleteSync(
|
||||||
stateEvents = removeDuplicates(stateEvents, recentEvents)
|
stateEvents = removeDuplicates(stateEvents, recentEvents)
|
||||||
jr := types.NewJoinResponse()
|
jr := types.NewJoinResponse()
|
||||||
jr.Timeline.PrevBatch = types.NewPaginationTokenFromTypeAndPosition(
|
jr.Timeline.PrevBatch = types.NewPaginationTokenFromTypeAndPosition(
|
||||||
types.PaginationTokenTypeTopology, backwardTopologyPos-1,
|
types.PaginationTokenTypeTopology, backwardTopologyPos,
|
||||||
).String()
|
).String()
|
||||||
jr.Timeline.Events = gomatrixserverlib.ToClientEvents(recentEvents, gomatrixserverlib.FormatSync)
|
jr.Timeline.Events = gomatrixserverlib.ToClientEvents(recentEvents, gomatrixserverlib.FormatSync)
|
||||||
jr.Timeline.Limited = true
|
jr.Timeline.Limited = true
|
||||||
|
@ -542,6 +557,8 @@ func (d *SyncServerDatabase) addRoomDeltaToResponse(
|
||||||
}
|
}
|
||||||
if backwardTopologyPos-1 <= 0 {
|
if backwardTopologyPos-1 <= 0 {
|
||||||
backwardTopologyPos = types.StreamPosition(1)
|
backwardTopologyPos = types.StreamPosition(1)
|
||||||
|
} else {
|
||||||
|
backwardTopologyPos = backwardTopologyPos - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
switch delta.membership {
|
switch delta.membership {
|
||||||
|
@ -549,7 +566,7 @@ func (d *SyncServerDatabase) addRoomDeltaToResponse(
|
||||||
jr := types.NewJoinResponse()
|
jr := types.NewJoinResponse()
|
||||||
|
|
||||||
jr.Timeline.PrevBatch = types.NewPaginationTokenFromTypeAndPosition(
|
jr.Timeline.PrevBatch = types.NewPaginationTokenFromTypeAndPosition(
|
||||||
types.PaginationTokenTypeTopology, backwardTopologyPos-1,
|
types.PaginationTokenTypeTopology, backwardTopologyPos,
|
||||||
).String()
|
).String()
|
||||||
jr.Timeline.Events = gomatrixserverlib.ToClientEvents(recentEvents, gomatrixserverlib.FormatSync)
|
jr.Timeline.Events = gomatrixserverlib.ToClientEvents(recentEvents, gomatrixserverlib.FormatSync)
|
||||||
jr.Timeline.Limited = false // TODO: if len(events) >= numRecents + 1 and then set limited:true
|
jr.Timeline.Limited = false // TODO: if len(events) >= numRecents + 1 and then set limited:true
|
||||||
|
@ -562,7 +579,7 @@ func (d *SyncServerDatabase) addRoomDeltaToResponse(
|
||||||
// no longer in the room.
|
// no longer in the room.
|
||||||
lr := types.NewLeaveResponse()
|
lr := types.NewLeaveResponse()
|
||||||
lr.Timeline.PrevBatch = types.NewPaginationTokenFromTypeAndPosition(
|
lr.Timeline.PrevBatch = types.NewPaginationTokenFromTypeAndPosition(
|
||||||
types.PaginationTokenTypeStream, backwardTopologyPos-1,
|
types.PaginationTokenTypeStream, backwardTopologyPos,
|
||||||
).String()
|
).String()
|
||||||
lr.Timeline.Events = gomatrixserverlib.ToClientEvents(recentEvents, gomatrixserverlib.FormatSync)
|
lr.Timeline.Events = gomatrixserverlib.ToClientEvents(recentEvents, gomatrixserverlib.FormatSync)
|
||||||
lr.Timeline.Limited = false // TODO: if len(events) >= numRecents + 1 and then set limited:true
|
lr.Timeline.Limited = false // TODO: if len(events) >= numRecents + 1 and then set limited:true
|
||||||
|
|
Loading…
Reference in a new issue