diff --git a/lib/nostrum/cache/guild_cache.ex b/lib/nostrum/cache/guild_cache.ex index cee8f9769..880fd7a79 100644 --- a/lib/nostrum/cache/guild_cache.ex +++ b/lib/nostrum/cache/guild_cache.ex @@ -78,18 +78,14 @@ defmodule Nostrum.Cache.GuildCache do Returns `{:error, :not_found}` if no result was found. """ - @spec get(Guild.id()) :: {:ok, Guild.t()} | {:error, :not_found} - @spec get(Guild.id(), module()) :: {:ok, Guild.t()} | {:error, :not_found} - def get(guild_id, cache \\ @configured_cache) do - handle = :nostrum_guild_cache_qlc.get(guild_id, cache) - - wrap_qlc(cache, fn -> - case :qlc.eval(handle) do - [guild] -> {:ok, guild} - [] -> {:error, :not_found} - end - end) - end + @callback get(Guild.id()) :: {:ok, Guild.t()} | {:error, :not_found} + + @doc """ + Retrieves a single `Nostrum.Struct.Guild` from the cache via its `id`. + + Returns `{:error, :not_found}` if no result was found. + """ + defdelegate get(guild_id), to: @configured_cache # Functions called from nostrum. diff --git a/lib/nostrum/cache/guild_cache/ets.ex b/lib/nostrum/cache/guild_cache/ets.ex index fc94b9b46..0eccf6904 100644 --- a/lib/nostrum/cache/guild_cache/ets.ex +++ b/lib/nostrum/cache/guild_cache/ets.ex @@ -45,6 +45,17 @@ defmodule Nostrum.Cache.GuildCache.ETS do def tabname, do: @table_name # IMPLEMENTATION + + @doc "Get a guild from the cache." + @impl GuildCache + @spec get(Guild.id()) :: {:ok, Guild.t()} | {:error, :not_found} + def get(guild_id) do + case :ets.lookup(@table_name, guild_id) do + [{_id, guild}] -> {:ok, guild} + [] -> {:error, :not_found} + end + end + @doc "Create the given guild in the cache." @impl GuildCache @spec create(map()) :: Guild.t() diff --git a/lib/nostrum/cache/guild_cache/mnesia.ex b/lib/nostrum/cache/guild_cache/mnesia.ex index 04f279559..c60651094 100644 --- a/lib/nostrum/cache/guild_cache/mnesia.ex +++ b/lib/nostrum/cache/guild_cache/mnesia.ex @@ -57,6 +57,18 @@ if Code.ensure_loaded?(:mnesia) do :ok end + @impl GuildCache + @doc "get a guild from the cache." + @spec get(Guild.id()) :: {:ok, Guild.t()} | {:error, :not_found} + def get(guild_id) do + :mnesia.activity(:sync_transaction, fn -> + case :mnesia.read(@table_name, guild_id) do + [{_tag, _id, guild}] -> {:ok, guild} + [] -> {:error, :not_found} + end + end) + end + # Used by dispatch @impl GuildCache diff --git a/lib/nostrum/cache/guild_cache/noop.ex b/lib/nostrum/cache/guild_cache/noop.ex index b87909c2b..7d51d36b4 100644 --- a/lib/nostrum/cache/guild_cache/noop.ex +++ b/lib/nostrum/cache/guild_cache/noop.ex @@ -26,6 +26,9 @@ defmodule Nostrum.Cache.GuildCache.NoOp do Supervisor.init([], strategy: :one_for_one) end + @impl GuildCache + def get(_guild_id), do: {:error, :not_found} + @impl GuildCache def create(payload), do: Guild.to_struct(payload) diff --git a/lib/nostrum/cache/member_cache.ex b/lib/nostrum/cache/member_cache.ex index 5b7b9158c..a3486dca4 100644 --- a/lib/nostrum/cache/member_cache.ex +++ b/lib/nostrum/cache/member_cache.ex @@ -24,6 +24,11 @@ defmodule Nostrum.Cache.MemberCache do @configured_cache Nostrum.Cache.Base.get_cache_module(:members, @default_cache_implementation) + @doc """ + Retrieve a member from the cache by guild and user ID. + """ + @callback get(Guild.id(), Member.user_id()) :: {:ok, Member.t()} | {:error, atom()} + @doc """ Add the member for the given guild from upstream data. @@ -116,7 +121,7 @@ defmodule Nostrum.Cache.MemberCache do @spec get_with_user(Guild.id(), Member.user_id(), module()) :: {Member.t(), User.t() | nil} | nil def get_with_user(guild_id, member_id, cache \\ @configured_cache) do - case get(guild_id, member_id, cache) do + case cache.get(guild_id, member_id) do {:ok, member} -> case UserCache.get(member_id) do {:ok, user} -> @@ -152,20 +157,7 @@ defmodule Nostrum.Cache.MemberCache do Get a single member on the given guild ID. """ @spec get(Guild.id(), Member.user_id()) :: {:ok, Member.t()} | {:error, atom()} - @spec get(Guild.id(), Member.user_id(), module()) :: {:ok, Member.t()} | {:error, atom()} - def get(guild_id, user_id, cache \\ @configured_cache) do - handle = :nostrum_member_cache_qlc.lookup(guild_id, user_id, cache) - - wrap_qlc(cache, fn -> - case :qlc.e(handle) do - [result] -> - {:ok, result} - - [] -> - {:error, :not_found} - end - end) - end + defdelegate get(guild_id, member_id), to: @configured_cache @doc """ Fold (reduce) over members for the given guild ID. diff --git a/lib/nostrum/cache/member_cache/ets.ex b/lib/nostrum/cache/member_cache/ets.ex index 4a93d6d35..ec5b3d601 100644 --- a/lib/nostrum/cache/member_cache/ets.ex +++ b/lib/nostrum/cache/member_cache/ets.ex @@ -63,6 +63,19 @@ defmodule Nostrum.Cache.MemberCache.ETS do # Used by dispatch + @impl MemberCache + @doc "Retrieve the member for the given guild and user in the cache." + @spec get(Guild.id(), Member.user_id()) :: {:ok, Member.t()} | {:error, any()} + def get(guild_id, user_id) do + case :ets.lookup(@table_name, {guild_id, user_id}) do + [{_, member}] -> + {:ok, member} + + [] -> + {:error, :member_not_found} + end + end + @doc "Add the given member to the given guild in the cache." @impl MemberCache @spec create(Guild.id(), map()) :: Member.t() diff --git a/lib/nostrum/cache/member_cache/mnesia.ex b/lib/nostrum/cache/member_cache/mnesia.ex index 89802a0ee..49c280a62 100644 --- a/lib/nostrum/cache/member_cache/mnesia.ex +++ b/lib/nostrum/cache/member_cache/mnesia.ex @@ -62,6 +62,20 @@ if Code.ensure_loaded?(:mnesia) do # Used by dispatch + @impl MemberCache + @doc "Retrieve the member for the given guild and user in the cache." + @spec get(Guild.id(), Member.user_id()) :: {:ok, Member.t()} | {:error, any()} + def get(guild_id, user_id) do + key = {guild_id, user_id} + + :mnesia.activity(:sync_transaction, fn -> + case :mnesia.read(@table_name, key) do + [{_tag, _key, _guild_id, _user_id, member}] -> {:ok, member} + [] -> {:error, :member_not_found} + end + end) + end + @impl MemberCache @doc "Add the given member to the given guild in the cache." @spec create(Guild.id(), map()) :: Member.t() diff --git a/lib/nostrum/cache/member_cache/noop.ex b/lib/nostrum/cache/member_cache/noop.ex index 41cb19309..adeda5842 100644 --- a/lib/nostrum/cache/member_cache/noop.ex +++ b/lib/nostrum/cache/member_cache/noop.ex @@ -22,6 +22,9 @@ defmodule Nostrum.Cache.MemberCache.NoOp do Supervisor.init([], strategy: :one_for_one) end + @impl MemberCache + def get(_guild_id, _user_id), do: {:error, :member_not_found} + @impl MemberCache def create(_guild_id, payload), do: Util.cast(payload, {:struct, Member}) diff --git a/lib/nostrum/cache/presence_cache.ex b/lib/nostrum/cache/presence_cache.ex index 799d39495..27d5303dc 100644 --- a/lib/nostrum/cache/presence_cache.ex +++ b/lib/nostrum/cache/presence_cache.ex @@ -60,18 +60,10 @@ defmodule Nostrum.Cache.PresenceCache do end ``` """ - @spec get(Guild.id(), User.id()) :: {:ok, presence()} | {:error, :presence_not_found} - @spec get(Guild.id(), User.id(), module()) :: {:ok, presence()} | {:error, :presence_not_found} - def get(guild_id, user_id, cache \\ @configured_cache) do - handle = :nostrum_presence_cache_qlc.get(guild_id, user_id, cache) - - wrap_qlc(cache, fn -> - case :qlc.eval(handle) do - [presence] -> {:ok, presence} - [] -> {:error, :not_found} - end - end) - end + @spec get(Guild.id(), User.id()) :: {:ok, presence()} | {:error, any()} + defdelegate get(guild_id, user_id), to: @configured_cache + + @callback get(Guild.id(), User.id()) :: {:ok, presence()} | {:error, any()} @doc """ Create a presence in the cache. @@ -154,7 +146,7 @@ defmodule Nostrum.Cache.PresenceCache do def get!(guild_id, user_id, cache \\ @configured_cache) when is_snowflake(user_id) and is_snowflake(guild_id) do guild_id - |> get(user_id, cache) + |> get(user_id) |> Util.bangify_find({guild_id, user_id}, cache) end diff --git a/lib/nostrum/cache/presence_cache/ets.ex b/lib/nostrum/cache/presence_cache/ets.ex index a5a6b2276..c99529cb1 100644 --- a/lib/nostrum/cache/presence_cache/ets.ex +++ b/lib/nostrum/cache/presence_cache/ets.ex @@ -15,6 +15,8 @@ defmodule Nostrum.Cache.PresenceCache.ETS do @table_name :nostrum_presences alias Nostrum.Struct.Guild + alias Nostrum.Struct.User + use Supervisor @doc "Start the supervisor." @@ -34,6 +36,16 @@ defmodule Nostrum.Cache.PresenceCache.ETS do Supervisor.init([], strategy: :one_for_one) end + @impl PresenceCache + @doc "Retrieve a presence from the cache." + @spec get(Guild.id(), User.id()) :: {:ok, PresenceCache.presence()} | {:error, any} + def get(guild_id, user_id) do + case :ets.lookup(@table_name, {guild_id, user_id}) do + [{_, presence}] -> {:ok, presence} + [] -> {:error, :presence_not_found} + end + end + @impl PresenceCache @doc "Add the given presence data to the cache." @spec create(map) :: :ok diff --git a/lib/nostrum/cache/presence_cache/mnesia.ex b/lib/nostrum/cache/presence_cache/mnesia.ex index 5d312b389..1a5213cd3 100644 --- a/lib/nostrum/cache/presence_cache/mnesia.ex +++ b/lib/nostrum/cache/presence_cache/mnesia.ex @@ -13,7 +13,10 @@ if Code.ensure_loaded?(:mnesia) do @behaviour Nostrum.Cache.PresenceCache alias Nostrum.Cache.PresenceCache + alias Nostrum.Struct.Guild + alias Nostrum.Struct.User + use Supervisor @doc "Retrieve the table name used by the cache." @@ -46,6 +49,18 @@ if Code.ensure_loaded?(:mnesia) do Supervisor.init([], strategy: :one_for_one) end + @impl PresenceCache + @doc "Retrieve a presence from the cache." + @spec get(Guild.id(), User.id()) :: {:ok, PresenceCache.presence()} | {:error, any} + def get(guild_id, user_id) do + :mnesia.activity(:sync_transaction, fn -> + case :mnesia.read(@table_name, {guild_id, user_id}) do + [{_tag, _key, presence}] -> {:ok, presence} + [] -> {:error, :presence_not_found} + end + end) + end + @impl PresenceCache @doc "Add the given presence to the cache." @spec create(map()) :: :ok diff --git a/lib/nostrum/cache/presence_cache/noop.ex b/lib/nostrum/cache/presence_cache/noop.ex index e05430222..d1033ccd4 100644 --- a/lib/nostrum/cache/presence_cache/noop.ex +++ b/lib/nostrum/cache/presence_cache/noop.ex @@ -8,7 +8,10 @@ defmodule Nostrum.Cache.PresenceCache.NoOp do @behaviour Nostrum.Cache.PresenceCache alias Nostrum.Cache.PresenceCache + alias Nostrum.Struct.Guild + alias Nostrum.Struct.User + use Supervisor @doc "Start the supervisor." @@ -22,6 +25,10 @@ defmodule Nostrum.Cache.PresenceCache.NoOp do Supervisor.init([], strategy: :one_for_one) end + @impl PresenceCache + @spec get(Guild.id(), User.id()) :: {:ok, map()} | {:error, any()} + def get(_guild_id, _user_id), do: {:error, :presence_not_found} + @impl PresenceCache @spec create(map) :: :ok def create(_presence), do: :ok diff --git a/test/nostrum/cache/guild_cache_meta_test.exs b/test/nostrum/cache/guild_cache_meta_test.exs index 33398942f..03e55d69e 100644 --- a/test/nostrum/cache/guild_cache_meta_test.exs +++ b/test/nostrum/cache/guild_cache_meta_test.exs @@ -90,7 +90,7 @@ defmodule Nostrum.Cache.GuildCacheMetaTest do created = @cache.channel_create(@test_guild.id, @test_channel) expected = Channel.to_struct(@test_channel) assert ^expected = created - {:ok, cached} = GuildCache.get(@test_guild.id, @cache) + {:ok, cached} = @cache.get(@test_guild.id) channels = %{expected.id => expected} assert ^channels = cached.channels @@ -128,7 +128,7 @@ defmodule Nostrum.Cache.GuildCacheMetaTest do assert ^expected_return = @cache.role_create(@test_guild.id, @test_role) assert {:ok, %Guild{roles: %{^role_id => ^expected_role_struct}}} = - GuildCache.get(@test_guild.id, @cache) + @cache.get(@test_guild.id) # role_update/2 updated_payload = Map.put(@test_role, :name, "Higher Sharders") @@ -139,7 +139,7 @@ defmodule Nostrum.Cache.GuildCacheMetaTest do # role_delete/2 {_guild_id, ^new_role} = @cache.role_delete(@test_guild.id, @test_role.id) - {:ok, guild} = GuildCache.get(@test_guild.id, @cache) + {:ok, guild} = @cache.get(@test_guild.id) assert guild.roles == %{} end end @@ -152,11 +152,11 @@ defmodule Nostrum.Cache.GuildCacheMetaTest do end test "member count operations" do - assert {:ok, %{member_count: 0}} = GuildCache.get(@test_guild.id, @cache) + assert {:ok, %{member_count: 0}} = @cache.get(@test_guild.id) assert @cache.member_count_up(@test_guild.id) - assert {:ok, %{member_count: 1}} = GuildCache.get(@test_guild.id, @cache) + assert {:ok, %{member_count: 1}} = @cache.get(@test_guild.id) assert @cache.member_count_down(@test_guild.id) - assert {:ok, %{member_count: 0}} = GuildCache.get(@test_guild.id, @cache) + assert {:ok, %{member_count: 0}} = @cache.get(@test_guild.id) end test "member count operations for uncached guild" do diff --git a/test/nostrum/cache/presence_cache_meta_test.exs b/test/nostrum/cache/presence_cache_meta_test.exs index a7fb90cf3..d359a51ac 100644 --- a/test/nostrum/cache/presence_cache_meta_test.exs +++ b/test/nostrum/cache/presence_cache_meta_test.exs @@ -58,8 +58,8 @@ defmodule Nostrum.Cache.PresenceCacheMetaTest do describe "empty cache" do test "lookup of nonexistent user" do - assert {:error, :not_found} = - PresenceCache.get(@test_guild_id, @test_presence.user.id + 1, @cache) + assert {:error, :presence_not_found} = + @cache.get(@test_guild_id, @test_presence.user.id + 1) end test "create, update, delete" do @@ -71,7 +71,7 @@ defmodule Nostrum.Cache.PresenceCacheMetaTest do assert :noop = @cache.update(@test_presence) assert {:ok, ^test_presence} = - PresenceCache.get(@test_guild_id, test_presence.user.id, @cache) + @cache.get(@test_guild_id, test_presence.user.id) updated_presence = Map.put(@test_presence, :status, :offline) @@ -87,8 +87,8 @@ defmodule Nostrum.Cache.PresenceCacheMetaTest do user_2_presence = %{status: :offline, user: %{id: user_2_id}} presences = [user_1_presence, user_2_presence] assert :ok = @cache.bulk_create(guild_id, presences) - assert {:ok, ^user_1_presence} = PresenceCache.get(guild_id, user_1_id, @cache) - assert {:ok, ^user_2_presence} = PresenceCache.get(guild_id, user_2_id, @cache) + assert {:ok, ^user_1_presence} = @cache.get(guild_id, user_1_id) + assert {:ok, ^user_2_presence} = @cache.get(guild_id, user_2_id) end test "bulk_create/2 with empty presences" do