Avoid potentially slow count queries for user note count.
authorRoger Braun <roger@rogerbraun.net>
Tue, 31 Oct 2017 15:37:11 +0000 (16:37 +0100)
committerRoger Braun <roger@rogerbraun.net>
Tue, 31 Oct 2017 15:37:11 +0000 (16:37 +0100)
For a variety of reasons, posgresql won't use the available actor,
type index to do an index only scan. We now just increase the user
note count, which will lead to slightly wrong counts in some cases,
but it's better than the potentially very slow count query.

lib/pleroma/user.ex
lib/pleroma/web/common_api/common_api.ex
lib/pleroma/web/ostatus/handlers/note_handler.ex
test/user_test.exs

index bf63a22b3f4075a16581bdfc7728654af8352ac5..5f1750035127b77ff9867af0bd145bf2a6a07daf 100644 (file)
@@ -239,6 +239,15 @@ defmodule Pleroma.User do
     {:ok, Repo.all(q)}
   end
 
+  def increase_note_count(%User{} = user) do
+    note_count = (user.info["note_count"] || 0) + 1
+    new_info = Map.put(user.info, "note_count", note_count)
+
+    cs = info_changeset(user, %{info: new_info})
+
+    Repo.update(cs)
+  end
+
   def update_note_count(%User{} = user) do
     note_count_query = from a in Object,
       where: fragment("?->>'actor' = ? and ?->>'type' = 'Note'", a.data, ^user.ap_id, a.data),
index a865cd143470799c38d87e4d2d70b9d0e5dfae81..c9822dc2d333056d0abccb1b975b0997615e3318 100644 (file)
@@ -61,7 +61,7 @@ defmodule Pleroma.Web.CommonAPI do
          context <- make_context(inReplyTo),
          object <- make_note_data(user.ap_id, to, context, content_html, attachments, inReplyTo, tags) do
       res = ActivityPub.create(to, user, context, object)
-      User.update_note_count(user)
+      User.increase_note_count(user)
       res
     end
   end
index dda5c7d5ea5dd15983c3812098fbd1bb355e3944..b151c118a787330c27bffd462da0e00e43d67e56 100644 (file)
@@ -112,7 +112,7 @@ defmodule Pleroma.Web.OStatus.NoteHandler do
          note <- (if inReplyTo && !inReplyToActivity, do: note |> Map.put("inReplyTo", inReplyTo), else: note)
       do
       res = ActivityPub.create(to, actor, context, note, %{}, date, false)
-      User.update_note_count(actor)
+      User.increase_note_count(actor)
       res
     else
       %Activity{} = activity -> {:ok, activity}
index 097d7d98e9740a727071232f6c22405fc27f02d4..ae9a48e743cc8ddc36a82ffbb0b9c3e96f25f06b 100644 (file)
@@ -246,6 +246,21 @@ defmodule Pleroma.UserTest do
       assert user.info["note_count"] == 1
     end
 
+    test "it increases the info->note_count property" do
+      note = insert(:note)
+      user = User.get_by_ap_id(note.data["actor"])
+
+      assert user.info["note_count"] == nil
+
+      {:ok, user} = User.increase_note_count(user)
+
+      assert user.info["note_count"] == 1
+
+      {:ok, user} = User.increase_note_count(user)
+
+      assert user.info["note_count"] == 2
+    end
+
     test "it sets the info->follower_count property" do
       user = insert(:user)
       follower = insert(:user)