summaryrefslogtreecommitdiff
path: root/lib/mix/tasks/pleroma/refresh_counter_cache.ex
blob: 66eed86570d7e0a0ea1f6c38a8d1fbf34710934d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only

defmodule Mix.Tasks.Pleroma.RefreshCounterCache do
  @shortdoc "Refreshes counter cache"

  use Mix.Task

  alias Pleroma.Activity
  alias Pleroma.CounterCache
  alias Pleroma.Repo

  require Logger
  import Ecto.Query

  def run([]) do
    Mix.Pleroma.start_pleroma()

    instances =
      Activity
      |> distinct([a], true)
      |> select([a], fragment("split_part(?, '/', 3)", a.actor))
      |> Repo.all()

    instances
    |> Enum.with_index(1)
    |> Enum.each(fn {instance, i} ->
      counters = instance_counters(instance)
      CounterCache.set(instance, counters)

      Mix.Pleroma.shell_info(
        "[#{i}/#{length(instances)}] Setting #{instance} counters: #{inspect(counters)}"
      )
    end)

    Mix.Pleroma.shell_info("Done")
  end

  defp instance_counters(instance) do
    counters = %{"public" => 0, "unlisted" => 0, "private" => 0, "direct" => 0}

    Activity
    |> where([a], fragment("(? ->> 'type'::text) = 'Create'", a.data))
    |> where([a], fragment("split_part(?, '/', 3) = ?", a.actor, ^instance))
    |> select(
      [a],
      {fragment(
         "activity_visibility(?, ?, ?)",
         a.actor,
         a.recipients,
         a.data
       ), count(a.id)}
    )
    |> group_by(
      [a],
      fragment(
        "activity_visibility(?, ?, ?)",
        a.actor,
        a.recipients,
        a.data
      )
    )
    |> Repo.all(timeout: :timer.minutes(30))
    |> Enum.reduce(counters, fn {visibility, count}, acc ->
      Map.put(acc, visibility, count)
    end)
  end
end