Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unified channel cache #2528

Merged
merged 17 commits into from
Jan 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ dependencies {

testImplementation("org.junit.jupiter:junit-jupiter:5.8.2")
testImplementation("org.reflections:reflections:0.10.2")
testImplementation("org.mockito:mockito-core:5.8.0")
}

val compileJava: JavaCompile by tasks
Expand Down
13 changes: 1 addition & 12 deletions src/main/java/net/dv8tion/jda/api/JDA.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
*
* @see JDABuilder
*/
public interface JDA extends IGuildChannelContainer
public interface JDA extends IGuildChannelContainer<Channel>
{
/**
* Represents the connection status of JDA and its Main WebSocket.
Expand Down Expand Up @@ -1478,17 +1478,6 @@ default List<ScheduledEvent> getScheduledEventsByName(@Nonnull String name, bool
return getScheduledEventCache().getElementsByName(name, ignoreCase);
}

@Nullable
@Override
default <T extends Channel> T getChannelById(@Nonnull Class<T> type, long id)
{
Checks.notNull(type, "Class");
Channel channel = getPrivateChannelById(id);
if (channel != null)
return type.isInstance(channel) ? type.cast(channel) : null;
return IGuildChannelContainer.super.getChannelById(type, id);
}

/**
* {@link net.dv8tion.jda.api.utils.cache.SnowflakeCacheView SnowflakeCacheView} of
* all cached {@link PrivateChannel PrivateChannels} visible to this JDA session.
Expand Down
25 changes: 20 additions & 5 deletions src/main/java/net/dv8tion/jda/api/entities/Guild.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import net.dv8tion.jda.api.entities.automod.AutoModTriggerType;
import net.dv8tion.jda.api.entities.automod.build.AutoModRuleData;
import net.dv8tion.jda.api.entities.channel.Channel;
import net.dv8tion.jda.api.entities.channel.ChannelType;
import net.dv8tion.jda.api.entities.channel.attribute.ICopyableChannel;
import net.dv8tion.jda.api.entities.channel.attribute.IGuildChannelContainer;
import net.dv8tion.jda.api.entities.channel.attribute.IInviteContainer;
Expand Down Expand Up @@ -59,10 +60,7 @@
import net.dv8tion.jda.api.utils.FileUpload;
import net.dv8tion.jda.api.utils.ImageProxy;
import net.dv8tion.jda.api.utils.MiscUtil;
import net.dv8tion.jda.api.utils.cache.CacheFlag;
import net.dv8tion.jda.api.utils.cache.MemberCacheView;
import net.dv8tion.jda.api.utils.cache.SnowflakeCacheView;
import net.dv8tion.jda.api.utils.cache.SortedSnowflakeCacheView;
import net.dv8tion.jda.api.utils.cache.*;
import net.dv8tion.jda.api.utils.concurrent.Task;
import net.dv8tion.jda.internal.interactions.CommandDataImpl;
import net.dv8tion.jda.internal.requests.DeferredRestAction;
Expand Down Expand Up @@ -93,7 +91,7 @@
* @see JDA#getGuildsByName(String, boolean)
* @see JDA#getGuilds()
*/
public interface Guild extends IGuildChannelContainer, ISnowflake
public interface Guild extends IGuildChannelContainer<GuildChannel>, ISnowflake
{
/** Template for {@link #getIconUrl()}. */
String ICON_URL = "https://cdn.discordapp.com/icons/%s/%s.%s";
Expand Down Expand Up @@ -1561,6 +1559,23 @@ default List<ScheduledEvent> getScheduledEvents()
@Override
SortedSnowflakeCacheView<ForumChannel> getForumChannelCache();

/**
* {@link SortedChannelCacheView SortedChannelCacheView} of {@link GuildChannel}.
*
* <p>Provides cache access to all channels of this guild, including thread channels (unlike {@link #getChannels()}).
* The cache view attempts to provide a sorted list, based on how channels are displayed in the client.
* Various methods like {@link SortedChannelCacheView#forEachUnordered(Consumer)} or {@link SortedChannelCacheView#lockedIterator()}
* bypass sorting for optimization reasons.
*
* <p>It is possible to filter the channels to more specific types using
* {@link ChannelCacheView#getElementById(ChannelType, long)} or {@link SortedChannelCacheView#ofType(Class)}.
*
* @return {@link SortedChannelCacheView SortedChannelCacheView}
*/
@Nonnull
@Override
SortedChannelCacheView<GuildChannel> getChannelCache();

/**
* Populated list of {@link GuildChannel channels} for this guild.
* <br>This includes all types of channels, except for threads.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,24 @@
* @see Category
* @see net.dv8tion.jda.api.entities.Guild#getCategories()
*/
public interface ICategorizableChannel extends GuildChannel, IPermissionContainer
public interface ICategorizableChannel extends GuildChannel, IPermissionContainer, IPositionableChannel
{
@Override
@Nonnull
ICategorizableChannelManager<?, ?> getManager();

/**
* Computes the relative position of this channel in the {@link #getParentCategory() parent category}.
* <br>This is effectively the same as {@code getParentCategory().getChannels().indexOf(channel)}.
*
* @return The relative position in the parent category, or {@code -1} if no parent is set
*/
default int getPositionInCategory()
{
Category parent = getParentCategory();
return parent == null ? -1 : parent.getChannels().indexOf(this);
}

/**
* Get the snowflake of the {@link Category} that contains this channel.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import net.dv8tion.jda.api.sharding.ShardManager;
import net.dv8tion.jda.api.utils.MiscUtil;
import net.dv8tion.jda.api.utils.cache.CacheView;
import net.dv8tion.jda.api.utils.cache.ChannelCacheView;
import net.dv8tion.jda.api.utils.cache.SnowflakeCacheView;
import net.dv8tion.jda.internal.utils.Checks;

Expand All @@ -45,8 +46,20 @@
* <p>For the most efficient usage, it is recommended to use {@link CacheView} getters such as {@link #getTextChannelCache()}.
* List getters usually require making a snapshot copy of the underlying cache view, which may introduce an undesirable performance hit.
*/
public interface IGuildChannelContainer
public interface IGuildChannelContainer<C extends Channel>
{
/**
* Unified cache of all channels associated with this shard or guild.
*
* <p>This {@link ChannelCacheView} stores all channels in individually typed maps based on {@link ChannelType}.
* You can use {@link ChannelCacheView#getElementById(ChannelType, long)} or {@link ChannelCacheView#ofType(Class)} to filter
* out more specific types.
*
* @return {@link ChannelCacheView}
*/
@Nonnull
ChannelCacheView<C> getChannelCache();

/**
* Get a channel of the specified type by id.
*
Expand All @@ -67,7 +80,7 @@ public interface IGuildChannelContainer
* @return The casted channel, if it exists and is assignable to the provided class, or null
*/
@Nullable
default <T extends Channel> T getChannelById(@Nonnull Class<T> type, @Nonnull String id)
default <T extends C> T getChannelById(@Nonnull Class<T> type, @Nonnull String id)
{
return getChannelById(type, MiscUtil.parseSnowflake(id));
}
Expand All @@ -92,11 +105,10 @@ default <T extends Channel> T getChannelById(@Nonnull Class<T> type, @Nonnull St
* @return The casted channel, if it exists and is assignable to the provided class, or null
*/
@Nullable
default <T extends Channel> T getChannelById(@Nonnull Class<T> type, long id)
default <T extends C> T getChannelById(@Nonnull Class<T> type, long id)
{
Checks.notNull(type, "Class");
GuildChannel channel = getGuildChannelById(id);
return type.isInstance(channel) ? type.cast(channel) : null;
return getChannelCache().ofType(type).getElementById(id);
}

/**
Expand Down Expand Up @@ -164,24 +176,8 @@ default GuildChannel getGuildChannelById(@Nonnull String id)
@Nullable
default GuildChannel getGuildChannelById(long id)
{
//TODO-v5-unified-channel-cache
GuildChannel channel = getTextChannelById(id);
if (channel == null)
channel = getNewsChannelById(id);
if (channel == null)
channel = getVoiceChannelById(id);
if (channel == null)
channel = getStageChannelById(id);
if (channel == null)
channel = getCategoryById(id);
if (channel == null)
channel = getThreadChannelById(id);
if (channel == null)
channel = getForumChannelById(id);
if (channel == null)
channel = getMediaChannelById(id);

return channel;
C channel = getChannelCache().getElementById(id);
return channel instanceof GuildChannel ? (GuildChannel) channel : null;
}

/**
Expand Down Expand Up @@ -260,29 +256,8 @@ default GuildChannel getGuildChannelById(@Nonnull ChannelType type, @Nonnull Str
@Nullable
default GuildChannel getGuildChannelById(@Nonnull ChannelType type, long id)
{
Checks.notNull(type, "ChannelType");
switch (type)
{
case NEWS:
return getNewsChannelById(id);
case TEXT:
return getTextChannelById(id);
case VOICE:
return getVoiceChannelById(id);
case STAGE:
return getStageChannelById(id);
case CATEGORY:
return getCategoryById(id);
case FORUM:
return getForumChannelById(id);
case MEDIA:
return getMediaChannelById(id);
}

if (type.isThread())
return getThreadChannelById(id);

return null;
C channel = getChannelCache().getElementById(type, id);
return channel instanceof GuildChannel ? (GuildChannel) channel : null;
}


Expand Down Expand Up @@ -352,7 +327,7 @@ default List<StageChannel> getStageChannelsByName(@Nonnull String name, boolean
@Nullable
default StageChannel getStageChannelById(@Nonnull String id)
{
return getStageChannelCache().getElementById(id);
return (StageChannel) getChannelCache().getElementById(ChannelType.STAGE, id);
}

/**
Expand All @@ -374,7 +349,7 @@ default StageChannel getStageChannelById(@Nonnull String id)
@Nullable
default StageChannel getStageChannelById(long id)
{
return getStageChannelCache().getElementById(id);
return (StageChannel) getChannelCache().getElementById(ChannelType.STAGE, id);
}

/**
Expand Down Expand Up @@ -473,7 +448,7 @@ default List<ThreadChannel> getThreadChannelsByName(@Nonnull String name, boolea
@Nullable
default ThreadChannel getThreadChannelById(@Nonnull String id)
{
return getThreadChannelCache().getElementById(id);
return (ThreadChannel) getChannelCache().getElementById(ChannelType.GUILD_PUBLIC_THREAD, id);
}

/**
Expand All @@ -497,7 +472,7 @@ default ThreadChannel getThreadChannelById(@Nonnull String id)
@Nullable
default ThreadChannel getThreadChannelById(long id)
{
return getThreadChannelCache().getElementById(id);
return (ThreadChannel) getChannelCache().getElementById(ChannelType.GUILD_PUBLIC_THREAD, id);
}

/**
Expand Down Expand Up @@ -595,7 +570,7 @@ default List<Category> getCategoriesByName(@Nonnull String name, boolean ignoreC
@Nullable
default Category getCategoryById(@Nonnull String id)
{
return getCategoryCache().getElementById(id);
return (Category) getChannelCache().getElementById(ChannelType.CATEGORY, id);
}

/**
Expand All @@ -617,7 +592,7 @@ default Category getCategoryById(@Nonnull String id)
@Nullable
default Category getCategoryById(long id)
{
return getCategoryCache().getElementById(id);
return (Category) getChannelCache().getElementById(ChannelType.CATEGORY, id);
}

/**
Expand Down Expand Up @@ -711,7 +686,7 @@ default List<TextChannel> getTextChannelsByName(@Nonnull String name, boolean ig
@Nullable
default TextChannel getTextChannelById(@Nonnull String id)
{
return getTextChannelCache().getElementById(id);
return (TextChannel) getChannelCache().getElementById(ChannelType.TEXT, id);
}

/**
Expand All @@ -733,7 +708,7 @@ default TextChannel getTextChannelById(@Nonnull String id)
@Nullable
default TextChannel getTextChannelById(long id)
{
return getTextChannelCache().getElementById(id);
return (TextChannel) getChannelCache().getElementById(ChannelType.TEXT, id);
}

/**
Expand Down Expand Up @@ -827,7 +802,7 @@ default List<NewsChannel> getNewsChannelsByName(@Nonnull String name, boolean ig
@Nullable
default NewsChannel getNewsChannelById(@Nonnull String id)
{
return getNewsChannelCache().getElementById(id);
return (NewsChannel) getChannelCache().getElementById(ChannelType.NEWS, id);
}

/**
Expand All @@ -849,7 +824,7 @@ default NewsChannel getNewsChannelById(@Nonnull String id)
@Nullable
default NewsChannel getNewsChannelById(long id)
{
return getNewsChannelCache().getElementById(id);
return (NewsChannel) getChannelCache().getElementById(ChannelType.NEWS, id);
}

/**
Expand Down Expand Up @@ -943,7 +918,7 @@ default List<VoiceChannel> getVoiceChannelsByName(@Nonnull String name, boolean
@Nullable
default VoiceChannel getVoiceChannelById(@Nonnull String id)
{
return getVoiceChannelCache().getElementById(id);
return (VoiceChannel) getChannelCache().getElementById(ChannelType.VOICE, id);
}

/**
Expand All @@ -965,7 +940,7 @@ default VoiceChannel getVoiceChannelById(@Nonnull String id)
@Nullable
default VoiceChannel getVoiceChannelById(long id)
{
return getVoiceChannelCache().getElementById(id);
return (VoiceChannel) getChannelCache().getElementById(ChannelType.VOICE, id);
}

/**
Expand Down Expand Up @@ -1058,7 +1033,7 @@ default List<ForumChannel> getForumChannelsByName(@Nonnull String name, boolean
@Nullable
default ForumChannel getForumChannelById(@Nonnull String id)
{
return getForumChannelCache().getElementById(id);
return (ForumChannel) getChannelCache().getElementById(ChannelType.FORUM, id);
}

/**
Expand All @@ -1080,7 +1055,7 @@ default ForumChannel getForumChannelById(@Nonnull String id)
@Nullable
default ForumChannel getForumChannelById(long id)
{
return getForumChannelCache().getElementById(id);
return (ForumChannel) getChannelCache().getElementById(ChannelType.FORUM, id);
}

/**
Expand Down Expand Up @@ -1172,7 +1147,7 @@ default List<MediaChannel> getMediaChannelsByName(@Nonnull String name, boolean
@Nullable
default MediaChannel getMediaChannelById(@Nonnull String id)
{
return getMediaChannelCache().getElementById(id);
return (MediaChannel) getChannelCache().getElementById(ChannelType.MEDIA, id);
}

/**
Expand All @@ -1194,7 +1169,7 @@ default MediaChannel getMediaChannelById(@Nonnull String id)
@Nullable
default MediaChannel getMediaChannelById(long id)
{
return getMediaChannelCache().getElementById(id);
return (MediaChannel) getChannelCache().getElementById(ChannelType.MEDIA, id);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ public interface IPositionableChannel extends GuildChannel
@Nonnull
IPositionableChannelManager<?, ?> getManager();

//TODO-v5: We should probably introduce getPositionInCategory (name pending) that returns index in Category#getChannels or -1

/**
* The position of this channel in the channel list of the guild.
* <br>This does not account for thread channels, as they do not have positions.
Expand Down
Loading
Loading