optimise notifications query

This commit is contained in:
FloatingGhost 2022-10-11 11:40:43 +01:00
parent 8af50dea36
commit cb9b0d3720
5 changed files with 33 additions and 42 deletions

View file

@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## Unreleased
## Changes
- Follows no longer override domain blocks, a domain block is final
## 2022.10 ## 2022.10
### Added ### Added

View file

@ -240,30 +240,6 @@ def find(following_relationships, follower, following) do
end) end)
end end
@doc """
For a query with joined activity,
keeps rows where activity's actor is followed by user -or- is NOT domain-blocked by user.
"""
def keep_following_or_not_domain_blocked(query, user) do
where(
query,
[_, activity],
fragment(
# "(actor's domain NOT in domain_blocks) OR (actor IS in followed AP IDs)"
"""
NOT (substring(? from '.*://([^/]*)') = ANY(?)) OR
? = ANY(SELECT ap_id FROM users AS u INNER JOIN following_relationships AS fr
ON u.id = fr.following_id WHERE fr.follower_id = ? AND fr.state = ?)
""",
activity.actor,
^user.domain_blocks,
activity.actor,
^User.binary_id(user.id),
^accept_state_code()
)
)
end
defp validate_not_self_relationship(%Changeset{} = changeset) do defp validate_not_self_relationship(%Changeset{} = changeset) do
changeset changeset
|> validate_follower_id_following_id_inequality() |> validate_follower_id_following_id_inequality()

View file

@ -138,7 +138,24 @@ defp exclude_blocked(query, user, opts) do
query query
|> where([n, a], a.actor not in ^blocked_ap_ids) |> where([n, a], a.actor not in ^blocked_ap_ids)
|> FollowingRelationship.keep_following_or_not_domain_blocked(user) |> restrict_domain_blocked(user)
end
defp restrict_domain_blocked(query, user) do
where(
query,
[_, activity],
fragment(
# "(actor's domain NOT in domain_blocks)"
"""
NOT (
substring(? from '.*://([^/]*)') = ANY(?)
)
""",
activity.actor,
^user.domain_blocks
)
)
end end
defp exclude_blockers(query, user) do defp exclude_blockers(query, user) do

View file

@ -63,11 +63,16 @@ def get_friends(user, params \\ %{}) do
def get_notifications(user, params \\ %{}) do def get_notifications(user, params \\ %{}) do
options = cast_params(params) options = cast_params(params)
user query =
|> Notification.for_user_query(options) user
|> restrict(:include_types, options) |> Notification.for_user_query(options)
|> restrict(:exclude_types, options) |> restrict(:include_types, options)
|> restrict(:account_ap_id, options) |> restrict(:exclude_types, options)
|> restrict(:account_ap_id, options)
IO.inspect(Pleroma.Repo.to_sql(:all, query))
query
|> Pagination.fetch_paginated(params) |> Pagination.fetch_paginated(params)
end end

View file

@ -1149,18 +1149,6 @@ test "it doesn't return notifications for domain-blocked non-followed user", %{u
assert Notification.for_user(user) == [] assert Notification.for_user(user) == []
end end
test "it returns notifications for domain-blocked but followed user" do
user = insert(:user)
blocked = insert(:user, ap_id: "http://some-domain.com")
{:ok, user} = User.block_domain(user, "some-domain.com")
{:ok, _, _} = User.follow(user, blocked)
{:ok, _activity} = CommonAPI.post(blocked, %{status: "hey @#{user.nickname}"})
assert length(Notification.for_user(user)) == 1
end
test "it doesn't return notifications for muted thread", %{user: user} do test "it doesn't return notifications for muted thread", %{user: user} do
another_user = insert(:user) another_user = insert(:user)