Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Mark events as read using threaded read receipts from MSC3771 #13877

Merged
merged 42 commits into from Oct 4, 2022
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
9cb167c
Update filtering to include the thread notifications flag.
clokep Sep 8, 2022
8ac2f32
Ensure that the thread_id column is non-null and then require it to b…
clokep Sep 9, 2022
111fe57
Add infrastructure to pass notifications per thread.
clokep Sep 8, 2022
62aa85b
Calculate thread specific notification counts.
clokep Sep 8, 2022
cb679e2
Clarify comment.
clokep Sep 16, 2022
ba00c5f
Simplify handling of summaries with neither notifications or unread c…
clokep Sep 16, 2022
eb56567
Delete old push summaries.
clokep Sep 16, 2022
e6f97ec
Merge remote-tracking branch 'origin/develop' into clokep/threads-not…
clokep Sep 16, 2022
4f4711a
Merge remote-tracking branch 'origin/develop' into clokep/threads-not…
clokep Sep 19, 2022
8b63c5b
Fix postgres compatibility.
clokep Sep 19, 2022
c3783df
Merge remote-tracking branch 'origin/develop' into clokep/threads-not…
clokep Sep 20, 2022
c4f2d50
Create a constant for "main".
clokep Sep 20, 2022
6927e59
Reduce duplicated code.
clokep Sep 20, 2022
1d05975
Lint
clokep Sep 20, 2022
28b5a1f
Merge remote-tracking branch 'origin/develop' into clokep/threads-not…
clokep Sep 22, 2022
55d15a3
Threads must already be summarized between the stream orderings that …
clokep Sep 22, 2022
56c21e4
Don't delete empty push summaries.
clokep Sep 22, 2022
241b40c
Merge remote-tracking branch 'origin/develop' into clokep/threads-not…
clokep Sep 23, 2022
a04258f
Merge remote-tracking branch 'origin/develop' into clokep/threads-not…
clokep Sep 26, 2022
ddbb644
Merge remote-tracking branch 'origin/develop' into clokep/threads-not…
clokep Sep 27, 2022
f20620f
Update constraints and indexes now that thread ID is used.
clokep Sep 12, 2022
52b0a3d
Mark threads as read separately.
clokep Sep 22, 2022
fb50244
Use MAIN_TIMELINE constant in more places.
clokep Sep 28, 2022
79452e9
Merge remote-tracking branch 'origin/develop' into clokep/threads-not…
clokep Sep 28, 2022
b0d9008
Merge remote-tracking branch 'origin/develop' into clokep/threads-not…
clokep Sep 28, 2022
d6d7788
Combine logic for processing receipts.
clokep Sep 28, 2022
162bd8d
Expand comment and rename variables for clarity.
clokep Sep 28, 2022
e7b5421
Clarify comment.
clokep Sep 28, 2022
5f5e9ad
Improve docstrings.
clokep Sep 28, 2022
16a60b9
Rename function.
clokep Sep 28, 2022
f6a99c8
Lint
clokep Sep 28, 2022
f279a15
Merge remote-tracking branch 'origin/develop' into clokep/threads-not…
clokep Sep 29, 2022
ef37de2
Merge remote-tracking branch 'origin/clokep/threads-notif-2' into clo…
clokep Sep 29, 2022
6b2384d
Fix typo.
clokep Sep 29, 2022
041fe7f
Only attempt to find threaded receipts newer than the latest unthread…
clokep Sep 29, 2022
f416be9
Merge branch 'develop' into clokep/threads-notif-2
clokep Oct 4, 2022
0b1b432
Update for changes in develop.
clokep Oct 4, 2022
2322f8a
Merge remote-tracking branch 'origin/clokep/threads-notif-2' into clo…
clokep Oct 4, 2022
20ace0f
Update delta numbers.
clokep Oct 4, 2022
bd6c80c
Update background index numbers.
clokep Oct 4, 2022
09f36e9
Merge remote-tracking branch 'origin/clokep/threads-notif-2' into clo…
clokep Oct 4, 2022
377acc3
Merge remote-tracking branch 'origin/develop' into clokep/threads-not…
clokep Oct 4, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/13776.feature
@@ -0,0 +1 @@
Experimental support for thread-specific notifications ([MSC3773](https://github.com/matrix-org/matrix-spec-proposals/pull/3773)).
1 change: 1 addition & 0 deletions changelog.d/13877.feature
@@ -0,0 +1 @@
Experimental support for thread-specific receipts ([MSC3771](https://github.com/matrix-org/matrix-spec-proposals/pull/3771)).
clokep marked this conversation as resolved.
Show resolved Hide resolved
3 changes: 3 additions & 0 deletions synapse/api/constants.py
Expand Up @@ -31,6 +31,9 @@
# the maximum length for a user id is 255 characters
MAX_USERID_LENGTH = 255

# Constant value used for the pseudo-thread which is the main timeline.
MAIN_TIMELINE: Final = "main"


class Membership:

Expand Down
10 changes: 10 additions & 0 deletions synapse/api/filtering.py
Expand Up @@ -84,6 +84,7 @@
"contains_url": {"type": "boolean"},
"lazy_load_members": {"type": "boolean"},
"include_redundant_members": {"type": "boolean"},
"org.matrix.msc3773.unread_thread_notifications": {"type": "boolean"},
# Include or exclude events with the provided labels.
# cf https://github.com/matrix-org/matrix-doc/pull/2326
"org.matrix.labels": {"type": "array", "items": {"type": "string"}},
Expand Down Expand Up @@ -240,6 +241,9 @@ def lazy_load_members(self) -> bool:
def include_redundant_members(self) -> bool:
return self._room_state_filter.include_redundant_members

def unread_thread_notifications(self) -> bool:
return self._room_timeline_filter.unread_thread_notifications

async def filter_presence(
self, events: Iterable[UserPresenceState]
) -> List[UserPresenceState]:
Expand Down Expand Up @@ -304,6 +308,12 @@ def __init__(self, hs: "HomeServer", filter_json: JsonDict):
self.include_redundant_members = filter_json.get(
"include_redundant_members", False
)
if hs.config.experimental.msc3773_enabled:
self.unread_thread_notifications: bool = filter_json.get(
"org.matrix.msc3773.unread_thread_notifications", False
)
else:
self.unread_thread_notifications = False

self.types = filter_json.get("types", None)
self.not_types = filter_json.get("not_types", [])
Expand Down
2 changes: 2 additions & 0 deletions synapse/config/experimental.py
Expand Up @@ -87,6 +87,8 @@ def read_config(self, config: JsonDict, **kwargs: Any) -> None:
self.msc3771_enabled: bool = experimental.get("msc3771_enabled", False)
# MSC3772: A push rule for mutual relations.
self.msc3772_enabled: bool = experimental.get("msc3772_enabled", False)
# MSC3773: Thread notifications
self.msc3773_enabled: bool = experimental.get("msc3773_enabled", False)

# MSC3715: dir param on /relations.
self.msc3715_enabled: bool = experimental.get("msc3715_enabled", False)
Expand Down
40 changes: 35 additions & 5 deletions synapse/handlers/sync.py
Expand Up @@ -40,7 +40,7 @@
from synapse.logging.context import current_context
from synapse.logging.opentracing import SynapseTags, log_kv, set_tag, start_active_span
from synapse.push.clientformat import format_push_rules_for_user
from synapse.storage.databases.main.event_push_actions import NotifCounts
from synapse.storage.databases.main.event_push_actions import RoomNotifCounts
from synapse.storage.roommember import MemberSummary
from synapse.storage.state import StateFilter
from synapse.types import (
Expand Down Expand Up @@ -128,6 +128,7 @@ class JoinedSyncResult:
ephemeral: List[JsonDict]
account_data: List[JsonDict]
unread_notifications: JsonDict
unread_thread_notifications: JsonDict
summary: Optional[JsonDict]
unread_count: int

Expand Down Expand Up @@ -278,6 +279,8 @@ def __init__(self, hs: "HomeServer"):

self.rooms_to_exclude = hs.config.server.rooms_to_exclude_from_sync

self._msc3773_enabled = hs.config.experimental.msc3773_enabled

async def wait_for_sync_for_user(
self,
requester: Requester,
Expand Down Expand Up @@ -1288,7 +1291,7 @@ async def _find_missing_partial_state_memberships(

async def unread_notifs_for_room_id(
self, room_id: str, sync_config: SyncConfig
) -> NotifCounts:
) -> RoomNotifCounts:
with Measure(self.clock, "unread_notifs_for_room_id"):

return await self.store.get_unread_event_push_actions_by_room_for_user(
Expand Down Expand Up @@ -2359,17 +2362,44 @@ async def _generate_room_entry(
ephemeral=ephemeral,
account_data=account_data_events,
unread_notifications=unread_notifications,
unread_thread_notifications={},
summary=summary,
unread_count=0,
)

if room_sync or always_include:
notifs = await self.unread_notifs_for_room_id(room_id, sync_config)

unread_notifications["notification_count"] = notifs.notify_count
unread_notifications["highlight_count"] = notifs.highlight_count
# Notifications for the main timeline.
notify_count = notifs.main_timeline.notify_count
highlight_count = notifs.main_timeline.highlight_count
unread_count = notifs.main_timeline.unread_count

room_sync.unread_count = notifs.unread_count
# Check the sync configuration.
if (
self._msc3773_enabled
and sync_config.filter_collection.unread_thread_notifications()
):
# And add info for each thread.
room_sync.unread_thread_notifications = {
thread_id: {
"notification_count": thread_notifs.notify_count,
"highlight_count": thread_notifs.highlight_count,
}
for thread_id, thread_notifs in notifs.threads.items()
if thread_id is not None
}

else:
# Combine the unread counts for all threads and main timeline.
for thread_notifs in notifs.threads.values():
notify_count += thread_notifs.notify_count
highlight_count += thread_notifs.highlight_count
unread_count += thread_notifs.unread_count

unread_notifications["notification_count"] = notify_count
unread_notifications["highlight_count"] = highlight_count
room_sync.unread_count = unread_count

sync_result_builder.joined.append(room_sync)

Expand Down
4 changes: 2 additions & 2 deletions synapse/push/bulk_push_rule_evaluator.py
Expand Up @@ -30,7 +30,7 @@

from prometheus_client import Counter

from synapse.api.constants import EventTypes, Membership, RelationTypes
from synapse.api.constants import MAIN_TIMELINE, EventTypes, Membership, RelationTypes
from synapse.event_auth import auth_types_for_event, get_user_power_level
from synapse.events import EventBase, relation_from_event
from synapse.events.snapshot import EventContext
Expand Down Expand Up @@ -277,7 +277,7 @@ async def action_for_event_by_user(
# If the event does not have a relation, then cannot have any mutual
# relations or thread ID.
relations = {}
thread_id = "main"
thread_id = MAIN_TIMELINE
if relation:
relations = await self._get_mutual_relations(
relation.parent_id,
Expand Down
9 changes: 7 additions & 2 deletions synapse/push/push_tools.py
Expand Up @@ -39,15 +39,20 @@ async def get_room_unread_count(room_id: str) -> None:
await concurrently_execute(get_room_unread_count, joins, 10)

for notifs in room_notifs:
if notifs.notify_count == 0:
# Combine the counts from all the threads.
notify_count = notifs.main_timeline.notify_count + sum(
n.notify_count for n in notifs.threads.values()
)

if notify_count == 0:
continue

if group_by_room:
# return one badge count per conversation
badge += 1
else:
# increment the badge count by the number of unread messages in the room
badge += notifs.notify_count
badge += notify_count
return badge


Expand Down
4 changes: 4 additions & 0 deletions synapse/rest/client/sync.py
Expand Up @@ -509,6 +509,10 @@ async def encode_room(
ephemeral_events = room.ephemeral
result["ephemeral"] = {"events": ephemeral_events}
result["unread_notifications"] = room.unread_notifications
if room.unread_thread_notifications:
result[
"org.matrix.msc3773.unread_thread_notifications"
] = room.unread_thread_notifications
result["summary"] = room.summary
if self._msc2654_enabled:
result["org.matrix.msc2654.unread_count"] = room.unread_count
Expand Down
3 changes: 2 additions & 1 deletion synapse/rest/client/versions.py
Expand Up @@ -103,8 +103,9 @@ def on_GET(self, request: Request) -> Tuple[int, JsonDict]:
"org.matrix.msc3030": self.config.experimental.msc3030_enabled,
# Adds support for thread relations, per MSC3440.
"org.matrix.msc3440.stable": True, # TODO: remove when "v1.3" is added above
# Support for thread read receipts.
# Support for thread read receipts & notification counts.
"org.matrix.msc3771": self.config.experimental.msc3771_enabled,
"org.matrix.msc3773": self.config.experimental.msc3773_enabled,
# Allows moderators to fetch redacted event content as described in MSC2815
"fi.mau.msc2815": self.config.experimental.msc2815_enabled,
# Adds support for login token requests as per MSC3882
Expand Down
2 changes: 1 addition & 1 deletion synapse/storage/database.py
Expand Up @@ -94,7 +94,7 @@
"event_search": "event_search_event_id_idx",
"local_media_repository_thumbnails": "local_media_repository_thumbnails_method_idx",
"remote_media_cache_thumbnails": "remote_media_repository_thumbnails_method_idx",
"event_push_summary": "event_push_summary_unique_index",
"event_push_summary": "event_push_summary_unique_index2",
"receipts_linearized": "receipts_linearized_unique_index",
"receipts_graph": "receipts_graph_unique_index",
}
Expand Down