mirror of
https://git.pleroma.social/pleroma/pleroma.git
synced 2025-02-01 20:02:24 +00:00
Replace Object Cachex with Nebulex
This commit is contained in:
parent
6fb7626822
commit
d17e9b3ea2
25 changed files with 66 additions and 200 deletions
|
@ -43,7 +43,10 @@
|
||||||
# is restricted to this project.
|
# is restricted to this project.
|
||||||
import Config
|
import Config
|
||||||
|
|
||||||
|
config :pleroma, nebulex_cache: Pleroma.Cache
|
||||||
|
|
||||||
config :pleroma, Pleroma.Cache,
|
config :pleroma, Pleroma.Cache,
|
||||||
|
stats: true,
|
||||||
# When using :shards as backend
|
# When using :shards as backend
|
||||||
# backend: :shards,
|
# backend: :shards,
|
||||||
# GC interval for pushing new generation: 12 hrs
|
# GC interval for pushing new generation: 12 hrs
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
import Config
|
import Config
|
||||||
|
|
||||||
|
config :pleroma,
|
||||||
|
nebulex_cache: Pleroma.TestCache
|
||||||
|
|
||||||
# We don't run a server during test. If one is required,
|
# We don't run a server during test. If one is required,
|
||||||
# you can enable the server option below.
|
# you can enable the server option below.
|
||||||
config :pleroma, Pleroma.Web.Endpoint,
|
config :pleroma, Pleroma.Web.Endpoint,
|
||||||
|
|
|
@ -93,7 +93,7 @@ defmodule Pleroma.Application do
|
||||||
# Define workers and child supervisors to be supervised
|
# Define workers and child supervisors to be supervised
|
||||||
children =
|
children =
|
||||||
[
|
[
|
||||||
Pleroma.Cache,
|
{Application.get_env(:pleroma, :nebulex_cache), []},
|
||||||
Pleroma.PromEx,
|
Pleroma.PromEx,
|
||||||
Pleroma.Repo,
|
Pleroma.Repo,
|
||||||
Config.TransferTask,
|
Config.TransferTask,
|
||||||
|
@ -154,7 +154,6 @@ defmodule Pleroma.Application do
|
||||||
[
|
[
|
||||||
build_cachex("used_captcha", ttl_interval: seconds_valid_interval()),
|
build_cachex("used_captcha", ttl_interval: seconds_valid_interval()),
|
||||||
build_cachex("user", default_ttl: 25_000, ttl_interval: 1000, limit: 2500),
|
build_cachex("user", default_ttl: 25_000, ttl_interval: 1000, limit: 2500),
|
||||||
build_cachex("object", default_ttl: 25_000, ttl_interval: 1000, limit: 2500),
|
|
||||||
build_cachex("rich_media", default_ttl: :timer.minutes(120), limit: 5000),
|
build_cachex("rich_media", default_ttl: :timer.minutes(120), limit: 5000),
|
||||||
build_cachex("scrubber", limit: 2500),
|
build_cachex("scrubber", limit: 2500),
|
||||||
build_cachex("scrubber_management", limit: 2500),
|
build_cachex("scrubber_management", limit: 2500),
|
||||||
|
|
|
@ -540,7 +540,7 @@ defmodule Pleroma.Notification do
|
||||||
# For some activities, only notify the author of the object
|
# For some activities, only notify the author of the object
|
||||||
def get_potential_receiver_ap_ids(%{data: %{"type" => type, "object" => object_id}})
|
def get_potential_receiver_ap_ids(%{data: %{"type" => type, "object" => object_id}})
|
||||||
when type in ~w{Like Announce EmojiReact} do
|
when type in ~w{Like Announce EmojiReact} do
|
||||||
case Object.get_cached_by_ap_id(object_id) do
|
case Object.get_by_ap_id(object_id) do
|
||||||
%Object{data: %{"actor" => actor}} ->
|
%Object{data: %{"actor" => actor}} ->
|
||||||
[actor]
|
[actor]
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
defmodule Pleroma.Object do
|
defmodule Pleroma.Object do
|
||||||
use Ecto.Schema
|
use Ecto.Schema
|
||||||
|
use Nebulex.Caching
|
||||||
|
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
|
@ -24,7 +25,7 @@ defmodule Pleroma.Object do
|
||||||
|
|
||||||
@derive {Jason.Encoder, only: [:data]}
|
@derive {Jason.Encoder, only: [:data]}
|
||||||
|
|
||||||
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
@nebulex Pleroma.Config.get([:nebulex_cache], Pleroma.Cache)
|
||||||
|
|
||||||
schema "objects" do
|
schema "objects" do
|
||||||
field(:data, :map)
|
field(:data, :map)
|
||||||
|
@ -52,17 +53,23 @@ defmodule Pleroma.Object do
|
||||||
|
|
||||||
def create(data) do
|
def create(data) do
|
||||||
%Object{}
|
%Object{}
|
||||||
|> Object.change(%{data: data})
|
|> Object.changeset(%{data: data})
|
||||||
|> Repo.insert()
|
|> Repo.insert()
|
||||||
end
|
end
|
||||||
|
|
||||||
def change(struct, params \\ %{}) do
|
def changeset(object, attrs \\ %{}) do
|
||||||
struct
|
object
|
||||||
|> cast(params, [:data])
|
|> cast(attrs, [:data])
|
||||||
|> validate_required([:data])
|
|> validate_required([:data])
|
||||||
|> unique_constraint(:ap_id, name: :objects_unique_apid_index)
|
|> unique_constraint(:ap_id, name: :objects_unique_apid_index)
|
||||||
# Expecting `maybe_handle_hashtags_change/1` to run last:
|
# Expecting `maybe_handle_hashtags_change/1` to run last:
|
||||||
|> maybe_handle_hashtags_change(struct)
|
|> maybe_handle_hashtags_change(object)
|
||||||
|
end
|
||||||
|
|
||||||
|
@decorate cache_evict(cache: @nebulex, key: {Object, object.data["id"]})
|
||||||
|
def update(object, attrs) do
|
||||||
|
changeset(object, attrs)
|
||||||
|
|> Repo.update()
|
||||||
end
|
end
|
||||||
|
|
||||||
# Note: not checking activity type (assuming non-legacy objects are associated with Create act.)
|
# Note: not checking activity type (assuming non-legacy objects are associated with Create act.)
|
||||||
|
@ -122,6 +129,7 @@ defmodule Pleroma.Object do
|
||||||
|
|
||||||
def get_by_ap_id(nil), do: nil
|
def get_by_ap_id(nil), do: nil
|
||||||
|
|
||||||
|
@decorate cacheable(cache: @nebulex, key: {Object, ap_id}, opts: [ttl: 25_000])
|
||||||
def get_by_ap_id(ap_id) do
|
def get_by_ap_id(ap_id) do
|
||||||
Repo.one(from(object in Object, where: fragment("(?)->>'id' = ?", object.data, ^ap_id)))
|
Repo.one(from(object in Object, where: fragment("(?)->>'id' = ?", object.data, ^ap_id)))
|
||||||
end
|
end
|
||||||
|
@ -186,7 +194,7 @@ defmodule Pleroma.Object do
|
||||||
end
|
end
|
||||||
|
|
||||||
true ->
|
true ->
|
||||||
get_cached_by_ap_id(ap_id)
|
get_by_ap_id(ap_id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -204,20 +212,6 @@ defmodule Pleroma.Object do
|
||||||
# Legacy objects can be accessed by anybody
|
# Legacy objects can be accessed by anybody
|
||||||
def authorize_access(%Object{}, %User{}), do: :ok
|
def authorize_access(%Object{}, %User{}), do: :ok
|
||||||
|
|
||||||
@spec get_cached_by_ap_id(String.t()) :: Object.t() | nil
|
|
||||||
def get_cached_by_ap_id(ap_id) do
|
|
||||||
key = "object:#{ap_id}"
|
|
||||||
|
|
||||||
with {:ok, nil} <- @cachex.get(:object_cache, key),
|
|
||||||
object when not is_nil(object) <- get_by_ap_id(ap_id),
|
|
||||||
{:ok, true} <- @cachex.put(:object_cache, key, object) do
|
|
||||||
object
|
|
||||||
else
|
|
||||||
{:ok, object} -> object
|
|
||||||
nil -> nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def make_tombstone(%Object{data: %{"id" => id, "type" => type}}, deleted \\ DateTime.utc_now()) do
|
def make_tombstone(%Object{data: %{"id" => id, "type" => type}}, deleted \\ DateTime.utc_now()) do
|
||||||
%ObjectTombstone{
|
%ObjectTombstone{
|
||||||
id: id,
|
id: id,
|
||||||
|
@ -232,17 +226,16 @@ defmodule Pleroma.Object do
|
||||||
|
|
||||||
with {:ok, object} <-
|
with {:ok, object} <-
|
||||||
object
|
object
|
||||||
|> Object.change(%{data: tombstone})
|
|> Object.update(%{data: tombstone}) do
|
||||||
|> Repo.update() do
|
|
||||||
Hashtag.unlink(object)
|
Hashtag.unlink(object)
|
||||||
{:ok, object}
|
{:ok, object}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@decorate cache_evict(cache: @nebulex, key: {Object, id})
|
||||||
def delete(%Object{data: %{"id" => id}} = object) do
|
def delete(%Object{data: %{"id" => id}} = object) do
|
||||||
with {:ok, _obj} = swap_object_with_tombstone(object),
|
with {:ok, _obj} = swap_object_with_tombstone(object),
|
||||||
deleted_activity = Activity.delete_all_by_object_ap_id(id),
|
deleted_activity = Activity.delete_all_by_object_ap_id(id) do
|
||||||
{:ok, _} <- invalid_object_cache(object) do
|
|
||||||
cleanup_attachments(
|
cleanup_attachments(
|
||||||
Config.get([:instance, :cleanup_attachments]),
|
Config.get([:instance, :cleanup_attachments]),
|
||||||
object
|
object
|
||||||
|
@ -261,30 +254,14 @@ defmodule Pleroma.Object do
|
||||||
|
|
||||||
def cleanup_attachments(_, _), do: {:ok, nil}
|
def cleanup_attachments(_, _), do: {:ok, nil}
|
||||||
|
|
||||||
|
@decorate cache_evict(cache: @nebulex, key: {Object, object.data["id"]})
|
||||||
def prune(%Object{data: %{"id" => _id}} = object) do
|
def prune(%Object{data: %{"id" => _id}} = object) do
|
||||||
with {:ok, object} <- Repo.delete(object),
|
with {:ok, object} <- Repo.delete(object) do
|
||||||
{:ok, _} <- invalid_object_cache(object) do
|
|
||||||
{:ok, object}
|
{:ok, object}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def invalid_object_cache(%Object{data: %{"id" => id}}) do
|
@decorate cache_evict(cache: @nebulex, key: {Object, ap_id})
|
||||||
with {:ok, true} <- @cachex.del(:object_cache, "object:#{id}") do
|
|
||||||
@cachex.del(:web_resp_cache, URI.parse(id).path)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_cache(%Object{data: %{"id" => ap_id}} = object) do
|
|
||||||
@cachex.put(:object_cache, "object:#{ap_id}", object)
|
|
||||||
{:ok, object}
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_and_set_cache(changeset) do
|
|
||||||
with {:ok, object} <- Repo.update(changeset) do
|
|
||||||
set_cache(object)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def increase_replies_count(ap_id) do
|
def increase_replies_count(ap_id) do
|
||||||
Object
|
Object
|
||||||
|> where([o], fragment("?->>'id' = ?::text", o.data, ^to_string(ap_id)))
|
|> where([o], fragment("?->>'id' = ?::text", o.data, ^to_string(ap_id)))
|
||||||
|
@ -302,16 +279,13 @@ defmodule Pleroma.Object do
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|> Repo.update_all([])
|
|> Repo.update_all([])
|
||||||
|> case do
|
|
||||||
{1, [object]} -> set_cache(object)
|
|
||||||
_ -> {:error, "Not found"}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp poll_is_multiple?(%Object{data: %{"anyOf" => [_ | _]}}), do: true
|
defp poll_is_multiple?(%Object{data: %{"anyOf" => [_ | _]}}), do: true
|
||||||
|
|
||||||
defp poll_is_multiple?(_), do: false
|
defp poll_is_multiple?(_), do: false
|
||||||
|
|
||||||
|
@decorate cache_evict(cache: @nebulex, key: {Object, ap_id})
|
||||||
def decrease_replies_count(ap_id) do
|
def decrease_replies_count(ap_id) do
|
||||||
Object
|
Object
|
||||||
|> where([o], fragment("?->>'id' = ?::text", o.data, ^to_string(ap_id)))
|
|> where([o], fragment("?->>'id' = ?::text", o.data, ^to_string(ap_id)))
|
||||||
|
@ -329,12 +303,9 @@ defmodule Pleroma.Object do
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|> Repo.update_all([])
|
|> Repo.update_all([])
|
||||||
|> case do
|
|
||||||
{1, [object]} -> set_cache(object)
|
|
||||||
_ -> {:error, "Not found"}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@decorate cache_evict(cache: @nebulex, key: {Object, ap_id})
|
||||||
def increase_quotes_count(ap_id) do
|
def increase_quotes_count(ap_id) do
|
||||||
Object
|
Object
|
||||||
|> where([o], fragment("?->>'id' = ?::text", o.data, ^to_string(ap_id)))
|
|> where([o], fragment("?->>'id' = ?::text", o.data, ^to_string(ap_id)))
|
||||||
|
@ -352,12 +323,9 @@ defmodule Pleroma.Object do
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|> Repo.update_all([])
|
|> Repo.update_all([])
|
||||||
|> case do
|
|
||||||
{1, [object]} -> set_cache(object)
|
|
||||||
_ -> {:error, "Not found"}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@decorate cache_evict(cache: @nebulex, key: {Object, ap_id})
|
||||||
def decrease_quotes_count(ap_id) do
|
def decrease_quotes_count(ap_id) do
|
||||||
Object
|
Object
|
||||||
|> where([o], fragment("?->>'id' = ?::text", o.data, ^to_string(ap_id)))
|
|> where([o], fragment("?->>'id' = ?::text", o.data, ^to_string(ap_id)))
|
||||||
|
@ -375,12 +343,9 @@ defmodule Pleroma.Object do
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|> Repo.update_all([])
|
|> Repo.update_all([])
|
||||||
|> case do
|
|
||||||
{1, [object]} -> set_cache(object)
|
|
||||||
_ -> {:error, "Not found"}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@decorate cache_evict(cache: @nebulex, key: {Object, ap_id})
|
||||||
def increase_vote_count(ap_id, name, actor) do
|
def increase_vote_count(ap_id, name, actor) do
|
||||||
with %Object{} = object <- Object.normalize(ap_id, fetch: false),
|
with %Object{} = object <- Object.normalize(ap_id, fetch: false),
|
||||||
"Question" <- object.data["type"] do
|
"Question" <- object.data["type"] do
|
||||||
|
@ -404,18 +369,17 @@ defmodule Pleroma.Object do
|
||||||
|> Map.put("voters", voters)
|
|> Map.put("voters", voters)
|
||||||
|
|
||||||
object
|
object
|
||||||
|> Object.change(%{data: data})
|
|> Object.update(%{data: data})
|
||||||
|> update_and_set_cache()
|
|
||||||
else
|
else
|
||||||
_ -> :noop
|
_ -> :noop
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc "Updates data field of an object"
|
@doc "Updates data field of an object"
|
||||||
|
@decorate cache_evict(cache: @nebulex, key: {Object, object.data["id"]})
|
||||||
def update_data(%Object{data: data} = object, attrs \\ %{}) do
|
def update_data(%Object{data: data} = object, attrs \\ %{}) do
|
||||||
object
|
object
|
||||||
|> Object.change(%{data: Map.merge(data || %{}, attrs)})
|
|> Object.update(%{data: Map.merge(data || %{}, attrs)})
|
||||||
|> Repo.update()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def local?(%Object{data: %{"id" => id}}) do
|
def local?(%Object{data: %{"id" => id}}) do
|
||||||
|
|
|
@ -28,8 +28,7 @@ defmodule Pleroma.Object.Fetcher do
|
||||||
{:ok, new_object, _} <-
|
{:ok, new_object, _} <-
|
||||||
Object.Updater.do_update_and_invalidate_cache(
|
Object.Updater.do_update_and_invalidate_cache(
|
||||||
object,
|
object,
|
||||||
new_data,
|
new_data
|
||||||
_touch_changeset? = true
|
|
||||||
) do
|
) do
|
||||||
{:ok, new_object}
|
{:ok, new_object}
|
||||||
else
|
else
|
||||||
|
@ -61,7 +60,7 @@ defmodule Pleroma.Object.Fetcher do
|
||||||
# Note: will create a Create activity, which we need internally at the moment.
|
# Note: will create a Create activity, which we need internally at the moment.
|
||||||
@spec fetch_object_from_id(String.t(), list()) :: {:ok, Object.t()} | {:error | :reject, any()}
|
@spec fetch_object_from_id(String.t(), list()) :: {:ok, Object.t()} | {:error | :reject, any()}
|
||||||
def fetch_object_from_id(id, options \\ []) do
|
def fetch_object_from_id(id, options \\ []) do
|
||||||
with {_, nil} <- {:fetch_object, Object.get_cached_by_ap_id(id)},
|
with {_, nil} <- {:fetch_object, Object.get_by_ap_id(id)},
|
||||||
{_, true} <- {:allowed_depth, Federator.allowed_thread_distance?(options[:depth])},
|
{_, true} <- {:allowed_depth, Federator.allowed_thread_distance?(options[:depth])},
|
||||||
{_, {:ok, data}} <- {:fetch, fetch_and_contain_remote_object_from_id(id)},
|
{_, {:ok, data}} <- {:fetch, fetch_and_contain_remote_object_from_id(id)},
|
||||||
{_, nil} <- {:normalize, Object.normalize(data, fetch: false)},
|
{_, nil} <- {:normalize, Object.normalize(data, fetch: false)},
|
||||||
|
|
|
@ -246,17 +246,7 @@ defmodule Pleroma.Object.Updater do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp maybe_touch_changeset(changeset, true) do
|
def do_update_and_invalidate_cache(orig_object, updated_object) do
|
||||||
updated_at =
|
|
||||||
NaiveDateTime.utc_now()
|
|
||||||
|> NaiveDateTime.truncate(:second)
|
|
||||||
|
|
||||||
Ecto.Changeset.put_change(changeset, :updated_at, updated_at)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp maybe_touch_changeset(changeset, _), do: changeset
|
|
||||||
|
|
||||||
def do_update_and_invalidate_cache(orig_object, updated_object, touch_changeset? \\ false) do
|
|
||||||
orig_object_ap_id = updated_object["id"]
|
orig_object_ap_id = updated_object["id"]
|
||||||
orig_object_data = orig_object.data
|
orig_object_data = orig_object.data
|
||||||
|
|
||||||
|
@ -266,15 +256,9 @@ defmodule Pleroma.Object.Updater do
|
||||||
used_history_in_new_object?: used_history_in_new_object?
|
used_history_in_new_object?: used_history_in_new_object?
|
||||||
} = make_new_object_data_from_update_object(orig_object_data, updated_object)
|
} = make_new_object_data_from_update_object(orig_object_data, updated_object)
|
||||||
|
|
||||||
changeset =
|
preloaded_object = Repo.preload(orig_object, :hashtags)
|
||||||
orig_object
|
|
||||||
|> Repo.preload(:hashtags)
|
|
||||||
|> Object.change(%{data: updated_object_data})
|
|
||||||
|> maybe_touch_changeset(touch_changeset?)
|
|
||||||
|
|
||||||
with {:ok, new_object} <- Repo.update(changeset),
|
with {:ok, new_object} <- Object.update(preloaded_object, %{data: updated_object_data}),
|
||||||
{:ok, _} <- Object.invalid_object_cache(new_object),
|
|
||||||
{:ok, _} <- Object.set_cache(new_object),
|
|
||||||
# The metadata/utils.ex uses the object id for the cache.
|
# The metadata/utils.ex uses the object id for the cache.
|
||||||
{:ok, _} <- Pleroma.Activity.HTML.invalidate_cache_for(new_object.id) do
|
{:ok, _} <- Pleroma.Activity.HTML.invalidate_cache_for(new_object.id) do
|
||||||
if used_history_in_new_object? do
|
if used_history_in_new_object? do
|
||||||
|
|
|
@ -1800,7 +1800,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||||
def enqueue_pin_fetches(%{pinned_objects: pins}) do
|
def enqueue_pin_fetches(%{pinned_objects: pins}) do
|
||||||
# enqueue a task to fetch all pinned objects
|
# enqueue a task to fetch all pinned objects
|
||||||
Enum.each(pins, fn {ap_id, _} ->
|
Enum.each(pins, fn {ap_id, _} ->
|
||||||
if is_nil(Object.get_cached_by_ap_id(ap_id)) do
|
if is_nil(Object.get_by_ap_id(ap_id)) do
|
||||||
Pleroma.Workers.RemoteFetcherWorker.new(%{
|
Pleroma.Workers.RemoteFetcherWorker.new(%{
|
||||||
"op" => "fetch_remote",
|
"op" => "fetch_remote",
|
||||||
"id" => ap_id,
|
"id" => ap_id,
|
||||||
|
|
|
@ -80,7 +80,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|
||||||
|
|
||||||
def object(%{assigns: assigns} = conn, _) do
|
def object(%{assigns: assigns} = conn, _) do
|
||||||
with ap_id <- Endpoint.url() <> conn.request_path,
|
with ap_id <- Endpoint.url() <> conn.request_path,
|
||||||
%Object{} = object <- Object.get_cached_by_ap_id(ap_id),
|
%Object{} = object <- Object.get_by_ap_id(ap_id),
|
||||||
user <- Map.get(assigns, :user, nil),
|
user <- Map.get(assigns, :user, nil),
|
||||||
{_, true} <- {:visible?, Visibility.visible_for_user?(object, user)} do
|
{_, true} <- {:visible?, Visibility.visible_for_user?(object, user)} do
|
||||||
conn
|
conn
|
||||||
|
|
|
@ -81,7 +81,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator do
|
||||||
with actor when is_binary(actor) <- get_field(cng, :actor),
|
with actor when is_binary(actor) <- get_field(cng, :actor),
|
||||||
object when is_binary(object) <- get_field(cng, :object),
|
object when is_binary(object) <- get_field(cng, :object),
|
||||||
%User{} = actor <- User.get_cached_by_ap_id(actor),
|
%User{} = actor <- User.get_cached_by_ap_id(actor),
|
||||||
%Object{} = object <- Object.get_cached_by_ap_id(object),
|
%Object{} = object <- Object.get_by_ap_id(object),
|
||||||
false <- Visibility.public?(object) do
|
false <- Visibility.public?(object) do
|
||||||
same_actor = object.data["actor"] == actor.ap_id
|
same_actor = object.data["actor"] == actor.ap_id
|
||||||
recipients = get_field(cng, :to) ++ get_field(cng, :cc)
|
recipients = get_field(cng, :to) ++ get_field(cng, :cc)
|
||||||
|
|
|
@ -57,7 +57,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations do
|
||||||
|
|
||||||
cng
|
cng
|
||||||
|> validate_change(field_name, fn field_name, object_id ->
|
|> validate_change(field_name, fn field_name, object_id ->
|
||||||
object = Object.get_cached_by_ap_id(object_id) || Activity.get_by_ap_id(object_id)
|
object = Object.get_by_ap_id(object_id) || Activity.get_by_ap_id(object_id)
|
||||||
|
|
||||||
cond do
|
cond do
|
||||||
!object ->
|
!object ->
|
||||||
|
|
|
@ -57,7 +57,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateChatMessageValidator do
|
||||||
def validate_object_nonexistence(cng) do
|
def validate_object_nonexistence(cng) do
|
||||||
cng
|
cng
|
||||||
|> validate_change(:object, fn :object, object_id ->
|
|> validate_change(:object, fn :object, object_id ->
|
||||||
if Object.get_cached_by_ap_id(object_id) do
|
if Object.get_by_ap_id(object_id) do
|
||||||
[{:object, "The object to create already exists"}]
|
[{:object, "The object to create already exists"}]
|
||||||
else
|
else
|
||||||
[]
|
[]
|
||||||
|
|
|
@ -112,7 +112,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CreateGenericValidator do
|
||||||
def validate_object_nonexistence(cng) do
|
def validate_object_nonexistence(cng) do
|
||||||
cng
|
cng
|
||||||
|> validate_change(:object, fn :object, object_id ->
|
|> validate_change(:object, fn :object, object_id ->
|
||||||
if Object.get_cached_by_ap_id(object_id) do
|
if Object.get_by_ap_id(object_id) do
|
||||||
[{:object, "The object to create already exists"}]
|
[{:object, "The object to create already exists"}]
|
||||||
else
|
else
|
||||||
[]
|
[]
|
||||||
|
|
|
@ -668,7 +668,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||||
replies_uris =
|
replies_uris =
|
||||||
with limit when limit > 0 <-
|
with limit when limit > 0 <-
|
||||||
Pleroma.Config.get([:activitypub, :note_replies_output_limit], 0),
|
Pleroma.Config.get([:activitypub, :note_replies_output_limit], 0),
|
||||||
%Object{} = object <- Object.get_cached_by_ap_id(obj_data["id"]) do
|
%Object{} = object <- Object.get_by_ap_id(obj_data["id"]) do
|
||||||
object
|
object
|
||||||
|> Object.self_replies()
|
|> Object.self_replies()
|
||||||
|> select([o], fragment("?->>'id'", o.data))
|
|> select([o], fragment("?->>'id'", o.data))
|
||||||
|
|
|
@ -319,8 +319,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
||||||
)
|
)
|
||||||
|
|
||||||
object
|
object
|
||||||
|> Changeset.change(data: data)
|
|> Object.update(%{data: data})
|
||||||
|> Object.update_and_set_cache()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec add_emoji_reaction_to_object(Activity.t(), Object.t()) ::
|
@spec add_emoji_reaction_to_object(Activity.t(), Object.t()) ::
|
||||||
|
@ -881,8 +880,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
||||||
|
|
||||||
{:ok, object} =
|
{:ok, object} =
|
||||||
activity.object
|
activity.object
|
||||||
|> Object.change(%{data: object_data})
|
|> Object.update(%{data: object_data})
|
||||||
|> Object.update_and_set_cache()
|
|
||||||
|
|
||||||
activity_data =
|
activity_data =
|
||||||
activity.data
|
activity.data
|
||||||
|
|
|
@ -266,7 +266,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
||||||
pinned_objects
|
pinned_objects
|
||||||
|> Enum.sort_by(fn {_, pinned_at} -> pinned_at end, &>=/2)
|
|> Enum.sort_by(fn {_, pinned_at} -> pinned_at end, &>=/2)
|
||||||
|> Enum.map(fn {id, _} ->
|
|> Enum.map(fn {id, _} ->
|
||||||
ObjectView.render("object.json", %{object: Object.get_cached_by_ap_id(id)})
|
ObjectView.render("object.json", %{object: Object.get_by_ap_id(id)})
|
||||||
end)
|
end)
|
||||||
|
|
||||||
%{
|
%{
|
||||||
|
|
|
@ -351,7 +351,7 @@ defmodule Pleroma.Web.CommonAPI do
|
||||||
Activity.normalize(activity.data)
|
Activity.normalize(activity.data)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
object = Object.get_cached_by_ap_id(object.data["id"])
|
object = Object.get_by_ap_id(object.data["id"])
|
||||||
{:ok, answer_activities, object}
|
{:ok, answer_activities, object}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -672,8 +672,7 @@ defmodule Pleroma.Web.CommonAPI do
|
||||||
|
|
||||||
{:ok, object} =
|
{:ok, object} =
|
||||||
object
|
object
|
||||||
|> Object.change(%{data: new_data})
|
|> Object.update(%{data: new_data})
|
||||||
|> Object.update_and_set_cache()
|
|
||||||
|
|
||||||
{:ok, Map.put(activity, :object, object)}
|
{:ok, Map.put(activity, :object, object)}
|
||||||
end
|
end
|
||||||
|
|
|
@ -119,7 +119,7 @@ defmodule Pleroma.Web.Feed.FeedView do
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_href(id) do
|
def get_href(id) do
|
||||||
with %Object{data: %{"external_url" => external_url}} <- Object.get_cached_by_ap_id(id) do
|
with %Object{data: %{"external_url" => external_url}} <- Object.get_by_ap_id(id) do
|
||||||
external_url
|
external_url
|
||||||
else
|
else
|
||||||
_e -> id
|
_e -> id
|
||||||
|
|
|
@ -32,14 +32,9 @@ defmodule Pleroma.ObjectTest do
|
||||||
assert object == found_object
|
assert object == found_object
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "generic changeset" do
|
test "it ensures uniqueness of the ap_id" do
|
||||||
test "it ensures uniqueness of the id" do
|
object = insert(:note)
|
||||||
object = insert(:note)
|
assert {:error, _result} = Object.create(%{id: object.data["id"]})
|
||||||
cs = Object.change(%Object{}, %{data: %{id: object.data["id"]}})
|
|
||||||
assert cs.valid?
|
|
||||||
|
|
||||||
{:error, _result} = Repo.insert(cs)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "deletion function" do
|
describe "deletion function" do
|
||||||
|
@ -57,26 +52,6 @@ defmodule Pleroma.ObjectTest do
|
||||||
|
|
||||||
assert found_object.data["type"] == "Tombstone"
|
assert found_object.data["type"] == "Tombstone"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "ensures cache is cleared for the object" do
|
|
||||||
object = insert(:note)
|
|
||||||
cached_object = Object.get_cached_by_ap_id(object.data["id"])
|
|
||||||
|
|
||||||
assert object == cached_object
|
|
||||||
|
|
||||||
Cachex.put(:web_resp_cache, URI.parse(object.data["id"]).path, "cofe")
|
|
||||||
|
|
||||||
Object.delete(cached_object)
|
|
||||||
|
|
||||||
{:ok, nil} = Cachex.get(:object_cache, "object:#{object.data["id"]}")
|
|
||||||
{:ok, nil} = Cachex.get(:web_resp_cache, URI.parse(object.data["id"]).path)
|
|
||||||
|
|
||||||
cached_object = Object.get_cached_by_ap_id(object.data["id"])
|
|
||||||
|
|
||||||
refute object == cached_object
|
|
||||||
|
|
||||||
assert cached_object.data["type"] == "Tombstone"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "delete attachments" do
|
describe "delete attachments" do
|
||||||
|
@ -320,8 +295,6 @@ defmodule Pleroma.ObjectTest do
|
||||||
fetch: true
|
fetch: true
|
||||||
)
|
)
|
||||||
|
|
||||||
Object.set_cache(object)
|
|
||||||
|
|
||||||
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
||||||
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
||||||
|
|
||||||
|
@ -332,8 +305,6 @@ defmodule Pleroma.ObjectTest do
|
||||||
})
|
})
|
||||||
|
|
||||||
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
|
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
|
||||||
object_in_cache = Object.get_cached_by_ap_id(object.data["id"])
|
|
||||||
assert updated_object == object_in_cache
|
|
||||||
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 8
|
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 8
|
||||||
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 3
|
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 3
|
||||||
end
|
end
|
||||||
|
@ -345,8 +316,6 @@ defmodule Pleroma.ObjectTest do
|
||||||
fetch: true
|
fetch: true
|
||||||
)
|
)
|
||||||
|
|
||||||
Object.set_cache(object)
|
|
||||||
|
|
||||||
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
||||||
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
||||||
|
|
||||||
|
@ -354,8 +323,6 @@ defmodule Pleroma.ObjectTest do
|
||||||
mock_modified.(%Tesla.Env{status: 404, body: ""})
|
mock_modified.(%Tesla.Env{status: 404, body: ""})
|
||||||
|
|
||||||
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
|
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
|
||||||
object_in_cache = Object.get_cached_by_ap_id(object.data["id"])
|
|
||||||
assert updated_object == object_in_cache
|
|
||||||
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
||||||
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
||||||
end) =~
|
end) =~
|
||||||
|
@ -371,8 +338,6 @@ defmodule Pleroma.ObjectTest do
|
||||||
fetch: true
|
fetch: true
|
||||||
)
|
)
|
||||||
|
|
||||||
Object.set_cache(object)
|
|
||||||
|
|
||||||
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
||||||
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
||||||
|
|
||||||
|
@ -383,8 +348,6 @@ defmodule Pleroma.ObjectTest do
|
||||||
})
|
})
|
||||||
|
|
||||||
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: 100)
|
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: 100)
|
||||||
object_in_cache = Object.get_cached_by_ap_id(object.data["id"])
|
|
||||||
assert updated_object == object_in_cache
|
|
||||||
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
||||||
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
||||||
end
|
end
|
||||||
|
@ -396,8 +359,6 @@ defmodule Pleroma.ObjectTest do
|
||||||
fetch: true
|
fetch: true
|
||||||
)
|
)
|
||||||
|
|
||||||
Object.set_cache(object)
|
|
||||||
|
|
||||||
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
||||||
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
||||||
|
|
||||||
|
@ -415,8 +376,6 @@ defmodule Pleroma.ObjectTest do
|
||||||
})
|
})
|
||||||
|
|
||||||
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
|
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
|
||||||
object_in_cache = Object.get_cached_by_ap_id(object.data["id"])
|
|
||||||
assert updated_object == object_in_cache
|
|
||||||
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 8
|
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 8
|
||||||
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 3
|
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 3
|
||||||
|
|
||||||
|
|
|
@ -386,49 +386,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
||||||
|
|
||||||
assert json_response(conn, 404)
|
assert json_response(conn, 404)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it caches a response", %{conn: conn} do
|
|
||||||
note = insert(:note)
|
|
||||||
uuid = String.split(note.data["id"], "/") |> List.last()
|
|
||||||
|
|
||||||
conn1 =
|
|
||||||
conn
|
|
||||||
|> put_req_header("accept", "application/activity+json")
|
|
||||||
|> get("/objects/#{uuid}")
|
|
||||||
|
|
||||||
assert json_response(conn1, :ok)
|
|
||||||
assert Enum.any?(conn1.resp_headers, &(&1 == {"x-cache", "MISS from Pleroma"}))
|
|
||||||
|
|
||||||
conn2 =
|
|
||||||
conn
|
|
||||||
|> put_req_header("accept", "application/activity+json")
|
|
||||||
|> get("/objects/#{uuid}")
|
|
||||||
|
|
||||||
assert json_response(conn1, :ok) == json_response(conn2, :ok)
|
|
||||||
assert Enum.any?(conn2.resp_headers, &(&1 == {"x-cache", "HIT from Pleroma"}))
|
|
||||||
end
|
|
||||||
|
|
||||||
test "cached purged after object deletion", %{conn: conn} do
|
|
||||||
note = insert(:note)
|
|
||||||
uuid = String.split(note.data["id"], "/") |> List.last()
|
|
||||||
|
|
||||||
conn1 =
|
|
||||||
conn
|
|
||||||
|> put_req_header("accept", "application/activity+json")
|
|
||||||
|> get("/objects/#{uuid}")
|
|
||||||
|
|
||||||
assert json_response(conn1, :ok)
|
|
||||||
assert Enum.any?(conn1.resp_headers, &(&1 == {"x-cache", "MISS from Pleroma"}))
|
|
||||||
|
|
||||||
Object.delete(note)
|
|
||||||
|
|
||||||
conn2 =
|
|
||||||
conn
|
|
||||||
|> put_req_header("accept", "application/activity+json")
|
|
||||||
|> get("/objects/#{uuid}")
|
|
||||||
|
|
||||||
assert "Not found" == json_response(conn2, :not_found)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "/activities/:uuid" do
|
describe "/activities/:uuid" do
|
||||||
|
|
|
@ -35,7 +35,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidationTest do
|
||||||
|
|
||||||
test "keeps announced object context", %{valid_announce: valid_announce} do
|
test "keeps announced object context", %{valid_announce: valid_announce} do
|
||||||
assert %Object{data: %{"context" => object_context}} =
|
assert %Object{data: %{"context" => object_context}} =
|
||||||
Object.get_cached_by_ap_id(valid_announce["object"])
|
Object.get_by_ap_id(valid_announce["object"])
|
||||||
|
|
||||||
{:ok, %{"context" => context}, _} =
|
{:ok, %{"context" => context}, _} =
|
||||||
valid_announce
|
valid_announce
|
||||||
|
|
|
@ -40,8 +40,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.DeleteValidationTest do
|
||||||
|
|
||||||
{:ok, _object} =
|
{:ok, _object} =
|
||||||
object
|
object
|
||||||
|> Ecto.Changeset.change(%{data: data})
|
|> Object.update(%{data: data})
|
||||||
|> Object.update_and_set_cache()
|
|
||||||
|
|
||||||
{:error, cng} = ObjectValidator.validate(valid_post_delete, [])
|
{:error, cng} = ObjectValidator.validate(valid_post_delete, [])
|
||||||
assert {:object, {"object not in allowed types", []}} in cng.errors
|
assert {:object, {"object not in allowed types", []}} in cng.errors
|
||||||
|
|
|
@ -8,7 +8,6 @@ defmodule Pleroma.Web.ActivityPub.SideEffects.DeleteTest do
|
||||||
|
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
alias Pleroma.Repo
|
|
||||||
alias Pleroma.Tests.ObanHelpers
|
alias Pleroma.Tests.ObanHelpers
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
|
@ -135,8 +134,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects.DeleteTest do
|
||||||
} do
|
} do
|
||||||
{:ok, _object} =
|
{:ok, _object} =
|
||||||
object
|
object
|
||||||
|> Object.change(%{data: Map.delete(object.data, "actor")})
|
|> Object.update(%{data: Map.delete(object.data, "actor")})
|
||||||
|> Repo.update()
|
|
||||||
|
|
||||||
LoggerMock
|
LoggerMock
|
||||||
|> expect(:error, fn str -> assert str =~ "The object doesn't have an actor" end)
|
|> expect(:error, fn str -> assert str =~ "The object doesn't have an actor" end)
|
||||||
|
|
|
@ -257,8 +257,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
||||||
note_object.data
|
note_object.data
|
||||||
|> Map.put("content", nil)
|
|> Map.put("content", nil)
|
||||||
|
|
||||||
Object.change(note_object, %{data: data})
|
Object.update(note_object, %{data: data})
|
||||||
|> Object.update_and_set_cache()
|
|
||||||
|
|
||||||
User.get_cached_by_ap_id(note.data["actor"])
|
User.get_cached_by_ap_id(note.data["actor"])
|
||||||
|
|
||||||
|
|
5
test/support/test_cache.ex
Normal file
5
test/support/test_cache.ex
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
defmodule Pleroma.TestCache do
|
||||||
|
use Nebulex.Cache,
|
||||||
|
otp_app: :pleroma,
|
||||||
|
adapter: Nebulex.Adapters.Nil
|
||||||
|
end
|
Loading…
Reference in a new issue