From 801dc8d4bf6d7104d5740947804f449670a5dcbf Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Wed, 22 Nov 2023 10:35:53 +0000 Subject: [PATCH 1/8] Make clear the thread root is not in the thread Signed-off-by: Andy Balaam --- content/client-server-api/modules/push.md | 20 +++++++------- content/client-server-api/modules/receipts.md | 26 ++++++++++++------- .../client-server-api/modules/threading.md | 10 +++---- 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/content/client-server-api/modules/push.md b/content/client-server-api/modules/push.md index 8a515d2f5..c674bac94 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 8cd4e9f61..4731f910a 100644 --- a/content/client-server-api/modules/receipts.md +++ b/content/client-server-api/modules/receipts.md @@ -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.) + +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 +`main`. + +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. 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 04440a071..2d3abef5b 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*. 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: From d55f69220a9afba351e69fd1824f2b035d928bee Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Wed, 22 Nov 2023 10:53:17 +0000 Subject: [PATCH 2/8] Changlog entry for thread PR 1677 - thread roots not in thread --- changelogs/client_server/newsfragments/1677.clarification | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelogs/client_server/newsfragments/1677.clarification diff --git a/changelogs/client_server/newsfragments/1677.clarification b/changelogs/client_server/newsfragments/1677.clarification new file mode 100644 index 000000000..56c89af86 --- /dev/null +++ b/changelogs/client_server/newsfragments/1677.clarification @@ -0,0 +1 @@ +Clarify that thread roots are not considered within the thread. From 277f3192110e903a397939ebfa490e771803bed5 Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Mon, 27 Nov 2023 16:26:33 +0000 Subject: [PATCH 3/8] Fix typo --- content/client-server-api/modules/receipts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/client-server-api/modules/receipts.md b/content/client-server-api/modules/receipts.md index 4731f910a..fdd2def2a 100644 --- a/content/client-server-api/modules/receipts.md +++ b/content/client-server-api/modules/receipts.md @@ -145,7 +145,7 @@ considered to be "in a thread" if: depth: 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". Threaded receipts for the main timeine use a special thread ID of +timeline". Threaded receipts for the main timeline use a special thread ID of `main`. Thread roots are considered to be in the main timeline, as are events that are From ba4fd904b9f95cf307fd1b10bceb1119550dbd98 Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Mon, 27 Nov 2023 16:29:46 +0000 Subject: [PATCH 4/8] Add formatting for code values. Co-authored-by: Patrick Cloke --- content/client-server-api/modules/receipts.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/client-server-api/modules/receipts.md b/content/client-server-api/modules/receipts.md index fdd2def2a..74e2f1c38 100644 --- a/content/client-server-api/modules/receipts.md +++ b/content/client-server-api/modules/receipts.md @@ -139,8 +139,8 @@ 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 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 +* 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.) From 19a9446185674768070d1aeacae6977305987071 Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Mon, 27 Nov 2023 17:15:00 +0000 Subject: [PATCH 5/8] Reword main timeline ID paragraph --- content/client-server-api/modules/receipts.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/client-server-api/modules/receipts.md b/content/client-server-api/modules/receipts.md index 74e2f1c38..470c099bd 100644 --- a/content/client-server-api/modules/receipts.md +++ b/content/client-server-api/modules/receipts.md @@ -145,8 +145,8 @@ considered to be "in a thread" if: depth: 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". Threaded receipts for the main timeline use a special thread ID of -`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. Note that clients providing a From c8e39c10b7d50030282fa6184e93ce9fb4016276 Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Tue, 28 Nov 2023 11:22:28 +0000 Subject: [PATCH 6/8] Use close to the original wording for the 'recurse' part of the 'in the thread' definition --- content/client-server-api/modules/receipts.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/content/client-server-api/modules/receipts.md b/content/client-server-api/modules/receipts.md index 470c099bd..e32ab18e6 100644 --- a/content/client-server-api/modules/receipts.md +++ b/content/client-server-api/modules/receipts.md @@ -140,9 +140,10 @@ room and thus deserve their own read receipts and notification counts. An event 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.) +* 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 From 3c439d09f99ddc5cdf717bada581d141a8bbf744 Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Tue, 28 Nov 2023 11:24:50 +0000 Subject: [PATCH 7/8] Remove note about thread roots being displayed in a thread --- content/client-server-api/modules/receipts.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/content/client-server-api/modules/receipts.md b/content/client-server-api/modules/receipts.md index e32ab18e6..54c8c7cf4 100644 --- a/content/client-server-api/modules/receipts.md +++ b/content/client-server-api/modules/receipts.md @@ -150,10 +150,7 @@ 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. 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. +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. From 058e97e5f11971d1f9d508b7b90b8f02beae305a Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Tue, 28 Nov 2023 11:27:56 +0000 Subject: [PATCH 8/8] Define the thread root --- content/client-server-api/modules/threading.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/client-server-api/modules/threading.md b/content/client-server-api/modules/threading.md index 2d3abef5b..b6e118214 100644 --- a/content/client-server-api/modules/threading.md +++ b/content/client-server-api/modules/threading.md @@ -12,7 +12,7 @@ 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*. It is not possible to create a thread from an event which itself +*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