2021-05-13 16:25:42 +01:00
|
|
|
# sync-v3
|
2021-05-14 16:49:33 +01:00
|
|
|
|
|
|
|
Run an experimental sync v3 server using an existing Matrix account. This is possible because, for the most part,
|
|
|
|
v3 sync is a strict subset of v2 sync.
|
|
|
|
|
|
|
|
## Usage
|
|
|
|
|
2021-07-21 10:30:04 +01:00
|
|
|
```bash
|
2021-05-14 16:49:33 +01:00
|
|
|
$ createdb syncv3
|
|
|
|
$ go build ./cmd/syncv3
|
|
|
|
$ ./syncv3 -server "https://matrix-client.matrix.org" -db "user=$(whoami) dbname=syncv3 sslmode=disable"
|
|
|
|
```
|
2021-07-21 10:30:04 +01:00
|
|
|
|
|
|
|
Then issue Sync v3 calls.
|
|
|
|
|
|
|
|
## API overview
|
|
|
|
|
|
|
|
Sync v3 is implemented used POST requests. The URI is mostly constant:
|
|
|
|
- `Authorization: Bearer MDA...` : The access token for your account. `?access_token=` is unsupported.
|
|
|
|
- `/_matrix/client/v3/sync` : The path. Constant.
|
|
|
|
- `?since=` : The sync v3 token. To begin a new sync session, don't supply a `since` value.
|
|
|
|
|
|
|
|
The body of the request consists of different streams:
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"typing": {
|
|
|
|
...
|
|
|
|
},
|
|
|
|
"room_members": {
|
|
|
|
...
|
|
|
|
},
|
|
|
|
"to_device": {
|
|
|
|
...
|
|
|
|
},
|
|
|
|
...
|
|
|
|
}
|
|
|
|
```
|
|
|
|
Specify as many streams as you are interested in. For example, if you are on a room member page for
|
|
|
|
Matrix HQ, you probably only need the `room_members` stream.
|
|
|
|
|
|
|
|
Each stream has request parameters which control what data gets returned, for example `typing` has
|
|
|
|
a `room_id` which specifies which room to track typing notifications in. These request parameters are
|
|
|
|
given inside the JSON object for the respective stream. For example:
|
|
|
|
```json
|
|
|
|
"typing": {
|
|
|
|
"room_id": "!foo:bar"
|
|
|
|
}
|
|
|
|
```
|
|
|
|
These parameters are "sticky" and are remembered across requests so you don't need to constantly add
|
|
|
|
them and use up needless bandwidth. The server remembers this by associating a unique *session ID* to the `since`
|
|
|
|
token returned, so make sure you keep using the same `since` token.
|
|
|
|
|
|
|
|
A session is created when a client calls sync v3 without a `since` token. Just like how a user can
|
|
|
|
have multiple devices, a device can have multiple sessions. `to_device` messages are only purged from
|
|
|
|
the server when ALL sessions for that device have received the message. This resolves a longstanding
|
|
|
|
iOS E2EE bug whereby a device has 2 sync streams which are implicitly racing with each other and
|
|
|
|
clearing `to_device` messages, when both streams actually want the message. Sessions can be deleted
|
|
|
|
at the whim of the server (e.g to save resources). When this happens, the response will be:
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"errcode": "M_UNKNOWN_SYNC_SESSION",
|
|
|
|
"error": "Session unknown or expired"
|
|
|
|
}
|
|
|
|
```
|
|
|
|
Clients MUST call `/sync` again without a `?since=` value when this happens in order to make a new session.
|
|
|
|
|
|
|
|
Responses are split stream-by-stream:
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"typing": {
|
|
|
|
"events": [ Typing EDUs ]
|
|
|
|
},
|
|
|
|
"room_members": {
|
|
|
|
"events": [ Room Member Events]
|
|
|
|
},
|
|
|
|
"next": "sync_v3_token"
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Some streams are paginatable. Paginatable streams accept a `p` JSON object which contains pagination
|
|
|
|
parameters. The `p` object looks like:
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"room_members": {
|
|
|
|
"p": {
|
|
|
|
"limit": 10,
|
|
|
|
"sort": "enum_value:_the_sort_order_varies_by_stream"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
Servers can also return a `p` JSON object in the stream response which contains the pagination
|
|
|
|
parameters it is going to use. This allows servers to restrict the response to conserve resources
|
|
|
|
(e.g. reducing the `limit` value, modifying the `sort` order if it's unknown). This is called
|
|
|
|
*negotiation* and is frequently used by streams.
|
|
|
|
|
|
|
|
When paginated streams are returned, the next page of results are contained within `p`:
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"room_members": {
|
|
|
|
"p": {
|
|
|
|
"next": "$token_to_use_for_next_page"
|
|
|
|
},
|
|
|
|
"events": [ Room Member Events ]
|
|
|
|
},
|
|
|
|
"next": "$token_to_use_to_get_new_events"
|
|
|
|
}
|
|
|
|
```
|
|
|
|
To visualise this, the value of `?since=` is a snapshot of the room, and `p.next` paginates through
|
|
|
|
this snapshot. This means that when paginating you MUST NOT advance your `?since=` value. Clients can
|
|
|
|
request the next page by specifying `since` inside `p`:
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"room_members": {
|
|
|
|
"p": {
|
|
|
|
"since": "$token_from_p_next"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
Clients are not required to paginate through all entries in a paginated stream. If you are only interested
|
|
|
|
in the first 5 room members for example, then you can set `limit: 5` and ignore `p.next`. In order to differentiate
|
|
|
|
clients which are keeping up-to-date with room members and those who are just interested in the first page
|
|
|
|
of results, clients MUST specify `p.since = "1"` to indicate the first page of results. This makes `"1"` a
|
|
|
|
sentinel constant value in pagination to indicate "the first page of results". If you don't do this, the server
|
2021-07-21 12:12:57 +01:00
|
|
|
will just send back deltas from the last `since` value, which won't necessarily contain the first 5 members
|
|
|
|
of your chosen sort order (e.g alphabetically).
|
2021-07-21 10:30:04 +01:00
|
|
|
|
|
|
|
## Streams
|
|
|
|
|
|
|
|
### Typing Stream
|
|
|
|
|
2021-07-21 12:12:57 +01:00
|
|
|
Request Parameters:
|
|
|
|
- `room_id` (string): The room ID to track typing notifications in.
|
|
|
|
|
|
|
|
Response fields:
|
|
|
|
- `events` ([]EDU): A list of typing EDUs.
|
2021-07-21 10:30:04 +01:00
|
|
|
|
|
|
|
### To Device Stream
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
|
|
|
### Room Member Stream
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
|
|
|
### Room Stream
|
|
|
|
|
|
|
|
TODO
|
|
|
|
|
|
|
|
### Room List Stream
|
|
|
|
|
|
|
|
TODO
|