forked from AkkomaGang/akkoma
update counter_cache logic
This commit is contained in:
parent
0c2b09a9ba
commit
39d2f2118a
3 changed files with 82 additions and 34 deletions
|
@ -17,30 +17,46 @@ defmodule Mix.Tasks.Pleroma.RefreshCounterCache do
|
||||||
def run([]) do
|
def run([]) do
|
||||||
Mix.Pleroma.start_pleroma()
|
Mix.Pleroma.start_pleroma()
|
||||||
|
|
||||||
["public", "unlisted", "private", "direct"]
|
Activity
|
||||||
|> Enum.each(fn visibility ->
|
|> distinct([a], true)
|
||||||
count = status_visibility_count_query(visibility)
|
|> select([a], fragment("split_part(?, '/', 3)", a.actor))
|
||||||
name = "status_visibility_#{visibility}"
|
|> Repo.all()
|
||||||
CounterCache.set(name, count)
|
|> Enum.each(fn instance ->
|
||||||
Mix.Pleroma.shell_info("Set #{name} to #{count}")
|
counters = instance_counters(instance)
|
||||||
|
CounterCache.set(instance, counters)
|
||||||
|
Mix.Pleroma.shell_info("Setting #{instance} counters: #{inspect(counters)}")
|
||||||
end)
|
end)
|
||||||
|
|
||||||
Mix.Pleroma.shell_info("Done")
|
Mix.Pleroma.shell_info("Done")
|
||||||
end
|
end
|
||||||
|
|
||||||
defp status_visibility_count_query(visibility) do
|
defp instance_counters(instance) do
|
||||||
|
counters = %{"public" => 0, "unlisted" => 0, "private" => 0, "direct" => 0}
|
||||||
|
|
||||||
Activity
|
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],
|
[a],
|
||||||
fragment(
|
fragment(
|
||||||
"activity_visibility(?, ?, ?) = ?",
|
"activity_visibility(?, ?, ?)",
|
||||||
a.actor,
|
a.actor,
|
||||||
a.recipients,
|
a.recipients,
|
||||||
a.data,
|
a.data
|
||||||
^visibility
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|> where([a], fragment("(? ->> 'type'::text) = 'Create'", a.data))
|
|> Repo.all(timeout: :timer.minutes(30))
|
||||||
|> Repo.aggregate(:count, :id, timeout: :timer.minutes(30))
|
|> Enum.reduce(counters, fn {visibility, count}, acc ->
|
||||||
|
Map.put(acc, visibility, count)
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,32 +10,70 @@ defmodule Pleroma.CounterCache do
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
|
|
||||||
schema "counter_cache" do
|
schema "counter_cache" do
|
||||||
field(:name, :string)
|
field(:instance, :string)
|
||||||
field(:count, :integer)
|
field(:public, :integer)
|
||||||
|
field(:unlisted, :integer)
|
||||||
|
field(:private, :integer)
|
||||||
|
field(:direct, :integer)
|
||||||
end
|
end
|
||||||
|
|
||||||
def changeset(struct, params) do
|
def changeset(struct, params) do
|
||||||
struct
|
struct
|
||||||
|> cast(params, [:name, :count])
|
|> cast(params, [:instance, :public, :unlisted, :private, :direct])
|
||||||
|> validate_required([:name])
|
|> validate_required([:instance])
|
||||||
|> unique_constraint(:name)
|
|> unique_constraint(:instance)
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_as_map(names) when is_list(names) do
|
def get_by_instance(instance) do
|
||||||
CounterCache
|
CounterCache
|
||||||
|> where([cc], cc.name in ^names)
|
|> select([c], %{
|
||||||
|> Repo.all()
|
"public" => c.public,
|
||||||
|> Enum.group_by(& &1.name, & &1.count)
|
"unlisted" => c.unlisted,
|
||||||
|> Map.new(fn {k, v} -> {k, hd(v)} end)
|
"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
|
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{}
|
%CounterCache{}
|
||||||
|> changeset(%{"name" => name, "count" => count})
|
|> changeset(params)
|
||||||
|> Repo.insert(
|
|> Repo.insert(
|
||||||
on_conflict: [set: [count: count]],
|
on_conflict: [
|
||||||
|
set: [
|
||||||
|
public: params["public"],
|
||||||
|
private: params["private"],
|
||||||
|
unlisted: params["unlisted"],
|
||||||
|
direct: params["direct"]
|
||||||
|
]
|
||||||
|
],
|
||||||
returning: true,
|
returning: true,
|
||||||
conflict_target: :name
|
conflict_target: :instance
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -98,13 +98,7 @@ def calculate_stat_data do
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_status_visibility_count do
|
def get_status_visibility_count do
|
||||||
counter_cache =
|
counter_cache = CounterCache.get_as_map()
|
||||||
CounterCache.get_as_map([
|
|
||||||
"status_visibility_public",
|
|
||||||
"status_visibility_private",
|
|
||||||
"status_visibility_unlisted",
|
|
||||||
"status_visibility_direct"
|
|
||||||
])
|
|
||||||
|
|
||||||
%{
|
%{
|
||||||
public: counter_cache["status_visibility_public"] || 0,
|
public: counter_cache["status_visibility_public"] || 0,
|
||||||
|
|
Loading…
Reference in a new issue