Skip to content
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

Make clear the thread root is not in the thread #1677

Merged
@@ -0,0 +1 @@
Clarify that thread roots are not considered within the thread.
20 changes: 10 additions & 10 deletions content/client-server-api/modules/push.md
Expand Up @@ -1070,16 +1070,16 @@ ahead), however if the `m.read.private` receipt were to be updated to
event D then the user has read up to D (the `m.read` receipt is now
behind the `m.read.private` receipt).

{{< added-in v="1.4" >}} When handling threaded read receipts, the server
is to partition the notification count to each thread (with the main timeline
being its own thread). To determine if an event is part of a thread the
server follows the [event relationship](#forming-relationships-between-events)
until it finds a thread root (as specified by the [threading module](#threading)),
however it is not recommended that the server traverse infinitely. Instead,
implementations are encouraged to do a maximum of 3 hops to find a thread
before deciding that the event does not belong to a thread. This is primarily
to ensure that future events, like `m.reaction`, are correctly considered
"part of" a given thread.
{{< added-in v="1.4" >}} When handling threaded read receipts, the server is to
partition the notification count to each thread (with the main timeline being
its own thread). To determine if an event is part of a thread the server follows
the [event relationship](#forming-relationships-between-events) until it finds a
thread root via an `m.thread` relation (as specified by the [threading
module](#threading)), however it is not recommended that the server traverse
infinitely. Instead, implementations are encouraged to do a maximum of 3 hops to
find a thread before deciding that the event does not belong to a thread. This
is primarily to ensure that future events, like `m.reaction`, are correctly
considered "part of" a given thread.

#### Server behaviour

Expand Down
26 changes: 16 additions & 10 deletions content/client-server-api/modules/receipts.md
Expand Up @@ -137,16 +137,22 @@ either a thread root's event ID or `main` for the main timeline.

Threading introduces a concept of multiple conversations being held in the same
room and thus deserve their own read receipts and notification counts. An event is
considered to be "in a thread" if it meets any of the following criteria:
* It has a `rel_type` of `m.thread`.
* It has child events with a `rel_type` of `m.thread` (in which case it'd be the
thread root).
* Following the event relationships, it has a parent event which qualifies for
one of the above. Implementations should not recurse infinitely, though: a
maximum of 3 hops is recommended to cover indirect relationships.

Events not in a thread but still in the room are considered to be part of the
"main timeline", or a special thread with an ID of `main`.
considered to be "in a thread" if:

* It has a rel_type of m.thread, or
* It has a parent event with this rel_type, or a parent of a parent, or further
up the chain of relations. (Implementations should not recurse to arbitrary
depth: a maximum of 3 hops is recommended to cover indirect relationships.)
andybalaam marked this conversation as resolved.
Show resolved Hide resolved

Events not in a thread but still in the room are considered to be in the "main
timeline". Threaded receipts for the main timeine use a special thread ID of
andybalaam marked this conversation as resolved.
Show resolved Hide resolved
`main`.
andybalaam marked this conversation as resolved.
Show resolved Hide resolved

Thread roots are considered to be in the main timeline, as are events that are
related to a thread root via non-thread relations. Note that clients providing a
single-thread view will probably want to include thread roots and some of their
child events (e.g. reactions) in that view, even though from a receipt point of
view they are not part of that thread.
andybalaam marked this conversation as resolved.
Show resolved Hide resolved

The following is an example DAG for a room, with dotted lines showing event
relationships and solid lines showing topological ordering.
Expand Down
10 changes: 5 additions & 5 deletions content/client-server-api/modules/threading.md
Expand Up @@ -12,11 +12,11 @@ as by providing some context to what is going on in the thread but keeping the f
history behind a disclosure.

Threads are established using a `rel_type` of `m.thread` and reference the
*thread root* (the first event in a thread). It is not possible to create a
thread from an event which itself is the child of an event relationship (i.e.,
one with an `m.relates_to` property). It is therefore also not possible to nest
threads. All events in a thread reference the thread root instead of the
most recent message, unlike rich reply chains.
*thread root*. It is not possible to create a thread from an event which itself
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've now lost the definition of a "thread root" here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Attempted a definition in 058e97e . I removed the original definition because it was not accurate (because it said the thread root was in the thread, which it is not).

is the child of an event relationship (i.e., one with an `m.relates_to`
property). It is therefore also not possible to nest threads. All events in a
thread reference the thread root instead of the most recent message, unlike rich
reply chains.
andybalaam marked this conversation as resolved.
Show resolved Hide resolved

As a worked example, the following represents a thread and how it would be formed:

Expand Down