-
Notifications
You must be signed in to change notification settings - Fork 413
MSC3771: Read receipts for threads #3771
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
d330ba9
42d7daf
4c5382d
b5dac99
9445049
0e42ec3
e74c989
65fa009
1f0d6dd
03ac0e0
e3e677a
5540252
bbdb23e
2678f3c
ea77632
1c60533
347d332
5d73531
ef736e4
de7ba49
e1ab8e5
6e71034
2b857b7
d423542
ecbd6c4
1a5b5ae
7471923
b171a31
668c9de
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,158 @@ | ||
| # MSC3771: Read receipts for threads | ||
clokep marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| Currently, each room has a single read receipt per user. This is used to sync the | ||
clokep marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| read status of a room across clients and calculate the number of unread messages. | ||
|
|
||
| Unfortunately a client displaying threads may show a subset of a room's messages | ||
| at a time, causing the read receipt to be misleading. | ||
|
|
||
| This might better be described by an example. Given a room with the following | ||
| DAG of events (note that the dotted lines are a thread relation, as specified by | ||
| [MSC3440](https://github.com/matrix-org/matrix-doc/pull/3440)): | ||
|
|
||
| ```mermaid | ||
| flowchart RL | ||
| F-->E | ||
| E-->D | ||
| D-->C | ||
| C-->B | ||
| B-->A | ||
| C-.->A | ||
| E-.->A | ||
| ``` | ||
|
|
||
| A client might interpret this as: | ||
|
|
||
| ```mermaid | ||
| flowchart RL | ||
| subgraph Main timeline | ||
| D-->B | ||
| B-->A | ||
| F-->D | ||
| end | ||
| subgraph Thread timeline | ||
| C-->A | ||
| E-->C | ||
| end | ||
|
|
||
| style A fill:cyan,stroke:#333,stroke-width:2px | ||
| style F fill:orange,stroke:#333,stroke-width:2px | ||
| ``` | ||
|
|
||
| While viewing the "main" timeline of the room, a client might move the read | ||
| receipt from event `A` to event `F` without ever showing events `C` and `E`. The | ||
| user then reads the thread, the client has no way to mark `E` as read. | ||
|
|
||
| ## Proposal | ||
|
|
||
| This MSC proposes allowing the same receipt type to exist multiple times in a room | ||
| by adding a `threadId` parameter to reach receipt. | ||
|
|
||
| The [`/receipt`](https://spec.matrix.org/v1.2/client-server-api/#post_matrixclientv3roomsroomidreceiptreceipttypeeventid) | ||
| endpoint gains a new optional path part and becomes: | ||
|
|
||
| `POST /_matrix/client/v3/rooms/{roomId}/receipt/{receiptType}/{eventId}/{threadId}` | ||
|
|
||
| The `threadId` contains the thread that the read receipts belongs to (i.e. it should | ||
| match the `event_id` contained within the `m.relates_to` of the event represented | ||
| by `eventId`). | ||
|
|
||
| This updates the unique tuple for receipts from | ||
| `(room ID, user ID, receipt type)` to `(room ID, user ID, receipt type, threadId)`. | ||
| A missing (or empty) `threadId` refers to the "main" timeline (or events which are | ||
| not part of a thread). | ||
|
|
||
| Given a threaded message: | ||
|
|
||
| ```json | ||
| { | ||
| "event_id": "$thread_reply", | ||
| "room_id": "!room:example.org", | ||
| "content": { | ||
| "m.relates_to": { | ||
| "rel_type": "m.thread", | ||
| "event_id": "$thread_root" | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| A client could mark this as read by sending a request: | ||
|
|
||
| ``` | ||
| POST /_matrix/client/r0/rooms/!room:example.org/receipt/m.read/$thread_reply/$thread_root | ||
clokep marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| {} | ||
| ``` | ||
|
|
||
| This would then come down `/sync` for the user with other receipts, but with an | ||
| additional property in the body containing the thread ID: | ||
|
|
||
| ```json | ||
| { | ||
| "content": { | ||
| "$thread_reply": { | ||
| "m.read.thread.private": { | ||
clokep marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| "@rikj:jki.re": { | ||
| "ts": 1436451550453, | ||
| "threadId": "$thread_root" | ||
clokep marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
| } | ||
| }, | ||
| "room_id": "!jEsUZKDJdhlrceRyVU:example.org", | ||
| "type": "m.receipt" | ||
| } | ||
| ``` | ||
|
|
||
| ## Potential issues | ||
|
|
||
| For long-lived rooms or rooms with many threads there could be a significant number | ||
| of receipts. This has a few downsides: | ||
|
|
||
| * The size of the `/sync` response would increase without bound. | ||
| * The effort to generate and process the receipts for each room would increase | ||
| without bound. | ||
dbkr marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we have a plan for this? I don't think this is a viable situation long-term, though happy enough to punt it for now. (might be worth looping in people thinking about sliding sync?) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I don't have a long-term plan for this, no. I'm unsure how much of a concern this really is -- it would depend how often folks sending threaded read receipts, although "without bound" might have been a bit of hyperbole. I think from this we'll end up processing more receipts, but they'll be over smaller chunks of events, so I hope the actual effort isn't too much worse. |
||
|
|
||
| [MSC2285](https://github.com/matrix-org/matrix-spec-proposals/pull/2285) suggests | ||
| that the `/read_markers` endpoint should become a generic bulk receipt endpoint. | ||
| This is not compatible with the additional `threadId` parameter in this MSC. | ||
clokep marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ### Compatibility with unthreaded clients | ||
|
|
||
| When a user has both a client which is "unthreaded" and "threaded" then there | ||
| is a possibility for read receipts to be misrepresented when switching between | ||
| clients. Solutions to this problem are deemed out of scope of this MSC. | ||
|
|
||
| ## Alternatives | ||
|
|
||
| Instead of adding the thread ID as a new path part, it could be added to the body | ||
clokep marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| of the receipt. There may be a small backwards compatibility benefit to this, but | ||
| it seems clearer to put it as part of the URL. | ||
|
|
||
| Instead of encoding the thread ID as an integral part of the receipt, the read | ||
| threads could be added to the body of the receipt. This could cause data | ||
| integrity issues if multiple clients attempt to update the receipt without first | ||
| reading it. | ||
|
|
||
| ## Security considerations | ||
|
|
||
| There is potential for abuse by allowing clients to specify a unique `threadId`. | ||
| A mitigation could be to ensure that the receipt is related to an event of the | ||
| thread, ensuring that each thread only has a single receipt. | ||
|
|
||
| ## Future extensions | ||
|
|
||
| Future extensions will tackle how the thread read receipts impact notification counts. | ||
|
|
||
| ## Unstable prefix | ||
|
|
||
| To detect server support, clients can either rely on the spec version (when stable) | ||
| or the presence of a `org.matrix.msc3771` flag in `unstable_features` on `/versions`. | ||
|
|
||
| ## Dependencies | ||
|
|
||
| This MSC depends on the following MSCs, which have been accepted into the spec, | ||
| but have yet to be released: | ||
|
|
||
| * [MSC3440](https://github.com/matrix-org/matrix-spec-proposals/pull/3440): Threading via `m.thread` relation | ||
Uh oh!
There was an error while loading. Please reload this page.