diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/mix/tasks/pleroma/refresh_counter_cache.ex | 42 | ||||
| -rw-r--r-- | lib/pleroma/counter_cache.ex | 66 | ||||
| -rw-r--r-- | lib/pleroma/stats.ex | 8 | 
3 files changed, 82 insertions, 34 deletions
diff --git a/lib/mix/tasks/pleroma/refresh_counter_cache.ex b/lib/mix/tasks/pleroma/refresh_counter_cache.ex index 15b4dbfa6..280201bef 100644 --- a/lib/mix/tasks/pleroma/refresh_counter_cache.ex +++ b/lib/mix/tasks/pleroma/refresh_counter_cache.ex @@ -17,30 +17,46 @@ defmodule Mix.Tasks.Pleroma.RefreshCounterCache do    def run([]) do      Mix.Pleroma.start_pleroma() -    ["public", "unlisted", "private", "direct"] -    |> Enum.each(fn visibility -> -      count = status_visibility_count_query(visibility) -      name = "status_visibility_#{visibility}" -      CounterCache.set(name, count) -      Mix.Pleroma.shell_info("Set #{name} to #{count}") +    Activity +    |> distinct([a], true) +    |> select([a], fragment("split_part(?, '/', 3)", a.actor)) +    |> Repo.all() +    |> Enum.each(fn instance -> +      counters = instance_counters(instance) +      CounterCache.set(instance, counters) +      Mix.Pleroma.shell_info("Setting #{instance} counters: #{inspect(counters)}")      end)      Mix.Pleroma.shell_info("Done")    end -  defp status_visibility_count_query(visibility) do +  defp instance_counters(instance) do +    counters = %{"public" => 0, "unlisted" => 0, "private" => 0, "direct" => 0} +      Activity -    |> where( +    |> where([a], fragment("(? ->> 'type'::text) = 'Create'", a.data)) +    |> where([a], like(a.actor, ^"%#{instance}%")) +    |> select( +      [a], +      {fragment( +         "activity_visibility(?, ?, ?)", +         a.actor, +         a.recipients, +         a.data +       ), count(a.id)} +    ) +    |> group_by(        [a],        fragment( -        "activity_visibility(?, ?, ?) = ?", +        "activity_visibility(?, ?, ?)",          a.actor,          a.recipients, -        a.data, -        ^visibility +        a.data        )      ) -    |> where([a], fragment("(? ->> 'type'::text) = 'Create'", a.data)) -    |> Repo.aggregate(:count, :id, timeout: :timer.minutes(30)) +    |> Repo.all(timeout: :timer.minutes(30)) +    |> Enum.reduce(counters, fn {visibility, count}, acc -> +      Map.put(acc, visibility, count) +    end)    end  end diff --git a/lib/pleroma/counter_cache.ex b/lib/pleroma/counter_cache.ex index 4d348a413..b469e7b50 100644 --- a/lib/pleroma/counter_cache.ex +++ b/lib/pleroma/counter_cache.ex @@ -10,32 +10,70 @@ defmodule Pleroma.CounterCache do    import Ecto.Query    schema "counter_cache" do -    field(:name, :string) -    field(:count, :integer) +    field(:instance, :string) +    field(:public, :integer) +    field(:unlisted, :integer) +    field(:private, :integer) +    field(:direct, :integer)    end    def changeset(struct, params) do      struct -    |> cast(params, [:name, :count]) -    |> validate_required([:name]) -    |> unique_constraint(:name) +    |> cast(params, [:instance, :public, :unlisted, :private, :direct]) +    |> validate_required([:instance]) +    |> unique_constraint(:instance)    end -  def get_as_map(names) when is_list(names) do +  def get_by_instance(instance) do      CounterCache -    |> where([cc], cc.name in ^names) -    |> Repo.all() -    |> Enum.group_by(& &1.name, & &1.count) -    |> Map.new(fn {k, v} -> {k, hd(v)} end) +    |> select([c], %{ +      "public" => c.public, +      "unlisted" => c.unlisted, +      "private" => c.private, +      "direct" => c.direct +    }) +    |> where([c], c.instance == ^instance) +    |> Repo.one() +    |> case do +      nil -> %{"public" => 0, "unlisted" => 0, "private" => 0, "direct" => 0} +      val -> val +    end    end -  def set(name, count) do +  def get_as_map() do +    CounterCache +    |> select([c], %{ +      "public" => sum(c.public), +      "unlisted" => sum(c.unlisted), +      "private" => sum(c.private), +      "direct" => sum(c.direct) +    }) +    |> Repo.one() +  end + +  def set(instance, values) do +    params = +      Enum.reduce( +        ["public", "private", "unlisted", "direct"], +        %{"instance" => instance}, +        fn param, acc -> +          Map.put_new(acc, param, Map.get(values, param, 0)) +        end +      ) +      %CounterCache{} -    |> changeset(%{"name" => name, "count" => count}) +    |> changeset(params)      |> Repo.insert( -      on_conflict: [set: [count: count]], +      on_conflict: [ +        set: [ +          public: params["public"], +          private: params["private"], +          unlisted: params["unlisted"], +          direct: params["direct"] +        ] +      ],        returning: true, -      conflict_target: :name +      conflict_target: :instance      )    end  end diff --git a/lib/pleroma/stats.ex b/lib/pleroma/stats.ex index 6b3a8a41f..4e355bd5c 100644 --- a/lib/pleroma/stats.ex +++ b/lib/pleroma/stats.ex @@ -98,13 +98,7 @@ defmodule Pleroma.Stats do    end    def get_status_visibility_count do -    counter_cache = -      CounterCache.get_as_map([ -        "status_visibility_public", -        "status_visibility_private", -        "status_visibility_unlisted", -        "status_visibility_direct" -      ]) +    counter_cache = CounterCache.get_as_map()      %{        public: counter_cache["status_visibility_public"] || 0,  | 
