diff --git a/lib/mobilizon/actors/actor.ex b/lib/mobilizon/actors/actor.ex index 5e7add0d5..610c68a73 100644 --- a/lib/mobilizon/actors/actor.ex +++ b/lib/mobilizon/actors/actor.ex @@ -351,17 +351,6 @@ defmodule Mobilizon.Actors.Actor do |> URI.decode() end - @doc """ - Clear multiple caches for an actor - """ - # TODO: move to MobilizonWeb - @spec clear_cache(t) :: {:ok, true} - def clear_cache(%__MODULE__{preferred_username: preferred_username, domain: nil}) do - Cachex.del(:activity_pub, "actor_" <> preferred_username) - Cachex.del(:feed, "actor_" <> preferred_username) - Cachex.del(:ics, "actor_" <> preferred_username) - end - @spec build_relay_creation_attrs(map) :: map defp build_relay_creation_attrs(%{url: url, preferred_username: preferred_username}) do %{ diff --git a/lib/mobilizon/actors/actors.ex b/lib/mobilizon/actors/actors.ex index a4f455dd7..8723d2550 100644 --- a/lib/mobilizon/actors/actors.ex +++ b/lib/mobilizon/actors/actors.ex @@ -160,24 +160,6 @@ defmodule Mobilizon.Actors do |> Repo.preload(:organized_events) end - @doc """ - Gets a cached local actor by username. - #TODO: move to MobilizonWeb layer - """ - @spec get_cached_local_actor_by_name(String.t()) :: - {:commit, Actor.t()} | {:ignore, any()} - def get_cached_local_actor_by_name(name) do - Cachex.fetch(:activity_pub, "actor_" <> name, fn "actor_" <> name -> - case get_local_actor_by_name(name) do - nil -> - {:ignore, nil} - - %Actor{} = actor -> - {:commit, actor} - end - end) - end - @doc """ Creates an actor. """ diff --git a/lib/mobilizon/events/events.ex b/lib/mobilizon/events/events.ex index 45a84007d..e3354b386 100644 --- a/lib/mobilizon/events/events.ex +++ b/lib/mobilizon/events/events.ex @@ -225,21 +225,6 @@ defmodule Mobilizon.Events do |> Repo.one() end - # TODO: move to MobilizonWeb - @spec get_cached_public_event_by_uuid_with_preload(String.t()) :: - {:commit, Event.t()} | {:ignore, nil} - def get_cached_public_event_by_uuid_with_preload(uuid) do - Cachex.fetch(:activity_pub, "event_" <> uuid, fn "event_" <> uuid -> - case get_public_event_by_uuid_with_preload(uuid) do - %Event{} = event -> - {:commit, event} - - nil -> - {:ignore, nil} - end - end) - end - @doc """ Creates an event. """ @@ -837,21 +822,6 @@ defmodule Mobilizon.Events do |> Repo.preload(@comment_preloads) end - # TODO: move to MobilizonWeb - @spec get_cached_comment_by_uuid_with_preload(String.t()) :: - {:commit, Comment.t()} | {:ignore, nil} - def get_cached_comment_by_uuid_with_preload(uuid) do - Cachex.fetch(:activity_pub, "comment_" <> uuid, fn "comment_" <> uuid -> - case get_comment_from_uuid_with_preload(uuid) do - %Comment{} = comment -> - {:commit, comment} - - nil -> - {:ignore, nil} - end - end) - end - @doc """ Creates a comment. """ diff --git a/lib/mobilizon_web/cache.ex b/lib/mobilizon_web/cache.ex new file mode 100644 index 000000000..70fba94f7 --- /dev/null +++ b/lib/mobilizon_web/cache.ex @@ -0,0 +1,24 @@ +defmodule MobilizonWeb.Cache do + @moduledoc """ + Facade module which provides access to all cached data. + """ + + alias Mobilizon.Actors.Actor + + alias MobilizonWeb.Cache.ActivityPub + + @caches [:activity_pub, :feed, :ics] + + @doc """ + Clears all caches for an actor. + """ + @spec clear_cache(Actor.t()) :: {:ok, true} + def clear_cache(%Actor{preferred_username: preferred_username, domain: nil}) do + Enum.each(@caches, &Cachex.del(&1, "actor_" <> preferred_username)) + end + + defdelegate get_local_actor_by_name(name), to: ActivityPub + defdelegate get_public_event_by_uuid_with_preload(uuid), to: ActivityPub + defdelegate get_comment_by_uuid_with_preload(uuid), to: ActivityPub + defdelegate get_relay, to: ActivityPub +end diff --git a/lib/mobilizon_web/cache/activity_pub.ex b/lib/mobilizon_web/cache/activity_pub.ex new file mode 100644 index 000000000..06e9e4311 --- /dev/null +++ b/lib/mobilizon_web/cache/activity_pub.ex @@ -0,0 +1,70 @@ +defmodule MobilizonWeb.Cache.ActivityPub do + @moduledoc """ + The ActivityPub related functions. + """ + + alias Mobilizon.{Actors, Events, Service} + alias Mobilizon.Actors.Actor + alias Mobilizon.Events.{Comment, Event} + + @cache :activity_pub + + @doc """ + Gets a local actor by username. + """ + @spec get_local_actor_by_name(String.t()) :: + {:commit, Actor.t()} | {:ignore, nil} + def get_local_actor_by_name(name) do + Cachex.fetch(@cache, "actor_" <> name, fn "actor_" <> name -> + case Actors.get_local_actor_by_name(name) do + %Actor{} = actor -> + {:commit, actor} + + nil -> + {:ignore, nil} + end + end) + end + + @doc """ + Gets a public event by its UUID, with all associations loaded. + """ + @spec get_public_event_by_uuid_with_preload(String.t()) :: + {:commit, Event.t()} | {:ignore, nil} + def get_public_event_by_uuid_with_preload(uuid) do + Cachex.fetch(@cache, "event_" <> uuid, fn "event_" <> uuid -> + case Events.get_public_event_by_uuid_with_preload(uuid) do + %Event{} = event -> + {:commit, event} + + nil -> + {:ignore, nil} + end + end) + end + + @doc """ + Gets a comment by its UUID, with all associations loaded. + """ + @spec get_comment_by_uuid_with_preload(String.t()) :: + {:commit, Comment.t()} | {:ignore, nil} + def get_comment_by_uuid_with_preload(uuid) do + Cachex.fetch(@cache, "comment_" <> uuid, fn "comment_" <> uuid -> + case Events.get_comment_from_uuid_with_preload(uuid) do + %Comment{} = comment -> + {:commit, comment} + + nil -> + {:ignore, nil} + end + end) + end + + @doc """ + Gets a relay. + """ + @spec get_relay :: {:commit, Actor.t()} | {:ignore, nil} + def get_relay do + Cachex.fetch(@cache, "relay_actor", &Service.ActivityPub.Relay.get_actor/0) + end +end diff --git a/lib/mobilizon_web/controllers/activity_pub_controller.ex b/lib/mobilizon_web/controllers/activity_pub_controller.ex index 6fa703f59..0c749c963 100644 --- a/lib/mobilizon_web/controllers/activity_pub_controller.ex +++ b/lib/mobilizon_web/controllers/activity_pub_controller.ex @@ -11,6 +11,7 @@ defmodule MobilizonWeb.ActivityPubController do alias Mobilizon.Service.Federator alias MobilizonWeb.ActivityPub.ActorView + alias MobilizonWeb.Cache require Logger @@ -113,13 +114,7 @@ defmodule MobilizonWeb.ActivityPubController do end def relay(conn, _params) do - with {status, actor} <- - Cachex.fetch( - :activity_pub, - "relay_actor", - &Mobilizon.Service.ActivityPub.Relay.get_actor/0 - ), - true <- status in [:ok, :commit] do + with {:commit, %Actor{} = actor} <- Cache.get_relay() do conn |> put_resp_header("content-type", "application/activity+json") |> json(ActorView.render("actor.json", %{actor: actor})) diff --git a/lib/mobilizon_web/controllers/feed_controller.ex b/lib/mobilizon_web/controllers/feed_controller.ex index 3b7a274be..4e4669b7d 100644 --- a/lib/mobilizon_web/controllers/feed_controller.ex +++ b/lib/mobilizon_web/controllers/feed_controller.ex @@ -8,60 +8,60 @@ defmodule MobilizonWeb.FeedController do def actor(conn, %{"name" => name, "format" => "atom"}) do case Cachex.fetch(:feed, "actor_" <> name) do - {status, data} when status in [:ok, :commit] -> + {:commit, data} -> conn |> put_resp_content_type("application/atom+xml") |> send_resp(200, data) - _err -> + _ -> {:error, :not_found} end end def actor(conn, %{"name" => name, "format" => "ics"}) do case Cachex.fetch(:ics, "actor_" <> name) do - {status, data} when status in [:ok, :commit] -> + {:commit, data} -> conn |> put_resp_content_type("text/calendar") |> send_resp(200, data) - _err -> + _ -> {:error, :not_found} end end def event(conn, %{"uuid" => uuid, "format" => "ics"}) do case Cachex.fetch(:ics, "event_" <> uuid) do - {status, data} when status in [:ok, :commit] -> + {:commit, data} -> conn |> put_resp_content_type("text/calendar") |> send_resp(200, data) - _err -> + _ -> {:error, :not_found} end end def going(conn, %{"token" => token, "format" => "ics"}) do case Cachex.fetch(:ics, "token_" <> token) do - {status, data} when status in [:ok, :commit] -> + {:commit, data} -> conn |> put_resp_content_type("text/calendar") |> send_resp(200, data) - _err -> + _ -> {:error, :not_found} end end def going(conn, %{"token" => token, "format" => "atom"}) do case Cachex.fetch(:feed, "token_" <> token) do - {status, data} when status in [:ok, :commit] -> + {:commit, data} -> conn |> put_resp_content_type("application/atom+xml") |> send_resp(200, data) - _err -> + {:ignore, _} -> {:error, :not_found} end end diff --git a/lib/mobilizon_web/controllers/page_controller.ex b/lib/mobilizon_web/controllers/page_controller.ex index d09a4f4bf..6e7f5fe89 100644 --- a/lib/mobilizon_web/controllers/page_controller.ex +++ b/lib/mobilizon_web/controllers/page_controller.ex @@ -3,8 +3,8 @@ defmodule MobilizonWeb.PageController do Controller to load our webapp """ use MobilizonWeb, :controller - alias Mobilizon.Actors - alias Mobilizon.Events + + alias MobilizonWeb.Cache plug(:put_layout, false) action_fallback(MobilizonWeb.FallbackController) @@ -12,17 +12,17 @@ defmodule MobilizonWeb.PageController do def index(conn, _params), do: render(conn, :index) def actor(conn, %{"name" => name}) do - {status, actor} = Actors.get_cached_local_actor_by_name(name) + {status, actor} = Cache.get_local_actor_by_name(name) render_or_error(conn, &ok_status?/2, status, :actor, actor) end def event(conn, %{"uuid" => uuid}) do - {status, event} = Events.get_cached_public_event_by_uuid_with_preload(uuid) + {status, event} = Cache.get_public_event_by_uuid_with_preload(uuid) render_or_error(conn, &ok_status_and_is_visible?/2, status, :event, event) end def comment(conn, %{"uuid" => uuid}) do - {status, comment} = Events.get_cached_comment_by_uuid_with_preload(uuid) + {status, comment} = Cache.get_comment_by_uuid_with_preload(uuid) render_or_error(conn, &ok_status_and_is_visible?/2, status, :comment, comment) end diff --git a/mix.exs b/mix.exs index 920da69ea..853a977ee 100644 --- a/mix.exs +++ b/mix.exs @@ -236,6 +236,7 @@ defmodule Mobilizon.Mixfile do MobilizonWeb.Router.Helpers, MobilizonWeb.AuthErrorHandler, MobilizonWeb.AuthPipeline, + MobilizonWeb.Cache, MobilizonWeb.ChangesetView, MobilizonWeb.Context, MobilizonWeb.Endpoint,