From b0cb64709409a2f45b343cdb94d88f1074b5bd51 Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Fri, 19 Apr 2024 23:16:32 +0100 Subject: [PATCH 1/2] Nuke the ChannelCache from existence --- examples/cache.ex | 5 +- lib/nostrum/cache/cache_supervisor.ex | 3 +- lib/nostrum/cache/channel_cache.ex | 177 ------------------ lib/nostrum/cache/channel_cache/ets.ex | 91 --------- lib/nostrum/cache/channel_cache/mnesia.ex | 113 ----------- lib/nostrum/cache/channel_cache/noop.ex | 39 ---- lib/nostrum/shard/dispatch.ex | 12 -- lib/nostrum/struct/channel.ex | 52 ++--- mix.exs | 1 - src/nostrum_channel_cache_qlc.erl | 10 - .../nostrum/cache/channel_cache_meta_test.exs | 92 --------- 11 files changed, 21 insertions(+), 574 deletions(-) delete mode 100644 lib/nostrum/cache/channel_cache.ex delete mode 100644 lib/nostrum/cache/channel_cache/ets.ex delete mode 100644 lib/nostrum/cache/channel_cache/mnesia.ex delete mode 100644 lib/nostrum/cache/channel_cache/noop.ex delete mode 100644 src/nostrum_channel_cache_qlc.erl delete mode 100644 test/nostrum/cache/channel_cache_meta_test.exs diff --git a/examples/cache.ex b/examples/cache.ex index 8507fa51c..f43c462a5 100644 --- a/examples/cache.ex +++ b/examples/cache.ex @@ -32,7 +32,7 @@ defmodule ExampleCommands do import Nostrum.Snowflake, only: [is_snowflake: 1] alias Nostrum.Api - alias Nostrum.Cache.{ChannelCache, GuildCache, UserCache} + alias Nostrum.Cache.{GuildCache, UserCache} alias Nostrum.Struct.User # Fetch the defined prefix from our config, however, @@ -66,15 +66,12 @@ defmodule ExampleCommands do {Integer.parse(message_user_id), :parse_id}, {:ok, user} <- get_cached_with_fallback(user_id, &UserCache.get/1, &Api.get_user/1), - {:ok, %{name: channel_name}} <- - get_cached_with_fallback(channel_id, &ChannelCache.get/1, &Api.get_channel/1), {:ok, %{name: guild_name}} <- get_cached_with_fallback(guild_id, &GuildCache.get/1, &Api.get_guild/1) do Api.create_message( channel_id, """ ID #{message_user_id} belongs to: #{User.full_name(user)} - Message sent in channel: ##{channel_name} Channel belongs to guild: #{guild_name} """ ) diff --git a/lib/nostrum/cache/cache_supervisor.ex b/lib/nostrum/cache/cache_supervisor.ex index 6cfe70ece..841f56e4f 100644 --- a/lib/nostrum/cache/cache_supervisor.ex +++ b/lib/nostrum/cache/cache_supervisor.ex @@ -4,9 +4,9 @@ defmodule Nostrum.Cache.CacheSupervisor do See the documentation for the relevant submodules for details: - - `Nostrum.Cache.ChannelCache` - `Nostrum.Cache.GuildCache` - `Nostrum.Cache.Me` + - `Nostrum.Cache.MemberCache` - `Nostrum.Cache.PresenceCache` - `Nostrum.Cache.UserCache` """ @@ -25,7 +25,6 @@ defmodule Nostrum.Cache.CacheSupervisor do Nostrum.Cache.GuildCache, Nostrum.Cache.MemberCache, Nostrum.Cache.UserCache, - Nostrum.Cache.ChannelCache, Nostrum.Cache.PresenceCache ] diff --git a/lib/nostrum/cache/channel_cache.ex b/lib/nostrum/cache/channel_cache.ex deleted file mode 100644 index 799949bab..000000000 --- a/lib/nostrum/cache/channel_cache.ex +++ /dev/null @@ -1,177 +0,0 @@ -defmodule Nostrum.Cache.ChannelCache do - @default_cache_implementation Nostrum.Cache.ChannelCache.ETS - @moduledoc """ - Cache behaviour & dispatcher for direct message channels. - - You can call the functions provided by this module independent of which cache - is configured, and it will dispatch to the configured cache implementation. - The user-facing functions for reading the cache can be found in the "Reading - the cache" section. - - By default, #{@default_cache_implementation} will be used for caching channels. - You can override this in the `:caches` option of the `:nostrum` application - by setting the `:channels` field to a different module implementing the - `Nostrum.Cache.ChannelCache` behaviour. Any module below - `Nostrum.Cache.ChannelCache` can be used as a cache. - - ## Writing your own channel cache - - As with the other caches, the channel cache API consists of three parts: - - - Functions called by nostrum, such as `c:create/1` or `c:update/1`. These - **do not create any objects in the Discord API**, they are purely created to - update the cached data from data that Discord sends us. If you want to create - objects on Discord, use the functions exposed by `Nostrum.Api` instead. - - - the QLC query handle for read operations, `c:query_handle/0`, and - - - the `c:child_spec/1` callback for starting the cache under a supervisor. - - You need to implement all of them for nostrum to work with your custom - cache. - - The "upstream data" wording in this module references the fact that the - data that the channel cache (and other caches) retrieves represents the raw - data we receive from the upstream connection, no attempt is made by nostrum - to sanitize the data before it enters the cache. Caching implementations - need to cast the data to the resulting type themselves. A possible future - improvement would be moving the data casting into this module before the - backing cache implementation is called. - """ - - alias Nostrum.Struct.Channel - alias Nostrum.Struct.Message - alias Nostrum.Util - - @configured_cache :nostrum - |> Application.compile_env( - [:caches, :channels], - @default_cache_implementation - ) - - @typedoc "Specifies the reason for why a lookup operation has failed." - @type reason :: :not_found - - ## Behaviour specification - - # Functions called from nostrum. - @doc "Create a channel in the cache." - @callback create(map) :: Channel.t() - - @doc """ - Update a channel from upstream data. - - Return the original channel before the update, and the updated channel. - """ - @callback update(Channel.t()) :: {Channel.t() | nil, Channel.t()} - - @doc """ - Delete a channel from the cache. - - Return the old channel if it was cached, or `nil` otherwise. - """ - @callback delete(Channel.id()) :: :noop | Channel.t() - - @doc """ - Return a QLC query handle for cache read operations. - - The Erlang manual on [Implementing a QLC - Table](https://www.erlang.org/doc/man/qlc.html#implementing_a_qlc_table) - contains examples for implementation. To prevent full table scans, accept - match specifications in your `TraverseFun` and implement a `LookupFun` as - documented. - - The query handle must return items in the form `{channel_id, channel}`, where: - - `channel_id` is a `t:Nostrum.Struct.Channel.id/0`, and - - `channel` is a `t:Nostrum.Struct.Channel.t/0` - - If your cache needs some form of setup or teardown for QLC queries (such as - opening connections), see `c:wrap_qlc/1`. - """ - @doc since: "0.8.0" - @callback query_handle() :: :qlc.query_handle() - - @doc """ - A function that should wrap any `:qlc` operations. - - If you implement a cache that is backed by a database and want to perform - cleanup and teardown actions such as opening and closing connections, - managing transactions and so on, you want to implement this function. nostrum - will then effectively call `wrap_qlc(fn -> :qlc.e(...) end)`. - - If your cache does not need any wrapping, you can omit this. - """ - @doc since: "0.8.0" - @callback wrap_qlc((-> result)) :: result when result: term() - @optional_callbacks wrap_qlc: 1 - - @doc """ - Retrieve the child specification for starting this mapping under a supervisor. - """ - @doc since: "0.8.0" - @callback child_spec(term()) :: Supervisor.child_spec() - - @doc """ - Look up a channel in the cache, by message or ID. - - An optional second argument can be passed to select the cache to read from. - """ - @spec get(Channel.id() | Message.t()) :: {:ok, Channel.t()} | {:error, reason} - @spec get(Channel.id() | Message.t(), module()) :: {:ok, Channel.t()} | {:error, reason} - def get(channel_or_message), do: get(channel_or_message, @configured_cache) - def get(%Message{channel_id: channel_id}, cache), do: get(channel_id, cache) - - def get(channel_id, cache) do - handle = :nostrum_channel_cache_qlc.get(channel_id, cache) - - wrap_qlc(cache, fn -> - case :qlc.eval(handle) do - [{_channel, channel}] -> - {:ok, channel} - - [] -> - {:error, :not_found} - end - end) - end - - @doc """ - Same as `get/1`, but raises `Nostrum.Error.CacheError` in case of failure. - """ - @spec get!(Channel.id() | Nostrum.Struct.Message.t()) :: no_return | Channel.t() - @spec get!(Channel.id() | Nostrum.Struct.Message.t(), module()) :: no_return | Channel.t() - def get!(channel_or_message), do: get!(channel_or_message, @configured_cache) - def get!(%Message{channel_id: channel_id}, cache), do: get!(channel_id, cache) - - def get!(channel_id, cache) do - channel_id - |> get(cache) - |> Util.bangify_find(channel_id, __MODULE__) - end - - @doc """ - Return the QLC handle of the configured cache. - """ - @doc since: "0.8.0" - defdelegate query_handle(), to: @configured_cache - - @spec wrap_qlc(module(), (-> result)) :: result when result: term() - defp wrap_qlc(cache, fun) do - if function_exported?(cache, :wrap_qlc, 1) do - cache.wrap_qlc(fun) - else - fun.() - end - end - - # Nostrum dispatch - @doc false - defdelegate create(map), to: @configured_cache - @doc false - defdelegate update(channel), to: @configured_cache - @doc false - defdelegate delete(channel_id), to: @configured_cache - - @doc false - defdelegate child_spec(opts), to: @configured_cache -end diff --git a/lib/nostrum/cache/channel_cache/ets.ex b/lib/nostrum/cache/channel_cache/ets.ex deleted file mode 100644 index 74364e4ef..000000000 --- a/lib/nostrum/cache/channel_cache/ets.ex +++ /dev/null @@ -1,91 +0,0 @@ -defmodule Nostrum.Cache.ChannelCache.ETS do - @moduledoc """ - An ETS-based cache for channels outside of guilds. - - The supervisor defined by this module will set up the ETS table associated - with it. - - If you need to get the table reference for the table used by this module, - please use the `table/0` function. - - Note that users should not call the functions not related to this specific - implementation of the cache directly. Instead, call the functions of - `Nostrum.Cache.ChannelCache` directly, which will dispatch to the configured - cache. - """ - @moduledoc since: "0.5.0" - - @behaviour Nostrum.Cache.ChannelCache - - @table_name :nostrum_channels - - alias Nostrum.Cache.ChannelCache - alias Nostrum.Struct.Channel - use Supervisor - - @doc "Start the supervisor." - def start_link(init_arg) do - Supervisor.start_link(__MODULE__, init_arg, name: __MODULE__) - end - - @doc "Set up the cache's ETS table." - @impl Supervisor - def init(_init_arg) do - :ets.new(@table_name, [:set, :public, :named_table]) - Supervisor.init([], strategy: :one_for_one) - end - - @doc "Retrieve the ETS table reference used for the cache." - @doc since: "0.8.0" - @spec table :: :ets.table() - def table, do: @table_name - - @doc "Converts and creates the given map as a channel in the cache." - @impl ChannelCache - @spec create(map) :: Channel.t() - def create(channel) do - parsed = convert(channel) - :ets.insert(@table_name, {channel.id, parsed}) - parsed - end - - @doc "Update the given channel in the cache." - @impl ChannelCache - @spec update(Channel.t()) :: {Channel.t() | nil, Channel.t()} - def update(channel) do - parsed = convert(channel) - - case :ets.lookup(@table_name, channel.id) do - [{_id, old_channel}] -> - :ets.insert(@table_name, {channel.id, parsed}) - {old_channel, parsed} - - [] -> - {nil, parsed} - end - end - - @doc "Delete the channel from the cache by ID." - @impl ChannelCache - @spec delete(Channel.id()) :: :noop | Channel.t() - def delete(id) do - case :ets.lookup(@table_name, id) do - [{_id, channel}] -> - :ets.delete(@table_name, id) - channel - - [] -> - :noop - end - end - - @impl ChannelCache - @doc "Retrieve a query handle for usage with QLC." - @doc since: "0.8.0" - @spec query_handle() :: :qlc.query_handle() - def query_handle, do: :ets.table(@table_name) - - # Converts a map into a Channel - defp convert(%{__struct__: _} = struct), do: struct - defp convert(map), do: Channel.to_struct(map) -end diff --git a/lib/nostrum/cache/channel_cache/mnesia.ex b/lib/nostrum/cache/channel_cache/mnesia.ex deleted file mode 100644 index ceb8dbe6e..000000000 --- a/lib/nostrum/cache/channel_cache/mnesia.ex +++ /dev/null @@ -1,113 +0,0 @@ -if Code.ensure_loaded?(:mnesia) do - defmodule Nostrum.Cache.ChannelCache.Mnesia do - @moduledoc """ - An Mnesia-based cache for channels outside of guilds. - - #{Nostrum.Cache.Base.mnesia_note()} - """ - @moduledoc since: "0.8.0" - - @table_name :nostrum_channels - @record_name @table_name - - @behaviour Nostrum.Cache.ChannelCache - - alias Nostrum.Cache.ChannelCache - alias Nostrum.Struct.Channel - use Supervisor - - @doc "Retrieve the table name used by the cache." - @spec table :: atom() - def table, do: @table_name - - @doc "Clear any objects in the cache." - @spec clear() :: {:atomic, :ok} | {:aborted, term()} - def clear, do: :mnesia.clear_table(@table_name) - - @doc "Drop the table used for caching." - @spec teardown() :: {:atomic, :ok} | {:aborted, term()} - def teardown, do: :mnesia.delete_table(@table_name) - - @doc "Start the supervisor." - def start_link(init_arg) do - Supervisor.start_link(__MODULE__, init_arg, name: __MODULE__) - end - - @impl Supervisor - @doc "Set up the cache's Mnesia table." - def init(_init_arg) do - options = [attributes: [:id, :data], record_name: @record_name] - - case :mnesia.create_table(@table_name, options) do - {:atomic, :ok} -> :ok - {:aborted, {:already_exists, _tab}} -> :ok - end - - Supervisor.init([], strategy: :one_for_one) - end - - @impl ChannelCache - @doc "Creates the given channel in the cache." - @spec create(map) :: Channel.t() - def create(channel) do - parsed = convert(channel) - record = {@record_name, channel.id, parsed} - {:atomic, :ok} = :mnesia.sync_transaction(fn -> :mnesia.write(record) end) - parsed - end - - @impl ChannelCache - @doc "Update the given channel in the cache." - @spec update(Channel.t()) :: {Channel.t() | nil, Channel.t()} - def update(channel) do - parsed = convert(channel) - - :mnesia.activity(:sync_transaction, fn -> - case :mnesia.read(@table_name, channel.id, :write) do - [{_tag, id, old_channel}] -> - :mnesia.write(@table_name, {@record_name, id, parsed}, :write) - {old_channel, parsed} - - [] -> - {nil, parsed} - end - end) - end - - @impl ChannelCache - @doc "Delete the channel from the cache by ID." - @spec delete(Channel.id()) :: :noop | Channel.t() - def delete(id) do - :mnesia.activity(:sync_transaction, fn -> - case :mnesia.read(@table_name, id, :write) do - [{_tag, _id, channel}] -> - :mnesia.delete({@table_name, id}) - channel - - [] -> - :noop - end - end) - end - - @impl ChannelCache - @doc "Retrieve a QLC query handle for the channel cache." - @doc since: "0.8.0" - @spec query_handle :: :qlc.query_handle() - def query_handle do - ms = [{{:_, :"$1", :"$2"}, [], [{{:"$1", :"$2"}}]}] - :mnesia.table(@table_name, {:traverse, {:select, ms}}) - end - - @impl ChannelCache - @doc "Wrap QLC operations in a transaction." - @doc since: "0.8.0" - def wrap_qlc(fun) do - :mnesia.activity(:sync_transaction, fun) - end - - # Converts a map into a Channel - defp convert(%{__struct__: _} = struct), do: struct - defp convert(map), do: Channel.to_struct(map) - end -end diff --git a/lib/nostrum/cache/channel_cache/noop.ex b/lib/nostrum/cache/channel_cache/noop.ex deleted file mode 100644 index 5fdb45225..000000000 --- a/lib/nostrum/cache/channel_cache/noop.ex +++ /dev/null @@ -1,39 +0,0 @@ -defmodule Nostrum.Cache.ChannelCache.NoOp do - @moduledoc """ - A NoOp implementation for the ChannelCache - - This cache does nothing, enable it if you dont need to cache channels - """ - @moduledoc since: "0.9.0" - - @behaviour Nostrum.Cache.ChannelCache - - alias Nostrum.Cache.ChannelCache - alias Nostrum.Struct.Channel - use Supervisor - - @doc "Start the supervisor." - def start_link(init_arg) do - Supervisor.start_link(__MODULE__, init_arg, name: __MODULE__) - end - - @impl Supervisor - def init(_init_arg) do - Supervisor.init([], strategy: :one_for_one) - end - - @impl ChannelCache - def create(channel), do: convert(channel) - - @impl ChannelCache - def update(channel), do: {nil, convert(channel)} - - @impl ChannelCache - def delete(_id), do: :noop - - @impl ChannelCache - def query_handle, do: :qlc.string_to_handle(~c"[].") - - defp convert(%{__struct__: _} = struct), do: struct - defp convert(map), do: Channel.to_struct(map) -end diff --git a/lib/nostrum/shard/dispatch.ex b/lib/nostrum/shard/dispatch.ex index a43606f18..fbcc406f5 100644 --- a/lib/nostrum/shard/dispatch.ex +++ b/lib/nostrum/shard/dispatch.ex @@ -2,7 +2,6 @@ defmodule Nostrum.Shard.Dispatch do @moduledoc false alias Nostrum.Cache.{ - ChannelCache, ChannelGuildMapping, GuildCache, MemberCache, @@ -90,10 +89,6 @@ defmodule Nostrum.Shard.Dispatch do def handle_event(:AUTO_MODERATION_RULE_EXECUTION = event, p, state), do: {event, AutoModerationRuleExecute.to_struct(p), state} - def handle_event(:CHANNEL_CREATE = event, %{type: 1} = p, state) do - {event, ChannelCache.create(p), state} - end - def handle_event(:CHANNEL_CREATE = event, %{type: t} = p, state) when t in [0, 2] do ChannelGuildMapping.create(p.id, p.guild_id) {event, GuildCache.channel_create(p.guild_id, p), state} @@ -104,10 +99,6 @@ defmodule Nostrum.Shard.Dispatch do :noop end - def handle_event(:CHANNEL_DELETE = event, %{type: 1} = p, state) do - {event, ChannelCache.delete(p.id), state} - end - def handle_event(:CHANNEL_DELETE = event, %{type: t} = p, state) when t in [0, 2] do ChannelGuildMapping.delete(p.id) {event, GuildCache.channel_delete(p.guild_id, p.id), state} @@ -294,9 +285,6 @@ defmodule Nostrum.Shard.Dispatch do end def handle_event(:READY = event, p, state) do - p.private_channels - |> Enum.each(fn dm_channel -> ChannelCache.create(dm_channel) end) - ready_guilds = p.guilds |> Enum.map(fn guild -> handle_event(:GUILD_CREATE, guild, state) end) diff --git a/lib/nostrum/struct/channel.ex b/lib/nostrum/struct/channel.ex index 3c9f46bf6..c85d8cee3 100644 --- a/lib/nostrum/struct/channel.ex +++ b/lib/nostrum/struct/channel.ex @@ -29,44 +29,30 @@ defmodule Nostrum.Struct.Channel do "<#766435015768539156>" ``` - ## Channel Cache + ## Channel Caching - The [`ChannelCache`](`Nostrum.Cache.ChannelCache`) module provides functionality for you to retrieve information about any channel that your application can see. It provides two functions: [`get/1`](`Nostrum.Cache.ChannelCache.get/1`) and [`get!/1`](`Nostrum.Cache.ChannelCache.get!/1`). + Channels are cached within the guild object they are a member of. To fetch a cached channel you should use the `Nostrum.Cache.ChannelGuildMapping` cache to map a cache to a guild ID. - ## Example + Once you have a guild ID, you can use the `Nostrum.Cache.GuildCache` to fetch the guild and all channels, then use the `t:Nostrum.Struct.Guild.channels/0` field to find the channel. + + ### Example ```elixir - Nostrum.Cache.ChannelCache.get!(827333533688397865) - %Nostrum.Struct.Channel{ - application_id: nil, - bitrate: nil, - guild_id: 766435015768539156, - icon: nil, - id: 827333533688397865, - last_message_id: nil, - last_pin_timestamp: nil, - name: "announcements", - nsfw: false, - owner_id: nil, - parent_id: nil, - permission_overwrites: [ - %Nostrum.Struct.Overwrite{ - allow: 0, - deny: 2048, - id: 766435015768539156, - type: :role - } - ], - position: 1, - recipients: nil, - topic: nil, - type: 5, - user_limit: nil - } + iex(20)> channel_id = 1229955694258684005 + 1229955694258684005 + iex(21)> guild_id = Nostrum.Cache.ChannelGuildMapping.get(channel_id) + 1226944827137069107 + iex(22)> {:ok, guild} = Nostrum.Cache.GuildCache.get(guild_id) + {:ok, + %Nostrum.Struct.Guild{ + id: 1226944827137069107, + name: "nostrum test", + ... + }} + iex(24)> guild.channels[channel_id].name + "test" ``` - More details of the cache can be found at `Nostrum.Cache.ChannelCache`. - ## Helper Functions This module contains two functions for assisting with channel structs. `mention/1` to convert the channel into a mention as a string, and `link/1` to convert the channel into a hyperlink as a string. Further details and examples are detailed in the [Functions section of this module.](#functions) @@ -695,7 +681,7 @@ defmodule Nostrum.Struct.Channel do ## Examples ```elixir - Nostrum.Cache.ChannelCache.get(381889573426429952) + channel |> Nostrum.Struct.Channel.mention() "<#381889573426429952>" diff --git a/mix.exs b/mix.exs index 40e1d6ce6..c6df715f6 100644 --- a/mix.exs +++ b/mix.exs @@ -53,7 +53,6 @@ defmodule Nostrum.Mixfile do assets: "guides/assets", nest_modules_by_prefix: [ Nostrum.Cache, - Nostrum.Cache.ChannelCache, Nostrum.Cache.ChannelGuildMapping, Nostrum.Cache.GuildCache, Nostrum.Cache.MemberCache, diff --git a/src/nostrum_channel_cache_qlc.erl b/src/nostrum_channel_cache_qlc.erl deleted file mode 100644 index b0e0868a0..000000000 --- a/src/nostrum_channel_cache_qlc.erl +++ /dev/null @@ -1,10 +0,0 @@ --module(nostrum_channel_cache_qlc). --export([get/2]). - --include_lib("stdlib/include/qlc.hrl"). - -% Optimized channel cache QLC queries. - -get(RequestedChannelId, Cache) -> - qlc:q([{ChannelId, Channel} || {ChannelId, Channel} <- Cache:query_handle(), - ChannelId =:= RequestedChannelId]). diff --git a/test/nostrum/cache/channel_cache_meta_test.exs b/test/nostrum/cache/channel_cache_meta_test.exs deleted file mode 100644 index 1284defe6..000000000 --- a/test/nostrum/cache/channel_cache_meta_test.exs +++ /dev/null @@ -1,92 +0,0 @@ -defmodule Nostrum.Cache.ChannelCacheMetaTest do - alias Nostrum.Cache.ChannelCache - alias Nostrum.Struct.Channel - use ExUnit.Case, async: true - - @cache_modules [ - # Dispatchers - ChannelCache, - # Implementations - ChannelCache.ETS, - ChannelCache.Mnesia - ] - - for cache <- @cache_modules do - defmodule :"#{cache}Test" do - use ExUnit.Case - # this is needed because otherwise we cannot access - # the cache in the tests - @cache cache - @test_channel %{ - id: 91231, - name: "Joe's Grumblings" - } - - doctest @cache - - describe "with an empty cache" do - setup do - if function_exported?(@cache, :teardown, 0) do - on_exit(:cleanup, fn -> apply(@cache, :teardown, []) end) - end - - [pid: start_supervised!(@cache)] - end - - test "get/1 returns channel not found" do - assert {:error, :not_found} = ChannelCache.get(123, @cache) - end - - test "create/1 returns channel" do - expected = Channel.to_struct(@test_channel) - assert ^expected = @cache.create(@test_channel) - end - - test "update/1 with a non-existing channel returns :noop" do - updated_channel = %{@test_channel | id: @test_channel.id + 1} - expected = {nil, Channel.to_struct(updated_channel)} - assert ^expected = @cache.update(updated_channel) - end - end - - describe "with cached channel" do - setup do - pid = start_supervised!(@cache) - - if function_exported?(@cache, :teardown, 0) do - on_exit(:cleanup, fn -> apply(@cache, :teardown, []) end) - end - - @cache.create(@test_channel) - [pid: pid] - end - - test "get/1 returns channel" do - expected = Channel.to_struct(@test_channel) - assert {:ok, ^expected} = ChannelCache.get(@test_channel.id, @cache) - end - - test "update/1 updates a channel" do - updated_channel = Map.put(@test_channel, :name, "Craig's Grumbling") - expected = Channel.to_struct(updated_channel) - - {old, new} = @cache.update(updated_channel) - old_name = @test_channel.name - - assert old_name == old.name - assert expected == new - end - - test "delete/1 deletes a channel the channel deleted" do - deleted = @cache.delete(@test_channel.id) - expected = Channel.to_struct(@test_channel) - assert deleted == expected - assert {:error, :not_found} = ChannelCache.get(@test_channel.id, @cache) - - # double delete: - assert :noop == @cache.delete(@test_channel.id) - end - end - end - end -end From e6e1b07e4f8072de232d7afe0504cbf1cda6a10b Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Fri, 19 Apr 2024 23:23:38 +0100 Subject: [PATCH 2/2] Rewrite doc-example to not be a doctest --- lib/nostrum/struct/channel.ex | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/nostrum/struct/channel.ex b/lib/nostrum/struct/channel.ex index c85d8cee3..70adfa323 100644 --- a/lib/nostrum/struct/channel.ex +++ b/lib/nostrum/struct/channel.ex @@ -38,19 +38,17 @@ defmodule Nostrum.Struct.Channel do ### Example ```elixir - iex(20)> channel_id = 1229955694258684005 - 1229955694258684005 - iex(21)> guild_id = Nostrum.Cache.ChannelGuildMapping.get(channel_id) + > guild_id = Nostrum.Cache.ChannelGuildMapping.get(1229955694258684005) 1226944827137069107 - iex(22)> {:ok, guild} = Nostrum.Cache.GuildCache.get(guild_id) + > {:ok, guild} = Nostrum.Cache.GuildCache.get(guild_id) {:ok, %Nostrum.Struct.Guild{ id: 1226944827137069107, - name: "nostrum test", + name: "Craig Cat Zone", ... }} - iex(24)> guild.channels[channel_id].name - "test" + > guild.channels[channel_id].name + "cat-general" ``` ## Helper Functions