# Pleroma: A lightweight social networking server # Copyright © 2017-2023 Pleroma Authors # 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