Hashtags, Blocks: Reword for performance.
This commit is contained in:
parent
5178c8dbc3
commit
12738732c9
@ -33,36 +33,6 @@ defmodule Mix.Tasks.Pleroma.Benchmarks.Tags do
|
||||
|
||||
Benchee.run(
|
||||
%{
|
||||
"Hashtag fetching, any" => fn tags ->
|
||||
Pleroma.Web.MastodonAPI.TimelineController.hashtag_fetching(
|
||||
%{
|
||||
"any" => tags
|
||||
},
|
||||
user,
|
||||
false
|
||||
)
|
||||
end,
|
||||
# Will always return zero results because no overlapping hashtags are generated.
|
||||
"Hashtag fetching, all" => fn tags ->
|
||||
Pleroma.Web.MastodonAPI.TimelineController.hashtag_fetching(
|
||||
%{
|
||||
"all" => tags
|
||||
},
|
||||
user,
|
||||
false
|
||||
)
|
||||
end
|
||||
},
|
||||
inputs:
|
||||
tags
|
||||
|> Enum.map(fn {_, v} -> v end)
|
||||
|> Enum.chunk_every(2)
|
||||
|> Enum.map(fn tags -> {"For #{inspect(tags)}", tags} end),
|
||||
time: 5
|
||||
)
|
||||
|
||||
Benchee.run(
|
||||
%{
|
||||
"Hashtag fetching" => fn tag ->
|
||||
Pleroma.Web.MastodonAPI.TimelineController.hashtag_fetching(
|
||||
%{
|
||||
|
@ -43,6 +43,7 @@ defmodule Pleroma.Activity do
|
||||
field(:local, :boolean, default: true)
|
||||
field(:actor, :string)
|
||||
field(:recipients, {:array, :string}, default: [])
|
||||
field(:block_cache, {:array, :string}, default: [], read_after_writes: true)
|
||||
field(:thread_muted?, :boolean, virtual: true)
|
||||
|
||||
# This is a fake relation,
|
||||
|
@ -800,50 +800,35 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||
|
||||
defp restrict_since(query, _), do: query
|
||||
|
||||
defp restrict_tag_reject(_query, %{"tag_reject" => _tag_reject, "skip_preload" => true}) do
|
||||
raise "Can't use the child object without preloading!"
|
||||
end
|
||||
|
||||
defp restrict_tag_reject(query, %{"tag_reject" => tag_reject})
|
||||
when is_list(tag_reject) and tag_reject != [] do
|
||||
from(
|
||||
[_activity, object] in query,
|
||||
where: fragment("not (?)->'tag' \\?| (?)", object.data, ^tag_reject)
|
||||
activity in query,
|
||||
where: fragment("not ? && ?", activity.tags, ^tag_reject)
|
||||
)
|
||||
end
|
||||
|
||||
defp restrict_tag_reject(query, _), do: query
|
||||
|
||||
defp restrict_tag_all(_query, %{"tag_all" => _tag_all, "skip_preload" => true}) do
|
||||
raise "Can't use the child object without preloading!"
|
||||
end
|
||||
|
||||
defp restrict_tag_all(query, %{"tag_all" => tag_all})
|
||||
when is_list(tag_all) and tag_all != [] do
|
||||
from(
|
||||
[_activity, object] in query,
|
||||
where: fragment("(?)->'tag' \\?& (?)", object.data, ^tag_all)
|
||||
activity in query,
|
||||
where: fragment("? @> ?", activity.tags, ^tag_all)
|
||||
)
|
||||
end
|
||||
|
||||
defp restrict_tag_all(query, _), do: query
|
||||
|
||||
defp restrict_tag(_query, %{"tag" => _tag, "skip_preload" => true}) do
|
||||
raise "Can't use the child object without preloading!"
|
||||
end
|
||||
|
||||
defp restrict_tag(query, %{"tag" => tag}) when is_list(tag) do
|
||||
from(
|
||||
[_activity, object] in query,
|
||||
where: fragment("(?)->'tag' \\?| (?)", object.data, ^tag)
|
||||
activity in query,
|
||||
where: fragment("? && ?", activity.tags, ^tag)
|
||||
)
|
||||
end
|
||||
|
||||
defp restrict_tag(query, %{"tag" => tag}) when is_binary(tag) do
|
||||
from(
|
||||
[_activity, object] in query,
|
||||
where: fragment("(?)->'tag' \\? (?)", object.data, ^tag)
|
||||
)
|
||||
restrict_tag(query, %{"tag" => [tag]})
|
||||
end
|
||||
|
||||
defp restrict_tag(query, _), do: query
|
||||
@ -934,8 +919,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||
|
||||
query =
|
||||
from([activity] in query,
|
||||
where: fragment("not (? = ANY(?))", activity.actor, ^mutes),
|
||||
where: fragment("not (?->'to' \\?| ?)", activity.data, ^mutes)
|
||||
where: fragment("not (? && ?)", activity.block_cache, ^mutes)
|
||||
)
|
||||
|
||||
unless opts["skip_preload"] do
|
||||
@ -953,34 +937,22 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||
|
||||
following_ap_ids = User.get_friends_ap_ids(user)
|
||||
|
||||
query =
|
||||
if has_named_binding?(query, :object), do: query, else: Activity.with_joined_object(query)
|
||||
|
||||
from(
|
||||
[activity, object: o] in query,
|
||||
where: fragment("not (? = ANY(?))", activity.actor, ^blocked_ap_ids),
|
||||
where: fragment("not (? && ?)", activity.recipients, ^blocked_ap_ids),
|
||||
[activity] in query,
|
||||
where:
|
||||
fragment(
|
||||
"not (?->>'type' = 'Announce' and ?->'to' \\?| ?)",
|
||||
activity.data,
|
||||
activity.data,
|
||||
^blocked_ap_ids
|
||||
),
|
||||
where:
|
||||
fragment(
|
||||
"(not (split_part(?, '/', 3) = ANY(?))) or ? = ANY(?)",
|
||||
activity.actor,
|
||||
^domain_blocks,
|
||||
"((not (? && ?)) or (? = ANY(?)))",
|
||||
activity.block_cache,
|
||||
^(blocked_ap_ids ++ domain_blocks),
|
||||
activity.actor,
|
||||
^following_ap_ids
|
||||
),
|
||||
where:
|
||||
fragment(
|
||||
"(not (split_part(?->>'actor', '/', 3) = ANY(?))) or (?->>'actor') = ANY(?)",
|
||||
o.data,
|
||||
activity.data,
|
||||
^domain_blocks,
|
||||
o.data,
|
||||
activity.data,
|
||||
^following_ap_ids
|
||||
)
|
||||
)
|
||||
|
@ -105,6 +105,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
|
||||
|> Map.put("tag", tags)
|
||||
|> Map.put("tag_all", tag_all)
|
||||
|> Map.put("tag_reject", tag_reject)
|
||||
|> Map.put("skip_preload", true)
|
||||
|> ActivityPub.fetch_public_activities()
|
||||
end
|
||||
|
||||
|
1
mix.exs
1
mix.exs
@ -76,6 +76,7 @@ defmodule Pleroma.Mixfile do
|
||||
defp warnings_as_errors(:prod), do: false
|
||||
# Uncomment this if you need testing configurable_from_database logic
|
||||
# defp warnings_as_errors(:dev), do: false
|
||||
defp warnings_as_errors(:benchmark), do: false
|
||||
defp warnings_as_errors(_), do: true
|
||||
|
||||
# Specifies OAuth dependencies.
|
||||
|
@ -0,0 +1,35 @@
|
||||
defmodule Pleroma.Repo.Migrations.AddTagsFieldToActivities do
|
||||
use Ecto.Migration
|
||||
|
||||
def up do
|
||||
alter table(:activities) do
|
||||
add(:tags, {:array, :string})
|
||||
end
|
||||
|
||||
execute("CREATE FUNCTION activities_tags_update() RETURNS trigger AS $$
|
||||
begin
|
||||
IF new.data->>'type' = 'Create' THEN
|
||||
select array_agg(tags->>0) into new.tags from (select jsonb_array_elements(data->'tag') tags from objects where jsonb_typeof(data->'tag') = 'array' and objects.data->>'id' = new.data->>'object') as tags where jsonb_typeof(tags) = 'string';
|
||||
END IF;
|
||||
return new;
|
||||
end
|
||||
$$ LANGUAGE plpgsql")
|
||||
|
||||
execute(
|
||||
"create trigger update_activity_tags before insert or update on activities for each row execute procedure activities_tags_update()"
|
||||
)
|
||||
|
||||
create_if_not_exists(index(:activities, [:tags], using: :gin))
|
||||
end
|
||||
|
||||
def down do
|
||||
drop("trigger if exists update_activity_tags")
|
||||
drop("function if exists activities_tags_update")
|
||||
|
||||
alter table(:activities) do
|
||||
remove(:tags, {:array, :string})
|
||||
end
|
||||
|
||||
drop_if_exists(index(:activities, [:tags], using: :gin))
|
||||
end
|
||||
end
|
@ -0,0 +1,46 @@
|
||||
defmodule Pleroma.Repo.Migrations.AddBlockCacheToActivities do
|
||||
use Ecto.Migration
|
||||
|
||||
def up do
|
||||
alter table(:activities) do
|
||||
add(:block_cache, {:array, :string})
|
||||
end
|
||||
|
||||
create_if_not_exists(index(:activities, [:block_cache], using: :gin))
|
||||
|
||||
statement = """
|
||||
create function activities_block_cache_update() returns trigger as $$
|
||||
DECLARE to_ary varchar[];
|
||||
begin
|
||||
if new.data->>'type' = 'Announce' then
|
||||
SELECT array_cat(array_agg(ary)::varchar[], array_agg(split_part(ary, '/', 3))::varchar[])
|
||||
INTO to_ary
|
||||
FROM jsonb_array_elements_text(new.data->'to') AS ary;
|
||||
|
||||
new.block_cache := array_cat(ARRAY[new.actor, split_part(new.actor, '/', 3)], to_ary);
|
||||
else
|
||||
new.block_cache := array_cat(ARRAY[new.actor, split_part(new.actor, '/', 3)], new.recipients);
|
||||
end if;
|
||||
return new;
|
||||
end
|
||||
$$ language plpgsql
|
||||
"""
|
||||
|
||||
execute(statement)
|
||||
|
||||
execute(
|
||||
"create trigger activities_block_cache_update before insert or update on activities for each row execute procedure activities_block_cache_update()"
|
||||
)
|
||||
end
|
||||
|
||||
def down do
|
||||
execute("drop trigger if exists activities_block_cache_update on activities")
|
||||
execute("drop function if exists activities_block_cache_update()")
|
||||
|
||||
drop_if_exists(index(:activities, [:block_cache], using: :gin))
|
||||
|
||||
alter table(:activities) do
|
||||
remove(:block_cache, {:array, :string})
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user