mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2025-05-07 18:35:01 -04:00
Mark events as read using threaded read receipts from MSC3771. (#13877)
Applies the proper logic for unthreaded and threaded receipts to either apply to all events in the room or only events in the same thread, respectively.
This commit is contained in:
parent
f0019f3f3b
commit
a7ba457b2b
5 changed files with 505 additions and 63 deletions
|
@ -16,6 +16,7 @@ from typing import Optional, Tuple
|
|||
|
||||
from twisted.test.proto_helpers import MemoryReactor
|
||||
|
||||
from synapse.api.constants import MAIN_TIMELINE
|
||||
from synapse.rest import admin
|
||||
from synapse.rest.client import login, room
|
||||
from synapse.server import HomeServer
|
||||
|
@ -250,6 +251,187 @@ class EventPushActionsStoreTestCase(HomeserverTestCase):
|
|||
|
||||
last_event_id: str
|
||||
|
||||
def _assert_counts(
|
||||
noitf_count: int,
|
||||
highlight_count: int,
|
||||
thread_notif_count: int,
|
||||
thread_highlight_count: int,
|
||||
) -> None:
|
||||
counts = self.get_success(
|
||||
self.store.db_pool.runInteraction(
|
||||
"get-unread-counts",
|
||||
self.store._get_unread_counts_by_receipt_txn,
|
||||
room_id,
|
||||
user_id,
|
||||
)
|
||||
)
|
||||
self.assertEqual(
|
||||
counts.main_timeline,
|
||||
NotifCounts(
|
||||
notify_count=noitf_count,
|
||||
unread_count=0,
|
||||
highlight_count=highlight_count,
|
||||
),
|
||||
)
|
||||
if thread_notif_count or thread_highlight_count:
|
||||
self.assertEqual(
|
||||
counts.threads,
|
||||
{
|
||||
thread_id: NotifCounts(
|
||||
notify_count=thread_notif_count,
|
||||
unread_count=0,
|
||||
highlight_count=thread_highlight_count,
|
||||
),
|
||||
},
|
||||
)
|
||||
else:
|
||||
self.assertEqual(counts.threads, {})
|
||||
|
||||
def _create_event(
|
||||
highlight: bool = False, thread_id: Optional[str] = None
|
||||
) -> str:
|
||||
content: JsonDict = {
|
||||
"msgtype": "m.text",
|
||||
"body": user_id if highlight else "msg",
|
||||
}
|
||||
if thread_id:
|
||||
content["m.relates_to"] = {
|
||||
"rel_type": "m.thread",
|
||||
"event_id": thread_id,
|
||||
}
|
||||
|
||||
result = self.helper.send_event(
|
||||
room_id,
|
||||
type="m.room.message",
|
||||
content=content,
|
||||
tok=other_token,
|
||||
)
|
||||
nonlocal last_event_id
|
||||
last_event_id = result["event_id"]
|
||||
return last_event_id
|
||||
|
||||
def _rotate() -> None:
|
||||
self.get_success(self.store._rotate_notifs())
|
||||
|
||||
def _mark_read(event_id: str, thread_id: str = MAIN_TIMELINE) -> None:
|
||||
self.get_success(
|
||||
self.store.insert_receipt(
|
||||
room_id,
|
||||
"m.read",
|
||||
user_id=user_id,
|
||||
event_ids=[event_id],
|
||||
thread_id=thread_id,
|
||||
data={},
|
||||
)
|
||||
)
|
||||
|
||||
_assert_counts(0, 0, 0, 0)
|
||||
thread_id = _create_event()
|
||||
_assert_counts(1, 0, 0, 0)
|
||||
_rotate()
|
||||
_assert_counts(1, 0, 0, 0)
|
||||
|
||||
_create_event(thread_id=thread_id)
|
||||
_assert_counts(1, 0, 1, 0)
|
||||
_rotate()
|
||||
_assert_counts(1, 0, 1, 0)
|
||||
|
||||
_create_event()
|
||||
_assert_counts(2, 0, 1, 0)
|
||||
_rotate()
|
||||
_assert_counts(2, 0, 1, 0)
|
||||
|
||||
event_id = _create_event(thread_id=thread_id)
|
||||
_assert_counts(2, 0, 2, 0)
|
||||
_rotate()
|
||||
_assert_counts(2, 0, 2, 0)
|
||||
|
||||
_create_event()
|
||||
_create_event(thread_id=thread_id)
|
||||
_mark_read(event_id)
|
||||
_assert_counts(1, 0, 3, 0)
|
||||
_mark_read(event_id, thread_id)
|
||||
_assert_counts(1, 0, 1, 0)
|
||||
|
||||
_mark_read(last_event_id)
|
||||
_mark_read(last_event_id, thread_id)
|
||||
_assert_counts(0, 0, 0, 0)
|
||||
|
||||
_create_event()
|
||||
_create_event(thread_id=thread_id)
|
||||
_assert_counts(1, 0, 1, 0)
|
||||
_rotate()
|
||||
_assert_counts(1, 0, 1, 0)
|
||||
|
||||
# Delete old event push actions, this should not affect the (summarised) count.
|
||||
self.get_success(self.store._remove_old_push_actions_that_have_rotated())
|
||||
_assert_counts(1, 0, 1, 0)
|
||||
|
||||
_mark_read(last_event_id)
|
||||
_mark_read(last_event_id, thread_id)
|
||||
_assert_counts(0, 0, 0, 0)
|
||||
|
||||
_create_event(True)
|
||||
_assert_counts(1, 1, 0, 0)
|
||||
_rotate()
|
||||
_assert_counts(1, 1, 0, 0)
|
||||
|
||||
event_id = _create_event(True, thread_id)
|
||||
_assert_counts(1, 1, 1, 1)
|
||||
_rotate()
|
||||
_assert_counts(1, 1, 1, 1)
|
||||
|
||||
# Check that adding another notification and rotating after highlight
|
||||
# works.
|
||||
_create_event()
|
||||
_rotate()
|
||||
_assert_counts(2, 1, 1, 1)
|
||||
|
||||
_create_event(thread_id=thread_id)
|
||||
_rotate()
|
||||
_assert_counts(2, 1, 2, 1)
|
||||
|
||||
# Check that sending read receipts at different points results in the
|
||||
# right counts.
|
||||
_mark_read(event_id)
|
||||
_assert_counts(1, 0, 2, 1)
|
||||
_mark_read(event_id, thread_id)
|
||||
_assert_counts(1, 0, 1, 0)
|
||||
_mark_read(last_event_id)
|
||||
_assert_counts(0, 0, 1, 0)
|
||||
_mark_read(last_event_id, thread_id)
|
||||
_assert_counts(0, 0, 0, 0)
|
||||
|
||||
_create_event(True)
|
||||
_create_event(True, thread_id)
|
||||
_assert_counts(1, 1, 1, 1)
|
||||
_mark_read(last_event_id)
|
||||
_mark_read(last_event_id, thread_id)
|
||||
_assert_counts(0, 0, 0, 0)
|
||||
_rotate()
|
||||
_assert_counts(0, 0, 0, 0)
|
||||
|
||||
def test_count_aggregation_mixed(self) -> None:
|
||||
"""
|
||||
This is essentially the same test as test_count_aggregation_threads, but
|
||||
sends both unthreaded and threaded receipts.
|
||||
"""
|
||||
|
||||
# Create a user to receive notifications and send receipts.
|
||||
user_id = self.register_user("user1235", "pass")
|
||||
token = self.login("user1235", "pass")
|
||||
|
||||
# And another users to send events.
|
||||
other_id = self.register_user("other", "pass")
|
||||
other_token = self.login("other", "pass")
|
||||
|
||||
# Create a room and put both users in it.
|
||||
room_id = self.helper.create_room_as(user_id, tok=token)
|
||||
self.helper.join(room_id, other_id, tok=other_token)
|
||||
thread_id: str
|
||||
|
||||
last_event_id: str
|
||||
|
||||
def _assert_counts(
|
||||
noitf_count: int,
|
||||
highlight_count: int,
|
||||
|
@ -350,7 +532,8 @@ class EventPushActionsStoreTestCase(HomeserverTestCase):
|
|||
_mark_read(event_id)
|
||||
_assert_counts(1, 0, 1, 0)
|
||||
|
||||
_mark_read(last_event_id)
|
||||
_mark_read(last_event_id, MAIN_TIMELINE)
|
||||
_mark_read(last_event_id, thread_id)
|
||||
_assert_counts(0, 0, 0, 0)
|
||||
|
||||
_create_event()
|
||||
|
@ -390,7 +573,11 @@ class EventPushActionsStoreTestCase(HomeserverTestCase):
|
|||
# right counts.
|
||||
_mark_read(event_id)
|
||||
_assert_counts(1, 0, 1, 0)
|
||||
_mark_read(last_event_id)
|
||||
_mark_read(event_id, MAIN_TIMELINE)
|
||||
_assert_counts(1, 0, 1, 0)
|
||||
_mark_read(last_event_id, MAIN_TIMELINE)
|
||||
_assert_counts(0, 0, 1, 0)
|
||||
_mark_read(last_event_id, thread_id)
|
||||
_assert_counts(0, 0, 0, 0)
|
||||
|
||||
_create_event(True)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue