Skip to content

Commit 36f8310

Browse files
committed
First draft of MSC4222
1 parent b76697e commit 36f8310

1 file changed

Lines changed: 181 additions & 0 deletions

File tree

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
# MSC4222: Adding `state_after` to sync v2
2+
3+
The current sync v2 API does not differentiate between state events in the timeline and updates to state, and so can
4+
cause the client's view of the current state of the room to diverge from the actual state of the room. This is
5+
particularly problematic for use-cases that rely on state being consistent between different clients.
6+
7+
This behavior stems from the fact that the clients update their view of the current state with state events that appear
8+
in the timeline. To handle gappy syncs, the `state` section includes state events that are from *before* the start of
9+
the timeline, and so are replaced by any matching state events in the timeline. This provides little opportunity for the
10+
server to ensure that the clients come to the correct conclusion about the current state of the room.
11+
12+
In [MSC4186 - Simplified Sliding Sync](https://github.com/matrix-org/matrix-spec-proposals/pull/4186) this problem is
13+
solved by the equivalent `required_state` section including all state changes between the previous sync and the end of
14+
the current sync, and clients do not update their view of state based on entries in the timeline.
15+
16+
17+
## Proposal
18+
19+
This change is gated behind the client adding a `?use_state_after=true` (the unstable name is
20+
`org.matrix.use_state_after`) query param.
21+
22+
When enabled, the Homeserver will **omit** the `state` section in the room response sections. This is replaced by
23+
`state_after` (the unstable field name is `org.matrix.state_after`), which will include all state changes between the
24+
previous sync and the *end* of the timeline section of the current sync. This is in contrast to the old `state` section
25+
that only included state changes between the previous sync and the *start* of the timeline section. Note that this does
26+
mean that a new state event will (likely) appear in both the timeline and state sections of the response.
27+
28+
This is basically the same as how state is returned in [MSC4186 - Simplified Sliding
29+
Sync](https://github.com/matrix-org/matrix-spec-proposals/pull/4186).
30+
31+
State events that appear in the timeline section **MUST NOT** update the current state. The current state **MUST** only be
32+
updated with the contents of `state_after`.
33+
34+
Clients can tell if the server supports this change by whether it returns a `state` or `state_after` section in the
35+
response.
36+
37+
### Examples
38+
39+
#### Example 1 \- Common case
40+
41+
Let’s take a look at the common case of a state event getting sent down an incremental sync, which is non-gappy.
42+
43+
<table>
44+
<tr><th>Previously</th><th>Proposed</th></tr>
45+
<tr>
46+
<td>
47+
48+
```json
49+
{
50+
"timeline": {
51+
"events": [ {
52+
"type": "org.matrix.example",
53+
"state_key": ""
54+
} ],
55+
"limited": false,
56+
},
57+
"state": {
58+
"events": []
59+
}
60+
}
61+
```
62+
63+
</td>
64+
<td>
65+
66+
```json
67+
{
68+
"timeline": {
69+
"events": [ {
70+
"type": "org.matrix.example",
71+
"state_key": ""
72+
} ],
73+
"limited": false,
74+
},
75+
"state_after": {
76+
"events": [ {
77+
"type": "org.matrix.example",
78+
"state_key": ""
79+
} ]
80+
}
81+
```
82+
83+
</td>
84+
</tr>
85+
</table>
86+
87+
> [!NOTE]
88+
> In the proposed API the state event comes down both in the timeline section *and* the state section.
89+
90+
91+
#### Example 2 - Receiving “outdated” state
92+
93+
Next, let’s look at what would happen if we receive a state event that does not take effect, i.e. that shouldn’t cause the client to update its state.
94+
95+
<table>
96+
<tr><th>Previously</th><th>Proposed</th></tr>
97+
<tr>
98+
<td>
99+
100+
```json
101+
{
102+
"timeline": {
103+
"events": [ {
104+
"type": "org.matrix.example",
105+
"state_key": ""
106+
} ],
107+
"limited": false,
108+
},
109+
"state": {
110+
"events": []
111+
}
112+
}
113+
```
114+
115+
</td>
116+
<td>
117+
118+
```json
119+
{
120+
"timeline": {
121+
"events": [ {
122+
"type": "org.matrix.example",
123+
"state_key": ""
124+
} ],
125+
"limited": false,
126+
},
127+
"state_after": {
128+
"events": []
129+
}
130+
}
131+
```
132+
133+
</td>
134+
</tr>
135+
</table>
136+
137+
> [!IMPORTANT]
138+
> Both responses are the same, but the client **MUST NOT** update its state with the event.
139+
140+
141+
## Potential issues
142+
143+
With the proposed API the common case for receiving a state update will cause the event to come down in both the
144+
`timeline` and `state` sections, potentially increasing bandwidth usage. However, it is common for the HTTP responses to
145+
be compressed, heavily reducing the impact of having duplicated data.
146+
147+
Clients will not be able to tell when a state change happened within the timeline. This was used by some clients to
148+
render e.g. display names of users at the time they sent the message (rather than their current display name), though
149+
e.g. Element clients have moved away from this UX. This behavior can be replicated in the same way that clients dealt
150+
with messages received via pagination (i.e. calling `/messages`), by walking the timeline backwards and inspecting the
151+
`unsigned.prev_state` field. While this can lead to incorrect results, this is no worse than the previous situation.
152+
153+
154+
## Alternatives
155+
156+
There are a number of ways of encoding the same information in different ways, for example the response could include
157+
both the `state` and a `state_delta` section, where `state_delta` would be any changes that needed to be applied to the
158+
client calculated state to correct it. However, since
159+
[MSC4186](https://github.com/matrix-org/matrix-spec-proposals/pull/4186) is likely to replace the sync v2 API, we may as
160+
well use the same mechanism. This also has the benefit of showing that the proposed API shape can be successfully
161+
implemented by clients.
162+
163+
We could also do nothing, and instead wait for [MSC4186](https://github.com/matrix-org/matrix-spec-proposals/pull/4186)
164+
(or equivalent) to land and for clients to update to it.
165+
166+
167+
## Security considerations
168+
169+
There are no security concerns with this proposal, as it simply encodes the same information sent do clients in a
170+
different way
171+
172+
## Unstable prefix
173+
174+
| Name | Stable prefix | Unstable prefix |
175+
| - | - | - |
176+
| Query param | `use_state_after` | `org.matrix.use_state_after` |
177+
| Room response field | `state_after` | `org.matrix.state_after` |
178+
179+
## Dependencies
180+
181+
None

0 commit comments

Comments
 (0)