Refactor query to return only 1 message instead of 20
authorRoman Chvanikov <chvanikoff@gmail.com>
Sat, 20 Apr 2019 17:40:41 +0000 (00:40 +0700)
committerRoman Chvanikov <chvanikoff@gmail.com>
Sat, 20 Apr 2019 17:40:41 +0000 (00:40 +0700)
lib/pleroma/conversation/participation.ex
lib/pleroma/web/activity_pub/activity_pub.ex

index f200c1df56698495f49cac149daeb95a527f238d..61021fb18104bfc07e0c706f52859602d6a82811 100644 (file)
@@ -65,22 +65,13 @@ defmodule Pleroma.Conversation.Participation do
 
   def for_user_with_last_activity_id(user, params \\ %{}) do
     for_user(user, params)
-    |> Repo.preload(:conversation)
     |> Enum.map(fn participation ->
-      # TODO: Don't load all those activities, just get the most recent
-      # Involves splitting up the query.
-      activities =
-        ActivityPub.fetch_activities_for_context(participation.conversation.ap_id, %{
+      activity_id =
+        ActivityPub.fetch_latest_activity_id_for_context(participation.conversation.ap_id, %{
           "user" => user,
           "blocking_user" => user
         })
 
-      activity_id =
-        case activities do
-          [activity | _] -> activity.id
-          _ -> nil
-        end
-
       %{
         participation
         | last_activity_id: activity_id
index 880d19a5ee56eea698e937c4f027442acb209852..577e6a59eea7527888b6e4a74733dce2556b9219 100644 (file)
@@ -459,35 +459,44 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
     end
   end
 
-  def fetch_activities_for_context(context, opts \\ %{}) do
+  defp fetch_activities_for_context_query(context, opts) do
     public = ["https://www.w3.org/ns/activitystreams#Public"]
 
     recipients =
       if opts["user"], do: [opts["user"].ap_id | opts["user"].following] ++ public, else: public
 
-    query = from(activity in Activity)
-
-    query =
-      query
-      |> restrict_blocked(opts)
-      |> restrict_recipients(recipients, opts["user"])
-
-    query =
-      from(
-        activity in query,
-        where:
-          fragment(
-            "?->>'type' = ? and ?->>'context' = ?",
-            activity.data,
-            "Create",
-            activity.data,
-            ^context
-          ),
-        order_by: [desc: :id]
+    from(activity in Activity)
+    |> restrict_blocked(opts)
+    |> restrict_recipients(recipients, opts["user"])
+    |> where(
+      [activity],
+      fragment(
+        "?->>'type' = ? and ?->>'context' = ?",
+        activity.data,
+        "Create",
+        activity.data,
+        ^context
       )
-      |> Activity.with_preloaded_object()
+    )
+    |> order_by([activity], desc: activity.id)
+  end
+
+  @spec fetch_activities_for_context(String.t(), keyword() | map()) :: [Activity.t()]
+  def fetch_activities_for_context(context, opts \\ %{}) do
+    context
+    |> fetch_activities_for_context_query(opts)
+    |> Activity.with_preloaded_object()
+    |> Repo.all()
+  end
 
-    Repo.all(query)
+  @spec fetch_latest_activity_id_for_context(String.t(), keyword() | map()) ::
+          Pleroma.FlakeId.t() | nil
+  def fetch_latest_activity_id_for_context(context, opts \\ %{}) do
+    context
+    |> fetch_activities_for_context_query(opts)
+    |> limit(1)
+    |> select([a], a.id)
+    |> Repo.one()
   end
 
   def fetch_public_activities(opts \\ %{}) do