diff --git a/changelogs/client_server/newsfragments/1677.clarification b/changelogs/client_server/newsfragments/1677.clarification new file mode 100644 index 00000000..56c89af8 --- /dev/null +++ b/changelogs/client_server/newsfragments/1677.clarification @@ -0,0 +1 @@ +Clarify that thread roots are not considered within the thread. diff --git a/content/client-server-api/modules/push.md b/content/client-server-api/modules/push.md index 8a515d2f..c674bac9 100644 --- a/content/client-server-api/modules/push.md +++ b/content/client-server-api/modules/push.md @@ -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 diff --git a/content/client-server-api/modules/receipts.md b/content/client-server-api/modules/receipts.md index 8cd4e9f6..54c8c7cf 100644 --- a/content/client-server-api/modules/receipts.md +++ b/content/client-server-api/modules/receipts.md @@ -137,16 +137,20 @@ 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 +* Following the event relationships, it has a parent event which references + the thread root with a `rel_type` of `m.thread`. 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 in the "main +timeline". When referring to the main timeline as a thread (e.g. in receipts +and notifications counts) a special thread ID of `main` is used. + +Thread roots are considered to be in the main timeline, as are events that are +related to a thread root via non-thread relations. The following is an example DAG for a room, with dotted lines showing event relationships and solid lines showing topological ordering. diff --git a/content/client-server-api/modules/threading.md b/content/client-server-api/modules/threading.md index 04440a07..b6e11821 100644 --- a/content/client-server-api/modules/threading.md +++ b/content/client-server-api/modules/threading.md @@ -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* (the main timeline event to which the thread events refer). 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. As a worked example, the following represents a thread and how it would be formed: