about summary refs log tree commit diff
diff options
context:
space:
mode:
authorClaire <claire.github-309c@sitedethib.com>2022-03-30 10:26:51 +0200
committerGitHub <noreply@github.com>2022-03-30 10:26:51 +0200
commit2cc7ba26715c9f3fcc81ee5d30b282b1493a2e0b (patch)
tree25488c40b357fcd3d2358899c51469e71e6f381c
parent2de5128e6658cf448b521498e687b17d83b5db02 (diff)
Refactor `response_to_recipient?` CTE (#17899)
* Optimize and clean up `response_to_recipient?` CTE

Marginally improve performances, and make the CTE much more readable

* Limit max depth in `response_to_recipient?` CTE
-rw-r--r--app/services/notify_service.rb40
1 files changed, 8 insertions, 32 deletions
diff --git a/app/services/notify_service.rb b/app/services/notify_service.rb
index b1f9fd755..a90f17cfd 100644
--- a/app/services/notify_service.rb
+++ b/app/services/notify_service.rb
@@ -48,47 +48,23 @@ class NotifyService < BaseService
     return false if @notification.target_status.in_reply_to_id.nil?
 
     # Using an SQL CTE to avoid unneeded back-and-forth with SQL server in case of long threads
-    !Status.count_by_sql([<<-SQL.squish, id: @notification.target_status.in_reply_to_id, recipient_id: @recipient.id, sender_id: @notification.from_account.id]).zero?
-      WITH RECURSIVE ancestors(id, in_reply_to_id, replying_to_sender, path) AS (
-          SELECT
-            s.id,
-            s.in_reply_to_id,
-            (CASE
-              WHEN s.account_id = :recipient_id THEN
-                EXISTS (
-                  SELECT *
-                  FROM mentions m
-                  WHERE m.silent = FALSE AND m.account_id = :sender_id AND m.status_id = s.id
-                )
-              ELSE
-                FALSE
-             END),
-            ARRAY[s.id]
+    !Status.count_by_sql([<<-SQL.squish, id: @notification.target_status.in_reply_to_id, recipient_id: @recipient.id, sender_id: @notification.from_account.id, depth_limit: 100]).zero?
+      WITH RECURSIVE ancestors(id, in_reply_to_id, mention_id, path, depth) AS (
+          SELECT s.id, s.in_reply_to_id, m.id, ARRAY[s.id], 0
           FROM statuses s
+          LEFT JOIN mentions m ON m.silent = FALSE AND m.account_id = :sender_id AND m.status_id = s.id
           WHERE s.id = :id
         UNION ALL
-          SELECT
-            s.id,
-            s.in_reply_to_id,
-            (CASE
-              WHEN s.account_id = :recipient_id THEN
-                EXISTS (
-                  SELECT *
-                  FROM mentions m
-                  WHERE m.silent = FALSE AND m.account_id = :sender_id AND m.status_id = s.id
-                )
-              ELSE
-                FALSE
-             END),
-            st.path || s.id
+          SELECT s.id, s.in_reply_to_id, m.id, st.path || s.id, st.depth + 1
           FROM ancestors st
           JOIN statuses s ON s.id = st.in_reply_to_id
-          WHERE st.replying_to_sender IS FALSE AND NOT s.id = ANY(path)
+          LEFT JOIN mentions m ON m.silent = FALSE AND m.account_id = :sender_id AND m.status_id = s.id
+          WHERE st.mention_id IS NULL AND NOT s.id = ANY(path) AND st.depth < :depth_limit
       )
       SELECT COUNT(*)
       FROM ancestors st
       JOIN statuses s ON s.id = st.id
-      WHERE st.replying_to_sender IS TRUE AND s.visibility = 3
+      WHERE st.mention_id IS NOT NULL AND s.visibility = 3
     SQL
   end