-
Notifications
You must be signed in to change notification settings - Fork 385
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
MSC3856: Threads List API #3856
Changes from 13 commits
805c0b2
be44a1f
5af798d
89a6146
d51209a
8ef8232
75afe34
f23162d
dd11005
a153ac0
6002d81
baa6705
78ee0e0
9f67a7c
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,187 @@ | ||
# MSC3856: Threads List API | ||
|
||
An endpoint specific to listing the threads in a room is proposed to solve two | ||
client problems: | ||
|
||
1. Clients wish to display threads ordered by the most recently active. | ||
2. Clients wish to display a list of threads the user has participated in. | ||
|
||
It is currently difficult for clients to sort threads by the most recently | ||
responded to. Clients can use the [`/messages`](https://spec.matrix.org/v1.3/client-server-api/#get_matrixclientv3roomsroomidmessages) | ||
API with a filter of `"related_by_rel_types": ["m.thread"]` (as defined in | ||
[MSC3440](/~https://github.com/matrix-org/matrix-spec-proposals/blob/main/proposals/3440-threading-via-relations.md#fetch-all-threads-in-a-room)) | ||
to fetch the list of threads in a room. This returns the root thread events in | ||
topological order of those events (either forwards or backwards depending on the | ||
`dir` parameter). | ||
|
||
Each event also includes bundled aggregation, which will include the latest | ||
event in each thread. | ||
|
||
In order to sort threads by the latest event in that thread clients must | ||
paginate through all of the threads in the room, inspect the latest event from | ||
the bundled aggregations and attempt to sort them. This can require many round | ||
trips to the server and is wasteful for both the client and server. | ||
|
||
Unfortunately even when a client has all the threads in a room is not able to accurately | ||
clokep marked this conversation as resolved.
Show resolved
Hide resolved
|
||
sort the threads since the client lacks the proper topological ordering of events. (The | ||
closest available information is the `age` or `origin_server_ts` of the events, but this | ||
is not always correct.) | ||
|
||
Additionally, it is currently not possible for a client to query for threads that | ||
the user has participated in, as defined in | ||
[MSC3440](/~https://github.com/matrix-org/matrix-spec-proposals/blob/main/proposals/3440-threading-via-relations.md#event-format): | ||
|
||
> The user has participated if: | ||
> | ||
> * They created the current event. | ||
> * They created an event with a m.thread relation targeting the current event. | ||
|
||
Currently, clients add the requesting user's MXID to the `related_by_senders` filter | ||
(as defined in | ||
[MSC3440](/~https://github.com/matrix-org/matrix-spec-proposals/blob/main/proposals/3440-threading-via-relations.md#fetch-all-threads-in-a-room)), | ||
e.g. `"related_by_senders":["@alice:example.com"]`, but this results in missing | ||
threads where the user sent the root message and has not yet replied. | ||
|
||
## Proposal | ||
|
||
### Client-Server endpoint | ||
|
||
A new endpoint is proposed to query for threads in a room. This endpoint requires | ||
authentication and is subject to rate-limiting. | ||
|
||
The endpoint returns events, which represent thread roots and includes | ||
[bundled aggregations](https://spec.matrix.org/v1.3/client-server-api/#aggregations) | ||
in the response (which includes the "latest event" of each thread, see | ||
[MSC3440](/~https://github.com/matrix-org/matrix-spec-proposals/blob/main/proposals/3440-threading-via-relations.md#event-format) | ||
for the format of bundled aggregations of threads). | ||
|
||
The returned events are ordered by the latest event of each thread. | ||
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. Latest by what metric? 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. This is meant to be rather vague and it is further defined below under
Note that this is mostly copied from the
|
||
|
||
#### Request format | ||
|
||
``` | ||
GET /_matrix/client/v1/rooms/{roomId}/threads | ||
``` | ||
|
||
Query Parameters: | ||
|
||
* **`include`**: `enum` | ||
|
||
Whether to include all thread roots in the room or only thread roots which the | ||
user has participated in, meaning that the user has created the root event of | ||
the thread or replied to the thread (they have created an event with a `m.thread` | ||
relation targeting the root event). | ||
|
||
One of `[all, participated]`. Defaults to `all`. | ||
* **`from`**: `string` | ||
clokep marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
The token to start returning events from. This token can be obtained from an | ||
`next_batch` token returned by a previous request to this endpoint. | ||
|
||
If it is not provided, the homeserver shall return a list of thread roots starting | ||
from the most recent visible event in the room history for the requesting user. | ||
* **`limit`**: Optional: a client-defined limit to the maximum | ||
number of threads to return per page. Must be an integer greater than zero. | ||
|
||
Server implementations should impose a maximum value to avoid resource | ||
exhaustion. | ||
|
||
#### Response format | ||
|
||
* **`chunk`**: [`[ClientEvent]`](https://spec.matrix.org/v1.3/client-server-api/#room-event-format) **Required** | ||
|
||
A list of room of events which are the root event of threads. Each event includes | ||
bundled aggregations. The order is chronological by the latest event in that thread. | ||
* **`next_batch`**: `string` | ||
|
||
A token which can be passed back to this endpoint to request additional events. | ||
|
||
If no further events are available (either because we have reached the start | ||
of the timeline, or because the user does not have permission to see any more | ||
events), this property is omitted from the response. | ||
|
||
If the sender of an event is ignored by the current user the results are modified | ||
slightly. This has two situations: | ||
|
||
1. If the ignored user sent the root thread event: the server should return the | ||
redacted form of the root event, but otherwise act as normal. This matches the | ||
information that a client would have if the threads list was aggregated locally | ||
(and generally matches the behavior if a thread root is unavailable, e.g. due | ||
to room history visibility). | ||
2. If the ignored user sent the latest thread event: the server should treat the | ||
latest event as not existing and replace it with the latest event from a | ||
non-ignored user; with the caveat that the ordering of the threads is not | ||
re-arranged due to this replacement. | ||
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 wonder how clients can match the above logic in their sync loops. Suppose I have a list of threads that I want to maintain. I load the latest few using 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 think it would be easy for clients to match. Unfortunately having the threads appear in the proper spot in pagination was quite difficult (unless you're constantly re-evaluating ignored users). It might be more doable now that we're not using |
||
|
||
#### Example request: | ||
|
||
``` | ||
GET /_matrix/client/v1/rooms/%21ol19s%3Ableecker.street/threads? | ||
limit=25& | ||
include=participated | ||
``` | ||
|
||
#### Example response: | ||
|
||
```json | ||
{ | ||
"chunk": [ClientEvent], | ||
"next_batch": "..." | ||
} | ||
``` | ||
|
||
### MSC3440 Filtering | ||
|
||
This MSC replaces the [event filters added in MSC3440](/~https://github.com/matrix-org/matrix-spec-proposals/blob/main/proposals/3440-threading-via-relations.md#fetch-all-threads-in-a-room) | ||
(`related_by_rel_types` and `related_by_senders`) as the only known use-case is | ||
more efficiently solved by this MSC. | ||
|
||
## Potential issues | ||
|
||
None foreseen. | ||
|
||
## Alternatives | ||
clokep marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
### Reusing the `/messages` endpoint | ||
|
||
Additional parameters could be added to the `/messages` endpoint to control the | ||
ordering of the returned results. This would likely not be compatible with all | ||
the other options available on that endpoint. | ||
|
||
Keeping this a separate endpoint also gives the possibility of additional | ||
threads-specific filtering in the future. | ||
|
||
### MSC2836 Threading | ||
|
||
[MSC2836](/~https://github.com/matrix-org/matrix-spec-proposals/pull/2836) includes | ||
a generic `/event_relationships` endpoint, but it is overly complex for | ||
[MSC3440](/~https://github.com/matrix-org/matrix-doc/pull/3440)-style threads. | ||
|
||
MSC2836 attempts to solve a larger problem, including allowing for arbitrary | ||
branching of threads (and many levels of event relations). MSC3440 forbids creating | ||
threads off a threaded message, allowing for a simpler design. Additionally, the | ||
MSC2836 design is more computensively intensive for both clients and servers to | ||
clokep marked this conversation as resolved.
Show resolved
Hide resolved
|
||
implement due to the tree-like nature of the query. | ||
|
||
A benefit to the MSC2836 design is that it supports querying over federation for | ||
additional events related to the event in question. | ||
|
||
## Security considerations | ||
|
||
As with other endpoints that accept a `limit`, homeservers should apply a hard | ||
server-side maximum. | ||
|
||
## Future extensions | ||
|
||
It does not seem useful to be able to paginate in reverse order, i.e. starting with | ||
the thread which was least recently updated. If there becomes a future need of this | ||
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. For the record, 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. That's a good point, perhaps on mobile this would be quite useful. |
||
a `dir` parameter could be added which takes an enum value of `[f, b]` defaulting to | ||
`b` to maintain backwards compatibility with this proposal. | ||
|
||
## Unstable prefix | ||
|
||
The client-server API will be: `/_matrix/client/unstable/org.matrix.msc3856/rooms/{roomId}/threads` | ||
|
||
## Dependencies | ||
|
||
N/A |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does this work over federation as the local server may not have all the thread roots?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does not change any behavior there -- a server could backfill to fetch additional thread roots if it wanted to, but that seems rather implementation specific.