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

Add option to control user cache #816

Merged
merged 1 commit into from Jul 21, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion gradle.properties
@@ -1,2 +1,2 @@
org.gradle.caching = true
version = 3.3.3-SNAPSHOT
version = 3.4.0-SNAPSHOT
22 changes: 22 additions & 0 deletions javacord-api/src/main/java/org/javacord/api/DiscordApiBuilder.java
Expand Up @@ -439,6 +439,28 @@ public DiscordApiBuilder setAllIntentsWhere(Predicate<Intent> condition) {
return this;
}

/**
* Sets whether or not the user cache should be enabled.
*
* <p>By default, the user cache is disabled.
*
* @param enabled Whether or not the user cache should be enabled.
* @return The current instance in order to chain call methods.
*/
public DiscordApiBuilder setUserCacheEnabled(boolean enabled) {
delegate.setUserCacheEnabled(enabled);
return this;
}

/**
* Gets whether or not the user cache is enabled.
*
* @return Whether or not the user cache is enabled.
*/
public boolean isUserCachedEnabled() {
return delegate.isUserCacheEnabled();
}

/**
* Retrieves the recommended shards count from the Discord API and sets it in this builder.
* Sharding allows you to split your bot into several independent instances.
Expand Down
Expand Up @@ -178,6 +178,22 @@ public interface DiscordApiBuilderDelegate {
*/
void setAllIntentsWhere(Predicate<Intent> condition);

/**
* Sets whether or not the user cache should be enabled.
*
* <p>By default, the user cache is disabled.
*
* @param enabled Whether or not the user cache should be enabled.
*/
void setUserCacheEnabled(boolean enabled);

/**
* Gets whether or not the user cache is enabled.
*
* @return Whether or not the user cache is enabled.
*/
boolean isUserCacheEnabled();

/**
* Logs the bot in.
*
Expand Down
Expand Up @@ -129,6 +129,11 @@ public class DiscordApiBuilderDelegateImpl implements DiscordApiBuilderDelegate
private Set<Intent> intents = Arrays.stream(Intent.values())
.filter(intent -> !intent.isPrivileged()).collect(Collectors.toCollection(HashSet::new));

/**
* Whether the user cache should be enabled or not.
*/
private boolean userCacheEnabled = false;

/**
* The globally attachable listeners to register for every created DiscordApi instance.
*/
Expand Down Expand Up @@ -194,7 +199,7 @@ public CompletableFuture<DiscordApi> login() {
new DiscordApiImpl(accountType, token, currentShard.get(), totalShards.get(), intents,
waitForServersOnStartup, waitForUsersOnStartup, registerShutdownHook, globalRatelimiter,
gatewayIdentifyRatelimiter, proxySelector, proxy, proxyAuthenticator, trustAllCertificates,
future, null, preparedListeners, preparedUnspecifiedListeners);
future, null, preparedListeners, preparedUnspecifiedListeners, userCacheEnabled);
}
return future;
}
Expand Down Expand Up @@ -395,6 +400,16 @@ public void setAllIntentsWhere(Predicate<Intent> condition) {
}
}

@Override
public void setUserCacheEnabled(boolean enabled) {
userCacheEnabled = enabled;
}

@Override
public boolean isUserCacheEnabled() {
return userCacheEnabled;
}

@Override
public CompletableFuture<Void> setRecommendedTotalShards() {
CompletableFuture<Void> future = new CompletableFuture<>();
Expand Down
18 changes: 12 additions & 6 deletions javacord-core/src/main/java/org/javacord/core/DiscordApiImpl.java
Expand Up @@ -462,7 +462,7 @@ public DiscordApiImpl(
) {
this(accountType, token, currentShard, totalShards, intents, waitForServersOnStartup, waitForUsersOnStartup,
true, globalRatelimiter, gatewayIdentifyRatelimiter, proxySelector, proxy, proxyAuthenticator,
trustAllCertificates, ready, null, Collections.emptyMap(), Collections.emptyList());
trustAllCertificates, ready, null, Collections.emptyMap(), Collections.emptyList(), false);
}

/**
Expand Down Expand Up @@ -509,7 +509,7 @@ private DiscordApiImpl(
Dns dns) {
this(accountType, token, currentShard, totalShards, intents, waitForServersOnStartup, waitForUsersOnStartup,
true, globalRatelimiter, gatewayIdentifyRatelimiter, proxySelector, proxy, proxyAuthenticator,
trustAllCertificates, ready, dns, Collections.emptyMap(), Collections.emptyList());
trustAllCertificates, ready, dns, Collections.emptyMap(), Collections.emptyList(), false);
}

/**
Expand All @@ -532,13 +532,14 @@ private DiscordApiImpl(
* websocket.
* @param proxyAuthenticator The authenticator that should be used to authenticate against proxies that
* require it.
* @param trustAllCertificates Whether to trust all SSL certificates.
* @param trustAllCertificates Whether to trust all SSL certificates.
* @param ready The future which will be completed when the connection to Discord was
* successful.
* @param dns The DNS instance to use in the OkHttp client. This should only be used in
* testing.
* @param listenerSourceMap The functions to create listeners for pre-registration.
* @param unspecifiedListeners The listeners of unspecified types to pre-register.
* @param unspecifiedListeners The listeners of unspecified types to pre-register.
* @param userCacheEnabled Whether or not the user cache should be enabled.
*/
@SuppressWarnings("unchecked")
public DiscordApiImpl(
Expand All @@ -561,7 +562,9 @@ public DiscordApiImpl(
Map<Class<? extends GloballyAttachableListener>,
List<Function<DiscordApi,GloballyAttachableListener>>
> listenerSourceMap,
List<Function<DiscordApi, GloballyAttachableListener>> unspecifiedListeners) {
List<Function<DiscordApi, GloballyAttachableListener>> unspecifiedListeners,
boolean userCacheEnabled
) {
this.accountType = accountType;
this.token = token;
this.currentShard = currentShard;
Expand All @@ -575,7 +578,7 @@ public DiscordApiImpl(
this.proxyAuthenticator = proxyAuthenticator;
this.trustAllCertificates = trustAllCertificates;
this.intents = intents;
userCacheEnabled = intents.contains(Intent.GUILD_MEMBERS);
this.userCacheEnabled = userCacheEnabled;
this.reconnectDelayProvider = x ->
(int) Math.round(Math.pow(x, 1.5) - (1 / (1 / (0.1 * x) + 1)) * Math.pow(x, 1.5));

Expand Down Expand Up @@ -940,6 +943,9 @@ public void removeChannelFromCache(long channelId) {
* @param member The member to add.
*/
public void addMemberToCacheOrReplaceExisting(Member member) {
if (!isUserCacheEnabled()) {
return;
}
entityCache.getAndUpdate(cache -> {
Member oldMember = cache.getMemberCache()
.getMemberByIdAndServer(member.getId(), member.getServer().getId())
Expand Down
Expand Up @@ -420,10 +420,8 @@ && getMembers().size() < getMemberCount()
.orElse(null);

if (user == null) {
// In theory, every user in "presences" should also be in "members", but Discord is weird
// sometimes. This happens very rarely, but when it happens, we should ignore the presence.
// Ignore rogue presences.
// It might be a similar issue than https://github.com/discordapp/discord-api-docs/issues/855
logger.debug("Found rogue presence. Ignoring it. ({})", presenceJson);
continue;
}

Expand Down