ad37cd20bed5d86c82f0e8a8db7373a04cd3f2b2
[anni] / lib / mix / tasks / pleroma / refresh_counter_cache.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Mix.Tasks.Pleroma.RefreshCounterCache do
6   @shortdoc "Refreshes counter cache"
7
8   use Mix.Task
9
10   alias Pleroma.Activity
11   alias Pleroma.CounterCache
12   alias Pleroma.Repo
13
14   require Logger
15   import Ecto.Query
16
17   def run([]) do
18     Mix.Pleroma.start_pleroma()
19
20     instances =
21       Activity
22       |> distinct([a], true)
23       |> select([a], fragment("split_part(?, '/', 3)", a.actor))
24       |> Repo.all()
25
26     instances
27     |> Enum.with_index(1)
28     |> Enum.each(fn {instance, i} ->
29       counters = instance_counters(instance)
30       CounterCache.set(instance, counters)
31
32       Mix.Pleroma.shell_info(
33         "[#{i}/#{length(instances)}] Setting #{instance} counters: #{inspect(counters)}"
34       )
35     end)
36
37     Mix.Pleroma.shell_info("Done")
38   end
39
40   defp instance_counters(instance) do
41     counters = %{"public" => 0, "unlisted" => 0, "private" => 0, "direct" => 0}
42
43     Activity
44     |> where([a], fragment("(? ->> 'type'::text) = 'Create'", a.data))
45     |> where([a], fragment("split_part(?, '/', 3) = ?", a.actor, ^instance))
46     |> select(
47       [a],
48       {fragment(
49          "activity_visibility(?, ?, ?)",
50          a.actor,
51          a.recipients,
52          a.data
53        ), count(a.id)}
54     )
55     |> group_by(
56       [a],
57       fragment(
58         "activity_visibility(?, ?, ?)",
59         a.actor,
60         a.recipients,
61         a.data
62       )
63     )
64     |> Repo.all(timeout: :timer.minutes(30))
65     |> Enum.reduce(counters, fn {visibility, count}, acc ->
66       Map.put(acc, visibility, count)
67     end)
68   end
69 end