summary refs log tree commit diff
diff options
context:
space:
mode:
authorkegsay <7190048+kegsay@users.noreply.github.com>2024-02-20 14:12:06 +0000
committerGitHub <noreply@github.com>2024-02-20 14:12:06 +0000
commitc51a2240d10a22296a92414b53a1373c328c6298 (patch)
treebeb58b8f555afdf4c94997bcd295219361848a0d
parentFix incorrect docker hub link in release script (#16910) (diff)
downloadsynapse-c51a2240d10a22296a92414b53a1373c328c6298.tar.xz
bugfix: always prefer unthreaded receipt when >1 exist (MSC4102) (#16927)
Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com>
-rw-r--r--changelog.d/16927.bugfix1
-rw-r--r--synapse/storage/databases/main/receipts.py21
2 files changed, 19 insertions, 3 deletions
diff --git a/changelog.d/16927.bugfix b/changelog.d/16927.bugfix
new file mode 100644
index 0000000000..ecc62a148c
--- /dev/null
+++ b/changelog.d/16927.bugfix
@@ -0,0 +1 @@
+Always prefer unthreaded receipt when >1 exist ([MSC4102](https://github.com/matrix-org/matrix-spec-proposals/pull/4102)).
\ No newline at end of file
diff --git a/synapse/storage/databases/main/receipts.py b/synapse/storage/databases/main/receipts.py
index 3c7708f5f3..8a426d2875 100644
--- a/synapse/storage/databases/main/receipts.py
+++ b/synapse/storage/databases/main/receipts.py
@@ -472,9 +472,24 @@ class ReceiptsWorkerStore(SQLBaseStore):
             event_entry = room_event["content"].setdefault(event_id, {})
             receipt_type_dict = event_entry.setdefault(receipt_type, {})
 
-            receipt_type_dict[user_id] = db_to_json(data)
-            if thread_id:
-                receipt_type_dict[user_id]["thread_id"] = thread_id
+            # MSC4102: always replace threaded receipts with unthreaded ones if there is a clash.
+            # Specifically:
+            # - if there is no existing receipt, great, set the data.
+            # - if there is an existing receipt, is it threaded (thread_id present)?
+            #    YES: replace if this receipt has no thread id. NO: do not replace.
+            # This means we will drop some receipts, but MSC4102 is designed to drop semantically
+            # meaningless receipts, so this is okay. Previously, we would drop meaningful data!
+            receipt_data = db_to_json(data)
+            if user_id in receipt_type_dict:  # existing receipt
+                # is the existing receipt threaded and we are currently processing an unthreaded one?
+                if "thread_id" in receipt_type_dict[user_id] and not thread_id:
+                    receipt_type_dict[
+                        user_id
+                    ] = receipt_data  # replace with unthreaded one
+            else:  # receipt does not exist, just set it
+                receipt_type_dict[user_id] = receipt_data
+                if thread_id:
+                    receipt_type_dict[user_id]["thread_id"] = thread_id
 
         results = {
             room_id: [results[room_id]] if room_id in results else []