Update stats admin endpoint

This commit is contained in:
Roman Chvanikov 2020-05-09 11:30:37 +03:00
parent 39d2f2118a
commit cbe383ae83
6 changed files with 87 additions and 24 deletions

View File

@ -40,7 +40,7 @@ def get_by_instance(instance) do
end end
end end
def get_as_map() do def get_sum() do
CounterCache CounterCache
|> select([c], %{ |> select([c], %{
"public" => sum(c.public), "public" => sum(c.public),
@ -49,6 +49,10 @@ def get_as_map() do
"direct" => sum(c.direct) "direct" => sum(c.direct)
}) })
|> Repo.one() |> Repo.one()
|> Enum.map(fn {visibility, dec_count} ->
{visibility, Decimal.to_integer(dec_count)}
end)
|> Enum.into(%{})
end end
def set(instance, values) do def set(instance, values) do

View File

@ -97,14 +97,11 @@ def calculate_stat_data do
} }
end end
def get_status_visibility_count do def get_status_visibility_count(instance \\ nil) do
counter_cache = CounterCache.get_as_map() if is_nil(instance) do
CounterCache.get_sum()
%{ else
public: counter_cache["status_visibility_public"] || 0, CounterCache.get_by_instance(instance)
unlisted: counter_cache["status_visibility_unlisted"] || 0, end
private: counter_cache["status_visibility_private"] || 0,
direct: counter_cache["status_visibility_direct"] || 0
}
end end
end end

View File

@ -1122,11 +1122,10 @@ def oauth_app_delete(conn, params) do
end end
end end
def stats(conn, _) do def stats(conn, params) do
count = Stats.get_status_visibility_count() counters = Stats.get_status_visibility_count(params["instance"])
conn json(conn, %{"status_visibility" => counters})
|> json(%{"status_visibility" => count})
end end
defp errors(conn, {:error, :not_found}) do defp errors(conn, {:error, :not_found}) do

View File

@ -43,7 +43,8 @@ def up do
END IF; END IF;
IF TG_OP = 'INSERT' THEN IF TG_OP = 'INSERT' THEN
visibility_new := activity_visibility(NEW.actor, NEW.recipients, NEW.data); visibility_new := activity_visibility(NEW.actor, NEW.recipients, NEW.data);
IF NEW.data->>'type' = 'Create' THEN IF NEW.data->>'type' = 'Create'
AND visibility_new IN ('public', 'unlisted', 'private', 'direct') THEN
EXECUTE format('INSERT INTO "counter_cache" ("instance", %1$I) VALUES ($1, 1) EXECUTE format('INSERT INTO "counter_cache" ("instance", %1$I) VALUES ($1, 1)
ON CONFLICT ("instance") DO ON CONFLICT ("instance") DO
UPDATE SET %1$I = "counter_cache".%1$I + 1', visibility_new) UPDATE SET %1$I = "counter_cache".%1$I + 1', visibility_new)
@ -53,7 +54,10 @@ def up do
ELSIF TG_OP = 'UPDATE' THEN ELSIF TG_OP = 'UPDATE' THEN
visibility_new := activity_visibility(NEW.actor, NEW.recipients, NEW.data); visibility_new := activity_visibility(NEW.actor, NEW.recipients, NEW.data);
visibility_old := activity_visibility(OLD.actor, OLD.recipients, OLD.data); visibility_old := activity_visibility(OLD.actor, OLD.recipients, OLD.data);
IF (NEW.data->>'type' = 'Create') and (OLD.data->>'type' = 'Create') and visibility_new != visibility_old THEN IF (NEW.data->>'type' = 'Create')
AND (OLD.data->>'type' = 'Create')
AND visibility_new != visibility_old
AND visibility_new IN ('public', 'unlisted', 'private', 'direct') THEN
EXECUTE format('UPDATE "counter_cache" SET EXECUTE format('UPDATE "counter_cache" SET
%1$I = greatest("counter_cache".%1$I - 1, 0), %1$I = greatest("counter_cache".%1$I - 1, 0),
%2$I = "counter_cache".%2$I + 1 %2$I = "counter_cache".%2$I + 1

View File

@ -17,10 +17,11 @@ test "it ignores internal users" do
end end
end end
describe "status visibility count" do describe "status visibility sum count" do
test "on new status" do test "on new status" do
instance2 = "instance2.tld"
user = insert(:user) user = insert(:user)
other_user = insert(:user) other_user = insert(:user, %{ap_id: "https://#{instance2}/@actor"})
CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"}) CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"})
@ -45,24 +46,24 @@ test "on new status" do
}) })
end) end)
assert %{direct: 3, private: 4, public: 1, unlisted: 2} = assert %{"direct" => 3, "private" => 4, "public" => 1, "unlisted" => 2} =
Pleroma.Stats.get_status_visibility_count() Pleroma.Stats.get_status_visibility_count()
end end
test "on status delete" do test "on status delete" do
user = insert(:user) user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"}) {:ok, activity} = CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"})
assert %{public: 1} = Pleroma.Stats.get_status_visibility_count() assert %{"public" => 1} = Pleroma.Stats.get_status_visibility_count()
CommonAPI.delete(activity.id, user) CommonAPI.delete(activity.id, user)
assert %{public: 0} = Pleroma.Stats.get_status_visibility_count() assert %{"public" => 0} = Pleroma.Stats.get_status_visibility_count()
end end
test "on status visibility update" do test "on status visibility update" do
user = insert(:user) user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"}) {:ok, activity} = CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"})
assert %{public: 1, private: 0} = Pleroma.Stats.get_status_visibility_count() assert %{"public" => 1, "private" => 0} = Pleroma.Stats.get_status_visibility_count()
{:ok, _} = CommonAPI.update_activity_scope(activity.id, %{"visibility" => "private"}) {:ok, _} = CommonAPI.update_activity_scope(activity.id, %{"visibility" => "private"})
assert %{public: 0, private: 1} = Pleroma.Stats.get_status_visibility_count() assert %{"public" => 0, "private" => 1} = Pleroma.Stats.get_status_visibility_count()
end end
test "doesn't count unrelated activities" do test "doesn't count unrelated activities" do
@ -73,8 +74,46 @@ test "doesn't count unrelated activities" do
CommonAPI.favorite(other_user, activity.id) CommonAPI.favorite(other_user, activity.id)
CommonAPI.repeat(activity.id, other_user) CommonAPI.repeat(activity.id, other_user)
assert %{direct: 0, private: 0, public: 1, unlisted: 0} = assert %{"direct" => 0, "private" => 0, "public" => 1, "unlisted" => 0} =
Pleroma.Stats.get_status_visibility_count() Pleroma.Stats.get_status_visibility_count()
end end
end end
describe "status visibility by instance count" do
test "single instance" do
local_instance = Pleroma.Web.Endpoint.url() |> String.split("//") |> Enum.at(1)
instance2 = "instance2.tld"
user1 = insert(:user)
user2 = insert(:user, %{ap_id: "https://#{instance2}/@actor"})
CommonAPI.post(user1, %{"visibility" => "public", "status" => "hey"})
Enum.each(1..5, fn _ ->
CommonAPI.post(user1, %{
"visibility" => "unlisted",
"status" => "hey"
})
end)
Enum.each(1..10, fn _ ->
CommonAPI.post(user1, %{
"visibility" => "direct",
"status" => "hey @#{user2.nickname}"
})
end)
Enum.each(1..20, fn _ ->
CommonAPI.post(user2, %{
"visibility" => "private",
"status" => "hey"
})
end)
assert %{"direct" => 10, "private" => 0, "public" => 1, "unlisted" => 5} =
Pleroma.Stats.get_status_visibility_count(local_instance)
assert %{"direct" => 0, "private" => 20, "public" => 0, "unlisted" => 0} =
Pleroma.Stats.get_status_visibility_count(instance2)
end
end
end end

View File

@ -3612,6 +3612,26 @@ test "status visibility count", %{conn: conn} do
assert %{"direct" => 0, "private" => 0, "public" => 1, "unlisted" => 2} = assert %{"direct" => 0, "private" => 0, "public" => 1, "unlisted" => 2} =
response["status_visibility"] response["status_visibility"]
end end
test "by instance", %{conn: conn} do
admin = insert(:user, is_admin: true)
user1 = insert(:user)
instance2 = "instance2.tld"
user2 = insert(:user, %{ap_id: "https://#{instance2}/@actor"})
CommonAPI.post(user1, %{"visibility" => "public", "status" => "hey"})
CommonAPI.post(user2, %{"visibility" => "unlisted", "status" => "hey"})
CommonAPI.post(user2, %{"visibility" => "private", "status" => "hey"})
response =
conn
|> assign(:user, admin)
|> get("/api/pleroma/admin/stats", instance: instance2)
|> json_response(200)
assert %{"direct" => 0, "private" => 1, "public" => 0, "unlisted" => 1} =
response["status_visibility"]
end
end end
describe "POST /api/pleroma/admin/oauth_app" do describe "POST /api/pleroma/admin/oauth_app" do