diff --git a/lib/nostrum/cache/guild_cache/ets.ex b/lib/nostrum/cache/guild_cache/ets.ex index ca102a724..d70b70e63 100644 --- a/lib/nostrum/cache/guild_cache/ets.ex +++ b/lib/nostrum/cache/guild_cache/ets.ex @@ -60,18 +60,21 @@ defmodule Nostrum.Cache.GuildCache.ETS do @doc since: "0.10.0" @spec all() :: Enumerable.t(Guild.t()) def all do - ms = [{{:_, :"$1"}, [], [:"$1"]}] - Stream.resource( - fn -> :ets.select(@table_name, ms, 100) - end, - fn items -> - case items do - {matches, cont} -> - {matches, :ets.select(cont)} - :"$end_of_table" -> {:halt, nil} end - end, - fn _cont -> :ok end - ) + ms = [{{:_, :"$1"}, [], [:"$1"]}] + + Stream.resource( + fn -> :ets.select(@table_name, ms, 100) end, + fn items -> + case items do + {matches, cont} -> + {matches, :ets.select(cont)} + + :"$end_of_table" -> + {:halt, nil} + end + end, + fn _cont -> :ok end + ) end @doc "Create the given guild in the cache." diff --git a/lib/nostrum/cache/guild_cache/mnesia.ex b/lib/nostrum/cache/guild_cache/mnesia.ex index d8b7815d0..5706a5d07 100644 --- a/lib/nostrum/cache/guild_cache/mnesia.ex +++ b/lib/nostrum/cache/guild_cache/mnesia.ex @@ -69,22 +69,26 @@ if Code.ensure_loaded?(:mnesia) do end) end - @impl GuildCache - @doc since: "0.10.0" - @spec all() :: Enumerable.t(Guild.t()) - def all do + @impl GuildCache + @doc since: "0.10.0" + @spec all() :: Enumerable.t(Guild.t()) + def all do ms = [{{:_, :_, :"$1"}, [], [:"$1"]}] + Stream.resource( fn -> :mnesia.select(@table_name, ms, 100, :read) end, fn items -> case items do {matches, cont} -> {matches, :mnesia.select(cont)} - :"$end_of_table" -> {:halt, nil} end + + :"$end_of_table" -> + {:halt, nil} + end end, - fn _cont -> :ok end + fn _cont -> :ok end ) - end + end # Used by dispatch diff --git a/lib/nostrum/cache/member_cache.ex b/lib/nostrum/cache/member_cache.ex index 51132e725..009a53f1c 100644 --- a/lib/nostrum/cache/member_cache.ex +++ b/lib/nostrum/cache/member_cache.ex @@ -37,13 +37,13 @@ defmodule Nostrum.Cache.MemberCache do to wrap calls to this function in `wrap_query/1`. """ @doc since: "0.10.0" - @callback by_user(User.id()) :: {:ok, Enumerable.t({Guild.id(), Member.t()})} | {:error. atom()} + @callback by_user(User.id()) :: Enumerable.t({Guild.id(), Member.t()}) @doc """ Yield an enumerable of members associated with the given guild ID. """ @doc since: "0.10.0" - @callback by_guild(Guild.id()) :: {:ok, Enumerable.t(Member.t())} | {:error. atom()} + @callback by_guild(Guild.id()) :: Enumerable.t(Member.t()) @doc """ Add the member for the given guild from upstream data. @@ -221,13 +221,13 @@ defmodule Nostrum.Cache.MemberCache do Enum.reduce( enumerable, acc, - fn (%Member{user_id: user_id} = member, acc) -> + fn %Member{user_id: user_id} = member, acc -> # credo:disable-for-next-line case UserCache.get(user_id) do {:ok, user} -> fun.({member, user}, acc) _error -> acc end - end + end ) end) end diff --git a/lib/nostrum/cache/member_cache/ets.ex b/lib/nostrum/cache/member_cache/ets.ex index f4776be43..36fda8902 100644 --- a/lib/nostrum/cache/member_cache/ets.ex +++ b/lib/nostrum/cache/member_cache/ets.ex @@ -79,35 +79,41 @@ defmodule Nostrum.Cache.MemberCache.ETS do @impl MemberCache @doc since: "0.10.0" def by_user(user_id) do - ms = [{{{:"$1", user_id}, :"$2"}, [], [{{:"$1", :"$2"}}]}] - Stream.resource( - fn -> :ets.select(@table_name, ms, 100) - end, - fn items -> - case items do - {matches, cont} -> - {matches, :ets.select(cont)} - :"$end_of_table" -> {:halt, nil} end - end, - fn _cont -> :ok end - ) + ms = [{{{:"$1", user_id}, :"$2"}, [], [{{:"$1", :"$2"}}]}] + + Stream.resource( + fn -> :ets.select(@table_name, ms, 100) end, + fn items -> + case items do + {matches, cont} -> + {matches, :ets.select(cont)} + + :"$end_of_table" -> + {:halt, nil} + end + end, + fn _cont -> :ok end + ) end @impl MemberCache @doc since: "0.10.0" def by_guild(guild_id) do - ms = [{{{guild_id, :_}, :"$1"}, [], [:"$1"]}] - Stream.resource( - fn -> :ets.select(@table_name, ms, 100) - end, - fn items -> - case items do - {matches, cont} -> - {matches, :ets.select(cont)} - :"$end_of_table" -> {:halt, nil} end - end, - fn _cont -> :ok end - ) + ms = [{{{guild_id, :_}, :"$1"}, [], [:"$1"]}] + + Stream.resource( + fn -> :ets.select(@table_name, ms, 100) end, + fn items -> + case items do + {matches, cont} -> + {matches, :ets.select(cont)} + + :"$end_of_table" -> + {:halt, nil} + end + end, + fn _cont -> :ok end + ) end @doc "Add the given member to the given guild in the cache." diff --git a/lib/nostrum/cache/member_cache/mnesia.ex b/lib/nostrum/cache/member_cache/mnesia.ex index a94e53c04..9f8d3745e 100644 --- a/lib/nostrum/cache/member_cache/mnesia.ex +++ b/lib/nostrum/cache/member_cache/mnesia.ex @@ -80,15 +80,19 @@ if Code.ensure_loaded?(:mnesia) do @doc since: "0.10.0" def by_user(user_id) do ms = [{{:_, :_, :"$1", user_id, :"$2"}, [], [{{:"$1", :"$2"}}]}] + Stream.resource( fn -> :mnesia.select(@table_name, ms, 100, :read) end, fn items -> case items do {matches, cont} -> {matches, :mnesia.select(cont)} - :"$end_of_table" -> {:halt, nil} end + + :"$end_of_table" -> + {:halt, nil} + end end, - fn _cont -> :ok end + fn _cont -> :ok end ) end @@ -96,15 +100,19 @@ if Code.ensure_loaded?(:mnesia) do @doc since: "0.10.0" def by_guild(guild_id) do ms = [{{:_, :_, guild_id, :_, :"$1"}, [], [:"$1"]}] + Stream.resource( fn -> :mnesia.select(@table_name, ms, 100, :read) end, fn items -> case items do {matches, cont} -> {matches, :mnesia.select(cont)} - :"$end_of_table" -> {:halt, nil} end + + :"$end_of_table" -> + {:halt, nil} + end end, - fn _cont -> :ok end + fn _cont -> :ok end ) end diff --git a/src/nostrum_guild_cache_qlc.erl b/src/nostrum_guild_cache_qlc.erl deleted file mode 100644 index 269ce4d3b..000000000 --- a/src/nostrum_guild_cache_qlc.erl +++ /dev/null @@ -1,9 +0,0 @@ --module(nostrum_guild_cache_qlc). --export([all/1]). - --include_lib("stdlib/include/qlc.hrl"). - -% Optimized channel cache QLC queries. - -all(Cache) -> - qlc:q([Guild || {_GuildId, Guild} <- Cache:query_handle()]). diff --git a/src/nostrum_member_cache_qlc.erl b/src/nostrum_member_cache_qlc.erl deleted file mode 100644 index 93dccc617..000000000 --- a/src/nostrum_member_cache_qlc.erl +++ /dev/null @@ -1,61 +0,0 @@ -% Native QLC operations. -% -% Using QLC from Elixir we pay the price of having to recompile our query -% handle every time we run it. For longer scans like `reduce` this is less of a -% problem, but for queries that users expect to be fast, like a `get` from an -% ETS table, more than a millisecond is unacceptable. -% -% Apart from the recompilation price, queries written using QLC's -% `string_to_handle` also have worse performance than queries written in native -% Erlang, see -% https://elixirforum.com/t/performance-discrepancies-with-using-qlc-queries-written-in-erlang-and-elixir/56006. -% I assume this is caused by the Erlang parse transform doing smart things at compile time. - --module(nostrum_member_cache_qlc). --export([by_user/2, by_guild/2, get_with_users/3]). - --include_lib("stdlib/include/qlc.hrl"). - -% The matching on the cache names here is smelly. But we need it for the -% built-in caches for now. -% -% Implement https://github.com/erlang/otp/issues/7268 to improve it. - --define(MNESIA_CACHE, 'Elixir.Nostrum.Cache.MemberCache.Mnesia'). - -% These must be selected carefully so that QLC can plan using the indices properly. --define(MNESIA_FORMAT, {_Tag, {GuildId, MemberId}, GuildId, MemberId, Member}). --define(MNESIA_FORMAT_NOMEMBERID, {_Tag, {_GuildId, _MemberId}, GuildId, _, Member}). - - --spec by_user('Elixir.Nostrum.Struct.User':id(), module()) -> qlc:query_handle(). -by_user(UserId, ?MNESIA_CACHE) -> - qlc:q([{GuildId, Member} || ?MNESIA_FORMAT <- ?MNESIA_CACHE:query_handle(), - MemberId =:= UserId]); - -by_user(UserId, Cache) -> - qlc:q([{GuildId, Member} || {{GuildId, MemberId}, Member} <- Cache:query_handle(), - MemberId =:= UserId]). - --spec by_guild('Elixir.Nostrum.Struct.Guild':id(), module()) -> qlc:query_handle(). -by_guild(RequestedGuildId, ?MNESIA_CACHE) -> - qlc:q([Member || ?MNESIA_FORMAT_NOMEMBERID <- ?MNESIA_CACHE:query_handle(), - GuildId =:= RequestedGuildId]); - -by_guild(RequestedGuildId, Cache) -> - qlc:q([Member || {{GuildId, _MemberId}, Member} <- Cache:query_handle(), - GuildId =:= RequestedGuildId]). - - --spec get_with_users('Elixir.Nostrum.Struct.Guild':id(), module(), module()) -> qlc:query_handle(). -get_with_users(RequestedGuildId, ?MNESIA_CACHE, UserCache) -> - qlc:q([{Member, User} || ?MNESIA_FORMAT <- ?MNESIA_CACHE:query_handle(), - GuildId =:= RequestedGuildId, - {UserId, User} <- UserCache:query_handle(), - MemberId =:= UserId]); - -get_with_users(RequestedGuildId, MemberCache, UserCache) -> - qlc:q([{Member, User} || {{GuildId, MemberId}, Member} <- MemberCache:query_handle(), - GuildId =:= RequestedGuildId, - {UserId, User} <- UserCache:query_handle(), - MemberId =:= UserId]).