Closed kegsay closed 9 months ago
As requested, I'm going to quickly lay out how Synapse implements this currently.
There are two orderings Synapse uses, called "stream ordering" and "topological ordering" (which is a specific topological ordering). Once an event is persisted these orderings do not change.
There are also two types of tokens: stream tokens and topological tokens. These correspond with segmenting events based on the stream ordering and the topological ordering respectively.
The two requests that happen are:
/sync
which returns events in stream ordering and includes stream tokens for the start and end of the included set of events. The events returned are the latest N events based on stream ordering in the room./messages
which returns events in topological ordering and includes topological tokens for the start and end of the included set of events. You can specify either stream or topological tokens for the upper and lower bounds of requested events. The events returned are the latest N events based on topological ordering in the room, filtered by the tokens specified.The question is: if we use a stream token from the start of the timeline in /sync
to paginate via /messages
, do we see all events?
Let's say we do a /sync
and get a prev_batch
stream token of s
. When we do /messages
this will return the set of events ordered by topological ordering less than s
, greatest first. i.e. there is a topological token t
(corresponding to the first event /messages
returns) for which any event before t
will be returned by /messages
(except maybe if the event is after s
).
Given an arbitrary event E
in the room, what cases are there and will it turn up in subsequent /sync
or /messages
?
E
is after s
then it will come down /sync
, and we're done.E
is before t
then it will come down /messages
and we're done.t
there cannot be an event that is after t
but before s
, as t
is defined to be a token that returns all events before s
. i.e., E
must be in one of the two cases above.This is true for the case where we receive E
and then do the the pagination. What about the case where we have already started paginating from a previous /sync
request? For non-backfilled events then E
must by definition of stream ordering happen after s
, and so come down /sync
if there are no gaps. For the gappy sync case the client will have to paginate, but then the same rationale as above applies.
Based on random conversations, we want to make sure that clients cannot accidentally miss being told about events if an earlier event (earlier in the DAG) arrives interleaved with newer events.