Skip to content

Commit 9d80dcb

Browse files
clokepturt2liveara4n
authored
MSC3773: Notifications for threads (#3773)
* Add initial MSC for notfications for threads. * No longer depends on MSC3664. * Fix events in diagram. * Major simplification. * Add missing words. * Add a note about reactions. * Clarify homeserver behavior when processing push rules. * Link to a spec version instead of latest. Co-authored-by: Travis Ralston <[email protected]> * Update 3773-notifications-for-threads.md typoe * Clarify wording. * Update how homeservers are to partition threads. Co-authored-by: Travis Ralston <[email protected]> Co-authored-by: Matthew Hodgson <[email protected]>
1 parent 4e1b562 commit 9d80dcb

File tree

1 file changed

+162
-0
lines changed

1 file changed

+162
-0
lines changed

Diff for: proposals/3773-notifications-for-threads.md

+162
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
# MSC3773: Notifications for threads
2+
3+
Since the unread notification count does not consider threads, a client is unable
4+
to separate the unread message counts into threads (as defined by
5+
[MSC3440](https://github.com/matrix-org/matrix-doc/pull/3440))
6+
without iterating over every missing message. Without this, clients are unable to:
7+
8+
* Let users know that a thread has new messages since they last read it.
9+
* Accurately display a count of unread messages in a room (or a thread).
10+
11+
## Proposal
12+
13+
### Modification to push rule processing
14+
15+
When an event which is part of a thread matches a push rule which results in a
16+
`notify` action then the homeserver should partition the resulting notification
17+
count per-thread. (This is needed for the
18+
[proposed `/sync` changes](#unread-thread-notifications-in-the-sync-response)).
19+
20+
It is recommended that at least 3 relations are traversed when attempting to
21+
find a thread, implementations should be careful to not infinitely recurse.[^1]
22+
23+
Similar behavior should be applied for an event which results in `notify` action
24+
with a `highlight` tweak set.
25+
26+
This MSC does not propose any changes to the payload sent to push gateways.
27+
28+
### Unread thread notifications in the sync response
29+
30+
Threaded clients can opt into receiving unread thread notifications by passing
31+
a new `unread_thread_notifications` parameter
32+
[as part of the `RoomEventFilter`](https://spec.matrix.org/v1.2/client-server-api/#filtering).
33+
(This is [similar to `lazy_load_members`](https://spec.matrix.org/v1.2/client-server-api/#lazy-loading-room-members),
34+
but only applies to the `/sync` endpoint.):
35+
36+
* `unread_thread_notifications`: If `true`, enables partitioning of unread notification
37+
counts by thread. Defaults to false.
38+
39+
If this flag is set to `true`, for each ["Joined Room" in the `/sync` response](https://spec.matrix.org/v1.3/client-server-api/#get_matrixclientv3sync)
40+
a new field is added:
41+
42+
* `unread_thread_notifications`: Counts of unread thread notifications for this
43+
room, an object which maps thread ID (the parent event ID) to
44+
`Unread Notification Counts`.
45+
46+
Additionally, the `unread_notifications` dictionary is modified to only include
47+
unread notifications from events which are not part of a thread.
48+
49+
An example of a joined room from a sync response:
50+
51+
```json5
52+
{
53+
"account_data": {
54+
// ...
55+
},
56+
"ephemeral": {
57+
// ...
58+
},
59+
"state": {
60+
// ...
61+
},
62+
"summary": {
63+
// ...
64+
},
65+
"timeline": {
66+
"events": [
67+
{
68+
"event_id": "$143273582443PhrSn:example.org",
69+
// other fields ...
70+
},
71+
{
72+
"event_id": "$SGNxGPGUopcPBUoTTL:example.org",
73+
"m.relates_to": {
74+
"event_id": "$143273582443PhrSn:example.org",
75+
"rel_type": "m.thread"
76+
}
77+
// other fields ...
78+
}
79+
]
80+
},
81+
"unread_notifications": {
82+
"highlight_count": 2,
83+
"notification_count": 18
84+
},
85+
"unread_thread_notifications": {
86+
"$143273582443PhrSn:example.org": {
87+
"highlight_count": 0,
88+
"notification_count": 1
89+
}
90+
}
91+
}
92+
```
93+
94+
## Potential issues
95+
96+
### Scalability
97+
98+
Rooms with many unread threads could cause some downsides:
99+
100+
* The size of the `/sync` response would increase without bound.
101+
* The effort to generate and process the receipts for each room would increase
102+
without bound.
103+
104+
This is not dissimilar to rooms which are never read, however, as their unread
105+
counts are continually tracked and returned as part of the `/sync` response.
106+
107+
### Clearing unread notifications
108+
109+
This MSC does not attempt to modify how unread notifications (for a thread or
110+
otherwise) are cleared. It currently assumes the rules set forth by
111+
[read receipts](https://spec.matrix.org/v1.3/client-server-api/#receiving-notifications)
112+
still apply. This will cause some flakiness with unread notifications, as the current
113+
receipt infrastructure assumes that a room's timeline is linear, which is no
114+
longer true.
115+
116+
[MSC3771](https://github.com/matrix-org/matrix-spec-proposals/pull/3771) is a
117+
potential solution for this.
118+
119+
## Alternatives
120+
121+
### Using push rules
122+
123+
It might seem that a new push rule `action` (or `tweak`) should be used to control
124+
the behavior of whether an event generates a notification for a thread or the
125+
room itself. There are issues with either approach though:
126+
127+
A new `action` (e.g. `notify_thread`) would mean that additional logic would
128+
need to be defined and added for events which aren't part of a thread but attempt
129+
to use this action. It also conflicts with [MSC3768](https://github.com/matrix-org/matrix-spec-proposals/pull/3768),
130+
which attempts to define another `action` which should also work fine for threads.
131+
132+
A new `tweak` (e.g. `threaded`) was discarded as an option since there is no need to
133+
pass this through to the push server, which is at odds with the current `tweaks`
134+
mechanism.
135+
136+
Regardless, the main issue with using push rules is that it becomes necessary to
137+
define rules which match threaded events. Whenever adding a new rule, matching rules
138+
would need to be added, but as a thread-specific version.
139+
140+
## Security considerations
141+
142+
N/A
143+
144+
## Unstable prefix
145+
146+
While this feature is in development the following unstable prefixes should be used:
147+
148+
* `unread_thread_notifications` --> `org.matrix.msc3773.unread_thread_notifications`
149+
150+
To detect server support, clients can either rely on the spec version (when stable)
151+
or the presence of a `org.matrix.msc3773` flag in `unstable_features` on `/versions`.
152+
153+
## Dependencies
154+
155+
N/A
156+
157+
[^1]: Three relations is relatively arbitrary, but is meant to cover an edit or
158+
reaction to a thread (to an event with no relations, i.e. the root of a thread):
159+
`A<--[m.thread]--B<--[m.annotation]--C`.
160+
With an additional leftover for future improvements. This is considered reasonable
161+
since threads cannot fork, edits cannot modify relation information, and generally
162+
annotations to annotations are ignored by user interfaces.

0 commit comments

Comments
 (0)