Improve lifecycle

This commit is contained in:
Vankka 2024-12-04 23:15:16 +02:00
parent 56c1baa830
commit 56cb74815c
No known key found for this signature in database
GPG Key ID: 62E48025ED4E7EBB
24 changed files with 377 additions and 359 deletions

View File

@ -38,8 +38,7 @@ import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.function.Predicate;
import java.util.Optional;
/**
* The DiscordSRV API.
@ -156,7 +155,6 @@ public interface DiscordSRVApi {
* <p>
* JDA is an external library and comes with its own versioning and deprecation policies, using DiscordSRV's own APIs where possible is recommended.
* DiscordSRV will upgrade JDA as needed, including breaking changes and major version upgrades.
*
* <a href="https://github.com/DV8FromTheWorld/JDA#deprecation-policy">JDA's deprecation policy</a>
*
* @see #discordAPI() discordAPI() for the first party api
@ -271,50 +269,6 @@ public interface DiscordSRVApi {
}
enum ReloadFlag {
CONFIG(false),
LINKED_ACCOUNT_PROVIDER(false),
STORAGE(true),
DISCORD_CONNECTION(DiscordSRVApi::isReady),
MODULES(false),
DISCORD_COMMANDS(false),
// Bukkit only
TRANSLATIONS(false)
;
public static final Set<ReloadFlag> ALL = Collections.unmodifiableSet(new LinkedHashSet<>(Arrays.asList(values())));
public static final Set<ReloadFlag> DEFAULT_FLAGS = Collections.unmodifiableSet(new LinkedHashSet<>(Arrays.asList(CONFIG, MODULES)));
private final Predicate<DiscordSRVApi> requiresConfirm;
ReloadFlag(boolean requiresConfirm) {
this(__ -> requiresConfirm);
}
ReloadFlag(Predicate<DiscordSRVApi> requiresConfirm) {
this.requiresConfirm = requiresConfirm;
}
public boolean requiresConfirm(DiscordSRVApi discordSRV) {
return requiresConfirm.test(discordSRV);
}
}
interface ReloadResult {
ReloadResult RESTART_REQUIRED = DefaultConstants.RESTART_REQUIRED;
String name();
enum DefaultConstants implements ReloadResult {
RESTART_REQUIRED
}
}
@ApiStatus.Internal
@SuppressWarnings("unused") // API, Reflection
final class InstanceHolder {

View File

@ -23,8 +23,8 @@
package com.discordsrv.api.events.lifecycle;
import com.discordsrv.api.DiscordSRVApi;
import com.discordsrv.api.events.Event;
import com.discordsrv.api.reload.ReloadFlag;
import java.util.Set;
@ -33,17 +33,17 @@ import java.util.Set;
*/
public class DiscordSRVReloadedEvent implements Event {
private final Set<DiscordSRVApi.ReloadFlag> flags;
private final Set<ReloadFlag> flags;
public DiscordSRVReloadedEvent(Set<DiscordSRVApi.ReloadFlag> flags) {
public DiscordSRVReloadedEvent(Set<ReloadFlag> flags) {
this.flags = flags;
}
/**
* Set of DiscordSRV systems that were reloaded.
* @return an unmodifiable set of {@link com.discordsrv.api.DiscordSRVApi.ReloadFlag}s
* @return an unmodifiable set of {@link ReloadFlag}s
*/
public Set<DiscordSRVApi.ReloadFlag> flags() {
public Set<ReloadFlag> flags() {
return flags;
}
}

View File

@ -30,6 +30,7 @@ import com.discordsrv.api.discord.connection.details.DiscordMemberCachePolicy;
import com.discordsrv.api.eventbus.EventListener;
import com.discordsrv.api.eventbus.Subscribe;
import com.discordsrv.api.events.discord.message.AbstractDiscordMessageEvent;
import com.discordsrv.api.reload.ReloadResult;
import net.dv8tion.jda.api.events.GenericEvent;
import net.dv8tion.jda.api.events.guild.member.GenericGuildMemberEvent;
import net.dv8tion.jda.api.requests.GatewayIntent;
@ -161,5 +162,5 @@ public interface Module {
* Called by DiscordSRV to reload this module. This is called when the module is enabled as well.
* @param resultConsumer a consumer to supply results to, if any apply
*/
default void reload(Consumer<DiscordSRVApi.ReloadResult> resultConsumer) {}
default void reload(Consumer<ReloadResult> resultConsumer) {}
}

View File

@ -0,0 +1,62 @@
/*
* This file is part of the DiscordSRV API, licensed under the MIT License
* Copyright (c) 2016-2024 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.discordsrv.api.reload;
import com.discordsrv.api.DiscordSRVApi;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.function.Predicate;
public enum ReloadFlag {
CONFIG(false),
LINKED_ACCOUNT_PROVIDER(false),
STORAGE(true),
DISCORD_CONNECTION(DiscordSRVApi::isReady),
DISCORD_COMMANDS(false),
// Bukkit only
TRANSLATIONS(false);
public static final Set<ReloadFlag> ALL = Collections.unmodifiableSet(
new LinkedHashSet<>(Arrays.asList(values())));
public static final Set<ReloadFlag> DEFAULT_FLAGS = Collections.unmodifiableSet(
new LinkedHashSet<>(Collections.singletonList(CONFIG)));
private final Predicate<DiscordSRVApi> requiresConfirm;
ReloadFlag(boolean requiresConfirm) {
this(__ -> requiresConfirm);
}
ReloadFlag(Predicate<DiscordSRVApi> requiresConfirm) {
this.requiresConfirm = requiresConfirm;
}
public boolean requiresConfirm(DiscordSRVApi discordSRV) {
return requiresConfirm.test(discordSRV);
}
}

View File

@ -0,0 +1,44 @@
/*
* This file is part of the DiscordSRV API, licensed under the MIT License
* Copyright (c) 2016-2024 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.discordsrv.api.reload;
import org.jetbrains.annotations.ApiStatus;
public enum ReloadResult {
RESTART_REQUIRED,
@ApiStatus.Internal
ERROR,
@ApiStatus.Internal
DEFAULT_BOT_TOKEN,
@ApiStatus.Internal
DISCORD_CONNECTION_RELOAD_REQUIRED,
@ApiStatus.Internal
SECURITY_FAILED,
@ApiStatus.Internal
STORAGE_CONNECTION_FAILED,
@ApiStatus.Internal
DISCORD_CONNECTION_FAILED,
}

View File

@ -19,6 +19,8 @@
package com.discordsrv.bukkit;
import com.discordsrv.api.DiscordSRVApi;
import com.discordsrv.api.reload.ReloadFlag;
import com.discordsrv.api.reload.ReloadResult;
import com.discordsrv.bukkit.ban.BukkitBanModule;
import com.discordsrv.bukkit.command.game.BukkitGameCommandExecutionHelper;
import com.discordsrv.bukkit.command.game.handler.AbstractBukkitCommandHandler;
@ -226,7 +228,7 @@ public class BukkitDiscordSRV extends AbstractDiscordSRV<DiscordSRVBukkitBootstr
}
@Override
public List<ReloadResult> reload(Set<ReloadFlag> flags, boolean initial) throws Throwable {
protected List<ReloadResult> reload(Set<ReloadFlag> flags, boolean initial) throws Throwable {
List<ReloadResult> results = super.reload(flags, initial);
if (flags.contains(ReloadFlag.TRANSLATIONS)) {

View File

@ -71,7 +71,7 @@ public class DiscordSRVBukkitBootstrap extends BukkitBootstrap implements IBoots
lifecycleManager.loadAndEnable(() -> this.discordSRV = new BukkitDiscordSRV(this));
if (discordSRV == null) return;
discordSRV.scheduler().runOnMainThreadLaterInTicks(() -> discordSRV.invokeServerStarted(), 1);
discordSRV.scheduler().runOnMainThreadLaterInTicks(() -> discordSRV.runServerStarted(), 1);
}
@Override

View File

@ -23,10 +23,11 @@ import com.discordsrv.api.events.lifecycle.DiscordSRVReadyEvent;
import com.discordsrv.api.events.lifecycle.DiscordSRVReloadedEvent;
import com.discordsrv.api.events.lifecycle.DiscordSRVShuttingDownEvent;
import com.discordsrv.api.module.Module;
import com.discordsrv.api.reload.ReloadFlag;
import com.discordsrv.common.abstraction.bootstrap.IBootstrap;
import com.discordsrv.common.command.discord.DiscordCommandModule;
import com.discordsrv.common.command.game.GameCommandModule;
import com.discordsrv.common.command.game.commands.subcommand.reload.ReloadResults;
import com.discordsrv.api.reload.ReloadResult;
import com.discordsrv.common.config.configurate.manager.ConnectionConfigManager;
import com.discordsrv.common.config.configurate.manager.MainConfigManager;
import com.discordsrv.common.config.configurate.manager.MessagesConfigManager;
@ -55,6 +56,7 @@ import com.discordsrv.common.core.storage.StorageType;
import com.discordsrv.common.core.storage.impl.MemoryStorage;
import com.discordsrv.common.discord.api.DiscordAPIEventModule;
import com.discordsrv.common.discord.api.DiscordAPIImpl;
import com.discordsrv.common.discord.connection.DiscordConnectionManager;
import com.discordsrv.common.discord.connection.details.DiscordConnectionDetailsImpl;
import com.discordsrv.common.discord.connection.jda.JDAConnectionManager;
import com.discordsrv.common.exception.StorageException;
@ -90,10 +92,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDAInfo;
import okhttp3.ConnectionPool;
import okhttp3.Dispatcher;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;
import org.intellij.lang.annotations.Language;
import org.jetbrains.annotations.MustBeInvokedByOverriders;
@ -136,6 +135,7 @@ public abstract class AbstractDiscordSRV<
private final AtomicReference<Status> status = new AtomicReference<>(Status.INITIALIZED);
private final AtomicReference<Boolean> beenReady = new AtomicReference<>(false);
private boolean serverStarted = false;
private final Object reloadLock = new Object();
// DiscordSRVApi
private EventBusImpl eventBus;
@ -543,37 +543,72 @@ public abstract class AbstractDiscordSRV<
// Lifecycle
public boolean isServerStarted() {
return serverStarted;
}
public ZonedDateTime getInitializeTime() {
return initializeTime;
}
/**
* Run blocking when plugin/mod is triggered for enabling.
*/
@Override
public final void runEnable() {
try {
this.enable();
} catch (Throwable t) {
logger.error("Failed to enable", t);
logger().error("Failed to enable", t);
setStatus(Status.FAILED_TO_START);
}
}
/**
* Must be manually triggered for {@link DiscordSRV.ServerType#SERVER}, automatically triggered in {@link #enable()} for {@link DiscordSRV.ServerType#PROXY}.
* @return a future running on the {@link #scheduler()}
*/
public final CompletableFuture<Void> runServerStarted() {
return scheduler().execute(() -> {
if (status().isShutdown()) {
// Already shutdown/shutting down, don't bother
return;
}
try {
this.serverStarted();
} catch (Throwable t) {
if (status().isShutdown() && t instanceof NoClassDefFoundError) {
// Already shutdown, ignore errors for classes that already got unloaded
return;
}
logger().error("Failed to start", t);
setStatus(Status.FAILED_TO_START);
disable();
}
});
}
/**
* Triggers a reload of DiscordSRV.
* @param flags the targets to reload
* @return the results of the reload
*/
@Override
public final CompletableFuture<Void> invokeDisable() {
return scheduler().execute(this::disable);
public final List<ReloadResult> runReload(Set<ReloadFlag> flags) {
try {
synchronized (reloadLock) {
return reload(flags, false);
}
} catch (Throwable e) {
logger.error("Failed to reload", e);
return Collections.singletonList(ReloadResult.ERROR);
}
}
@Override
public final List<ReloadResult> runReload(Set<ReloadFlag> flags, boolean silent) {
try {
return reload(flags, silent);
} catch (Throwable e) {
if (silent) {
throw new RuntimeException(e);
} else {
logger.error("Failed to reload", e);
}
return Collections.singletonList(ReloadResults.FAILED);
}
public final CompletableFuture<Void> runDisable() {
return scheduler().execute(this::disable);
}
@MustBeInvokedByOverriders
@ -643,41 +678,16 @@ public abstract class AbstractDiscordSRV<
}
// Initial load
try {
runReload(ReloadFlag.ALL, true);
} catch (RuntimeException e) {
throw e.getCause();
}
reload(ReloadFlag.ALL, true);
if (serverType() == ServerType.PROXY) {
invokeServerStarted().get();
runServerStarted().get();
}
// Register PlayerProvider listeners
playerProvider().subscribe();
}
public final CompletableFuture<Void> invokeServerStarted() {
return scheduler().supply(() -> {
if (status().isShutdown()) {
// Already shutdown/shutting down, don't bother
return null;
}
try {
this.serverStarted();
} catch (Throwable t) {
if (status().isShutdown() && t instanceof NoClassDefFoundError) {
// Already shutdown, ignore errors for classes that already got unloaded
return null;
}
setStatus(Status.FAILED_TO_START);
disable();
logger().error("Failed to start", t);
}
return null;
});
}
@MustBeInvokedByOverriders
protected void serverStarted() {
serverStarted = true;
@ -688,50 +698,8 @@ public abstract class AbstractDiscordSRV<
Optional.ofNullable(getModule(PresenceUpdaterModule.class)).ifPresent(PresenceUpdaterModule::serverStarted);
}
public boolean isServerStarted() {
return serverStarted;
}
private StorageType getStorageType() {
String backend = connectionConfig().storage.backend;
switch (backend.toLowerCase(Locale.ROOT)) {
case "h2": return StorageType.H2;
case "mysql": return StorageType.MYSQL;
case "mariadb": return StorageType.MARIADB;
}
if (backend.equals(MemoryStorage.IDENTIFIER)) {
return StorageType.MEMORY;
}
throw new StorageException("Unknown storage backend \"" + backend + "\"");
}
@MustBeInvokedByOverriders
protected void disable() {
Status status = this.status.get();
if (status == Status.INITIALIZED || status.isShutdown()) {
// Hasn't started or already shutting down/shutdown
return;
}
this.status.set(Status.SHUTTING_DOWN);
// Unregister PlayerProvider listeners
playerProvider().unsubscribe();
eventBus().publish(new DiscordSRVShuttingDownEvent());
eventBus().shutdown();
try {
if (storage != null) {
storage.close();
}
} catch (Throwable t) {
logger().error("Failed to close storage connection", t);
}
temporaryLocalData.save();
this.status.set(Status.SHUTDOWN);
}
@MustBeInvokedByOverriders
public List<ReloadResult> reload(Set<ReloadFlag> flags, boolean initial) throws Throwable {
protected List<ReloadResult> reload(Set<ReloadFlag> flags, boolean initial) throws Throwable {
if (!initial) {
logger().info("Reloading DiscordSRV...");
}
@ -767,7 +735,7 @@ public abstract class AbstractDiscordSRV<
logger().info("");
}
discordConnectionManager.invalidToken(true);
results.add(ReloadResults.DEFAULT_BOT_TOKEN);
results.add(ReloadResult.DEFAULT_BOT_TOKEN);
return results;
}
@ -776,13 +744,13 @@ public abstract class AbstractDiscordSRV<
if (updateConfig.security.enabled) {
if (updateChecker.isSecurityFailed()) {
// Security has already failed
return Collections.singletonList(ReloadResults.SECURITY_FAILED);
return Collections.singletonList(ReloadResult.SECURITY_FAILED);
}
if (initial && !updateChecker.check(true)) {
// Security failed cancel startup & shutdown
invokeDisable();
return Collections.singletonList(ReloadResults.SECURITY_FAILED);
runDisable();
return Collections.singletonList(ReloadResult.SECURITY_FAILED);
}
} else if (initial) {
// Not using security, run update check off thread
@ -824,7 +792,7 @@ public abstract class AbstractDiscordSRV<
if (initial) {
setStatus(Status.FAILED_TO_START);
}
return Collections.singletonList(ReloadResults.STORAGE_CONNECTION_FAILED);
return Collections.singletonList(ReloadResult.STORAGE_CONNECTION_FAILED);
}
}
@ -854,7 +822,7 @@ public abstract class AbstractDiscordSRV<
break;
default: {
linkProvider = null;
logger().error("Unknown linked account provider: \"" + provider + "\", linked accounts will not be used");
logger().error("Unknown linked account provider: \"" + provider + "\", linked accounts will be disabled");
break;
}
}
@ -865,35 +833,20 @@ public abstract class AbstractDiscordSRV<
}
if (flags.contains(ReloadFlag.DISCORD_CONNECTION)) {
try {
if (discordConnectionManager.instance() != null) {
discordConnectionManager.reconnect().get();
} else {
discordConnectionManager.connect().get();
// Shutdown will not fail even if not connected
discordConnectionManager.shutdown(DiscordConnectionManager.DEFAULT_SHUTDOWN_TIMEOUT);
discordConnectionManager.connect();
if (!initial) {
waitForStatus(Status.CONNECTED, 20, TimeUnit.SECONDS);
if (status() != Status.CONNECTED) {
return Collections.singletonList(ReloadResult.DISCORD_CONNECTION_FAILED);
}
if (!initial) {
waitForStatus(Status.CONNECTED, 20, TimeUnit.SECONDS);
if (status() != Status.CONNECTED) {
return Collections.singletonList(ReloadResults.DISCORD_CONNECTION_FAILED);
}
} else {
JDA jda = jda();
if (jda != null) {
try {
jda.awaitReady();
} catch (IllegalStateException ignored) {
// JDA shutdown -> don't continue
return Collections.singletonList(ReloadResults.DISCORD_CONNECTION_FAILED);
}
}
}
} catch (ExecutionException e) {
throw e.getCause();
}
}
// Modules are reloaded upon DiscordSRV being ready, thus not needed at initial
if (!initial && flags.contains(ReloadFlag.MODULES)) {
if (!initial && flags.contains(ReloadFlag.CONFIG)) {
results.addAll(moduleManager.reload());
}
@ -907,7 +860,56 @@ public abstract class AbstractDiscordSRV<
logger().info("Reload complete.");
}
results.add(ReloadResults.SUCCESS);
return results;
}
private StorageType getStorageType() {
String backend = connectionConfig().storage.backend;
switch (backend.toLowerCase(Locale.ROOT)) {
case "h2": return StorageType.H2;
case "mysql": return StorageType.MYSQL;
case "mariadb": return StorageType.MARIADB;
}
if (backend.equals(MemoryStorage.IDENTIFIER)) {
return StorageType.MEMORY;
}
throw new StorageException("Unknown storage backend \"" + backend + "\"");
}
@SuppressWarnings("resource") //
@MustBeInvokedByOverriders
protected void disable() {
Status status = this.status.get();
if (status == Status.INITIALIZED || status.isShutdown()) {
// Hasn't started or already shutting down/shutdown
return;
}
this.status.set(Status.SHUTTING_DOWN);
// Unregister PlayerProvider listeners
playerProvider().unsubscribe();
eventBus().publish(new DiscordSRVShuttingDownEvent());
eventBus().shutdown();
// Shutdown OkHttp
httpClient.dispatcher().executorService().shutdownNow();
httpClient.connectionPool().evictAll();
try {
Cache cache = httpClient.cache();
if (cache != null) {
cache.close();
}
} catch (IOException ignored) {}
try {
if (storage != null) {
storage.close();
}
} catch (Throwable t) {
logger().error("Failed to close storage connection", t);
}
temporaryLocalData.save();
this.status.set(Status.SHUTDOWN);
}
}

View File

@ -20,6 +20,7 @@ package com.discordsrv.common;
import com.discordsrv.api.DiscordSRVApi;
import com.discordsrv.api.module.Module;
import com.discordsrv.api.reload.ReloadFlag;
import com.discordsrv.api.placeholder.format.PlainPlaceholderFormat;
import com.discordsrv.common.abstraction.bootstrap.IBootstrap;
import com.discordsrv.common.abstraction.player.IPlayer;
@ -28,6 +29,7 @@ import com.discordsrv.common.abstraction.plugin.PluginManager;
import com.discordsrv.common.command.game.abstraction.GameCommandExecutionHelper;
import com.discordsrv.common.command.game.abstraction.handler.ICommandHandler;
import com.discordsrv.common.command.game.abstraction.sender.ICommandSender;
import com.discordsrv.api.reload.ReloadResult;
import com.discordsrv.common.config.configurate.manager.ConnectionConfigManager;
import com.discordsrv.common.config.configurate.manager.MainConfigManager;
import com.discordsrv.common.config.configurate.manager.MessagesConfigManager;
@ -174,8 +176,8 @@ public interface DiscordSRV extends DiscordSRVApi {
// Lifecycle
void runEnable();
List<ReloadResult> runReload(Set<ReloadFlag> flags, boolean silent);
CompletableFuture<Void> invokeDisable();
List<ReloadResult> runReload(Set<ReloadFlag> flags);
CompletableFuture<Void> runDisable();
boolean isServerStarted();
ZonedDateTime getInitializeTime();

View File

@ -18,7 +18,7 @@
package com.discordsrv.common.abstraction.bootstrap;
import com.discordsrv.api.DiscordSRVApi;
import com.discordsrv.api.reload.ReloadFlag;
import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.core.dependency.DependencyLoader;
import com.discordsrv.common.core.logging.Logger;
@ -44,7 +44,7 @@ public class LifecycleManager {
private final Logger logger;
private final ExecutorService taskPool;
private final DependencyLoader dependencyLoader;
private final CompletableFuture<?> completableFuture;
private final CompletableFuture<?> dependencyLoadFuture;
public LifecycleManager(
Logger logger,
@ -66,19 +66,26 @@ public class LifecycleManager {
classpathAppender,
resourcePaths.toArray(new String[0])
);
this.completableFuture = dependencyLoader.download();
this.completableFuture.whenComplete((v, t) -> taskPool.shutdownNow());
this.dependencyLoadFuture = dependencyLoader.download();
this.dependencyLoadFuture.whenComplete((v, t) -> taskPool.shutdownNow());
}
public void loadAndEnable(Supplier<DiscordSRV> discordSRVSupplier) {
if (relocateAndLoad()) {
discordSRVSupplier.get().runEnable();
if (!relocateAndLoad()) {
return;
}
DiscordSRV discordSRV = discordSRVSupplier.get();
if (discordSRV == null) {
return;
}
discordSRV.runEnable();
}
private boolean relocateAndLoad() {
try {
completableFuture.get();
dependencyLoadFuture.get();
dependencyLoader.relocateAndLoad(false).get();
return true;
} catch (InterruptedException ignored) {
@ -93,12 +100,12 @@ public class LifecycleManager {
if (discordSRV == null) {
return;
}
discordSRV.runReload(DiscordSRVApi.ReloadFlag.DEFAULT_FLAGS, false);
discordSRV.runReload(ReloadFlag.DEFAULT_FLAGS);
}
public void disable(DiscordSRV discordSRV) {
if (!completableFuture.isDone()) {
completableFuture.cancel(true);
if (!dependencyLoadFuture.isDone()) {
dependencyLoadFuture.cancel(true);
return;
}
@ -107,7 +114,7 @@ public class LifecycleManager {
}
try {
discordSRV.invokeDisable().get(/*15, TimeUnit.SECONDS*/);
discordSRV.runDisable().get(/*15, TimeUnit.SECONDS*/);
} catch (InterruptedException/* | TimeoutException*/ e) {
logger.warning("Timed out/interrupted shutting down DiscordSRV");
} catch (ExecutionException e) {

View File

@ -18,8 +18,8 @@
package com.discordsrv.common.abstraction.sync;
import com.discordsrv.api.DiscordSRVApi;
import com.discordsrv.api.eventbus.Subscribe;
import com.discordsrv.api.reload.ReloadResult;
import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.abstraction.player.IPlayer;
import com.discordsrv.common.abstraction.sync.cause.GenericSyncCauses;
@ -100,7 +100,7 @@ public abstract class AbstractSyncModule<
}
@Override
public void reload(Consumer<DiscordSRVApi.ReloadResult> resultConsumer) {
public void reload(Consumer<ReloadResult> resultConsumer) {
synchronized (syncs) {
syncs.values().forEach(future -> {
if (future != null) {

View File

@ -19,11 +19,12 @@
package com.discordsrv.common.command.game;
import com.discordsrv.api.DiscordSRVApi;
import com.discordsrv.api.reload.ReloadResult;
import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.command.combined.commands.LinkOtherCommand;
import com.discordsrv.common.command.game.abstraction.command.GameCommand;
import com.discordsrv.common.command.game.commands.DiscordSRVGameCommand;
import com.discordsrv.common.command.game.abstraction.handler.ICommandHandler;
import com.discordsrv.common.command.game.commands.DiscordSRVGameCommand;
import com.discordsrv.common.config.main.GameCommandConfig;
import com.discordsrv.common.core.module.type.AbstractModule;
@ -46,7 +47,7 @@ public class GameCommandModule extends AbstractModule<DiscordSRV> {
}
@Override
public void reload(Consumer<DiscordSRVApi.ReloadResult> resultConsumer) {
public void reload(Consumer<ReloadResult> resultConsumer) {
GameCommandConfig config = discordSRV.config().gameCommand;
if (config == null) {
return;

View File

@ -18,7 +18,8 @@
package com.discordsrv.common.command.game.commands.subcommand.reload;
import com.discordsrv.api.DiscordSRVApi;
import com.discordsrv.api.reload.ReloadFlag;
import com.discordsrv.api.reload.ReloadResult;
import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.abstraction.player.IPlayer;
import com.discordsrv.common.command.game.abstraction.command.GameCommand;
@ -65,9 +66,9 @@ public class ReloadCommand implements GameCommandExecutor, GameCommandSuggester
@Override
public void execute(ICommandSender sender, GameCommandArguments arguments, String label) {
AtomicBoolean dangerousFlags = new AtomicBoolean(false);
Set<DiscordSRV.ReloadFlag> flags = getFlagsFromArguments(sender, arguments, dangerousFlags);
Set<ReloadFlag> flags = getFlagsFromArguments(sender, arguments, dangerousFlags);
if (flags == null) {
flags = DiscordSRV.ReloadFlag.DEFAULT_FLAGS;
flags = ReloadFlag.DEFAULT_FLAGS;
}
if (dangerousFlags.get()) {
@ -80,50 +81,64 @@ public class ReloadCommand implements GameCommandExecutor, GameCommandSuggester
return;
}
List<DiscordSRVApi.ReloadResult> results = discordSRV.runReload(flags, false);
for (DiscordSRV.ReloadResult result : results) {
String res = result.name();
if (res.equals(ReloadResults.FAILED.name())) {
sender.sendMessage(
Component.text()
.append(Component.text("Reload failed.", NamedTextColor.DARK_RED, TextDecoration.BOLD))
.append(Component.text("Please check the server console/log for more details."))
);
} else if (res.equals(ReloadResults.SECURITY_FAILED.name())) {
sender.sendMessage(Component.text(
"DiscordSRV is disabled due to a security check failure. "
+ "Please check console for more details", NamedTextColor.DARK_RED));
} else if (res.equals(ReloadResults.SUCCESS.name())) {
sender.sendMessage(Component.text("Reload successful", NamedTextColor.GRAY));
} else if (res.equals(ReloadResults.RESTART_REQUIRED.name())) {
sender.sendMessage(Component.text("Some changes require a server restart"));
} else if (res.equals(ReloadResults.STORAGE_CONNECTION_FAILED.name())) {
sender.sendMessage(Component.text("Storage connection failed, please check console for details.", NamedTextColor.RED));
} else if (res.equals(ReloadResults.DISCORD_CONNECTION_FAILED.name())) {
sender.sendMessage(Component.text("Discord connection failed, please check console for details.", NamedTextColor.RED));
} else if (res.equals(ReloadResults.DISCORD_CONNECTION_RELOAD_REQUIRED.name())) {
String command = "discordsrv reload " + DiscordSRVApi.ReloadFlag.DISCORD_CONNECTION.name().toLowerCase(Locale.ROOT) + " -confirm";
Component child;
if (sender instanceof IPlayer) {
child = Component.text("[Click to reload Discord connection]", NamedTextColor.DARK_RED)
.clickEvent(ClickEvent.runCommand("/" + command))
.hoverEvent(HoverEvent.showText(Component.text("/" + command)));
} else {
child = Component.text("Run ", NamedTextColor.DARK_RED)
.append(Component.text(command, NamedTextColor.GRAY))
.append(Component.text(" to reload the Discord connection"));
List<ReloadResult> results = discordSRV.runReload(flags);
if (results.isEmpty()) {
sender.sendMessage(Component.text("Reload successful", NamedTextColor.GRAY));
return;
}
for (ReloadResult result : results) {
switch (result) {
case ERROR: {
sender.sendMessage(
Component.text()
.append(Component.text("Reload failed.", NamedTextColor.DARK_RED, TextDecoration.BOLD))
.append(Component.text("Please check the server console/log for more details."))
);
break;
}
case SECURITY_FAILED: {
sender.sendMessage(Component.text(
"DiscordSRV is disabled due to a security check failure. "
+ "Please check console for more details", NamedTextColor.DARK_RED));
break;
}
case RESTART_REQUIRED: {
sender.sendMessage(Component.text("Some changes require a server restart"));
break;
}
case STORAGE_CONNECTION_FAILED: {
sender.sendMessage(Component.text("Storage connection failed, please check console for details.", NamedTextColor.RED));
break;
}
case DISCORD_CONNECTION_FAILED: {
sender.sendMessage(Component.text("Discord connection failed, please check console for details.", NamedTextColor.RED));
break;
}
case DISCORD_CONNECTION_RELOAD_REQUIRED: {
String command = "discordsrv reload " + ReloadFlag.DISCORD_CONNECTION.name().toLowerCase(Locale.ROOT) + " -confirm";
Component child;
if (sender instanceof IPlayer) {
child = Component.text("[Click to reload Discord connection]", NamedTextColor.DARK_RED)
.clickEvent(ClickEvent.runCommand("/" + command))
.hoverEvent(HoverEvent.showText(Component.text("/" + command)));
} else {
child = Component.text("Run ", NamedTextColor.DARK_RED)
.append(Component.text(command, NamedTextColor.GRAY))
.append(Component.text(" to reload the Discord connection"));
}
sender.sendMessage(
Component.text()
.append(Component.text("Some changes require a Discord connection reload. ", NamedTextColor.GRAY))
.append(child)
);
sender.sendMessage(
Component.text()
.append(Component.text("Some changes require a Discord connection reload. ", NamedTextColor.GRAY))
.append(child)
);
break;
}
}
}
}
private Set<DiscordSRV.ReloadFlag> getFlagsFromArguments(ICommandSender sender, GameCommandArguments arguments, AtomicBoolean dangerousFlags) {
private Set<ReloadFlag> getFlagsFromArguments(ICommandSender sender, GameCommandArguments arguments, AtomicBoolean dangerousFlags) {
String argument = null;
try {
argument = arguments.get("flags", String.class);
@ -136,16 +151,16 @@ public class ReloadCommand implements GameCommandExecutor, GameCommandSuggester
List<String> parts = new ArrayList<>(Arrays.asList(argument.split(" ")));
boolean confirm = parts.remove("-confirm");
Set<DiscordSRV.ReloadFlag> flags = new LinkedHashSet<>();
Set<ReloadFlag> flags = new LinkedHashSet<>();
if (discordSRV.status().isStartupError()) {
// If startup error, use all flags
parts.clear();
flags.addAll(DiscordSRVApi.ReloadFlag.ALL);
flags.addAll(ReloadFlag.ALL);
}
for (String part : parts) {
try {
DiscordSRV.ReloadFlag flag = DiscordSRV.ReloadFlag.valueOf(part.toUpperCase(Locale.ROOT));
ReloadFlag flag = ReloadFlag.valueOf(part.toUpperCase(Locale.ROOT));
if (flag.requiresConfirm(discordSRV) && !confirm) {
dangerousFlags.set(true);
sender.sendMessage(
@ -175,7 +190,7 @@ public class ReloadCommand implements GameCommandExecutor, GameCommandSuggester
String last = currentInput.substring(lastSpace);
String beforeLastSpace = currentInput.substring(0, lastSpace);
List<String> options = DiscordSRV.ReloadFlag.ALL.stream()
List<String> options = ReloadFlag.ALL.stream()
.map(flag -> flag.name().toLowerCase(Locale.ROOT))
.filter(flag -> flag.startsWith(last))
.collect(Collectors.toList());

View File

@ -1,31 +0,0 @@
/*
* This file is part of DiscordSRV, licensed under the GPLv3 License
* Copyright (c) 2016-2024 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.discordsrv.common.command.game.commands.subcommand.reload;
import com.discordsrv.api.DiscordSRVApi;
public enum ReloadResults implements DiscordSRVApi.ReloadResult {
FAILED,
DEFAULT_BOT_TOKEN,
SUCCESS,
SECURITY_FAILED,
STORAGE_CONNECTION_FAILED,
DISCORD_CONNECTION_RELOAD_REQUIRED,
DISCORD_CONNECTION_FAILED
}

View File

@ -18,7 +18,6 @@
package com.discordsrv.common.core.module;
import com.discordsrv.api.DiscordSRVApi;
import com.discordsrv.api.discord.connection.details.DiscordCacheFlag;
import com.discordsrv.api.discord.connection.details.DiscordGatewayIntent;
import com.discordsrv.api.discord.connection.details.DiscordMemberCachePolicy;
@ -27,8 +26,8 @@ import com.discordsrv.api.eventbus.Subscribe;
import com.discordsrv.api.events.lifecycle.DiscordSRVReadyEvent;
import com.discordsrv.api.events.lifecycle.DiscordSRVShuttingDownEvent;
import com.discordsrv.api.module.Module;
import com.discordsrv.api.reload.ReloadResult;
import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.command.game.commands.subcommand.reload.ReloadResults;
import com.discordsrv.common.core.logging.Logger;
import com.discordsrv.common.core.logging.NamedLogger;
import com.discordsrv.common.core.module.type.AbstractModule;
@ -163,7 +162,7 @@ public class ModuleManager {
logger.debug(module.getClass().getName() + " unregistered");
}
private List<DiscordSRVApi.ReloadResult> enable(AbstractModule<?> module) {
private List<ReloadResult> enable(AbstractModule<?> module) {
try {
if (module.enableModule()) {
logger.debug(module + " enabled");
@ -176,8 +175,8 @@ public class ModuleManager {
return null;
}
private List<DiscordSRVApi.ReloadResult> reload(AbstractModule<?> module) {
List<DiscordSRVApi.ReloadResult> reloadResults = new ArrayList<>();
private List<ReloadResult> reload(AbstractModule<?> module) {
List<ReloadResult> reloadResults = new ArrayList<>();
try {
module.reload(result -> {
if (result == null) {
@ -225,7 +224,7 @@ public class ModuleManager {
}
}
public List<DiscordSRVApi.ReloadResult> reload() {
public List<ReloadResult> reload() {
return reloadAndEnableModules(true);
}
@ -233,19 +232,19 @@ public class ModuleManager {
reloadAndEnableModules(false);
}
private synchronized List<DiscordSRV.ReloadResult> reloadAndEnableModules(boolean reload) {
private synchronized List<ReloadResult> reloadAndEnableModules(boolean reload) {
boolean isReady = discordSRV.isReady();
logger().debug((reload ? "Reloading" : "Enabling") + " modules (DiscordSRV ready = " + isReady + ")");
Set<DiscordSRVApi.ReloadResult> reloadResults = new HashSet<>();
Set<ReloadResult> reloadResults = new HashSet<>();
for (Module module : modules) {
reloadResults.addAll(enableOrDisableAsNeeded(getAbstract(module), isReady, reload));
}
List<DiscordSRVApi.ReloadResult> results = new ArrayList<>();
List<ReloadResult> results = new ArrayList<>();
List<DiscordSRV.ReloadResult> validResults = Arrays.asList(DiscordSRVApi.ReloadResult.DefaultConstants.values());
for (DiscordSRVApi.ReloadResult reloadResult : reloadResults) {
List<ReloadResult> validResults = Arrays.asList(ReloadResult.values());
for (ReloadResult reloadResult : reloadResults) {
if (validResults.contains(reloadResult)) {
results.add(reloadResult);
}
@ -254,7 +253,7 @@ public class ModuleManager {
return results;
}
private List<DiscordSRVApi.ReloadResult> enableOrDisableAsNeeded(AbstractModule<?> module, boolean isReady, boolean mayReload) {
private List<ReloadResult> enableOrDisableAsNeeded(AbstractModule<?> module, boolean isReady, boolean mayReload) {
boolean canBeEnabled = isReady || module.canEnableBeforeReady();
if (!canBeEnabled) {
return Collections.emptyList();
@ -282,14 +281,14 @@ public class ModuleManager {
}
}
List<DiscordSRVApi.ReloadResult> reloadResults = new ArrayList<>();
List<ReloadResult> reloadResults = new ArrayList<>();
if (fail) {
reloadResults.add(ReloadResults.DISCORD_CONNECTION_RELOAD_REQUIRED);
reloadResults.add(ReloadResult.DISCORD_CONNECTION_RELOAD_REQUIRED);
}
// Enable the module if reload passed
if (!fail) {
List<DiscordSRVApi.ReloadResult> results = enable(module);
List<ReloadResult> results = enable(module);
if (results != null) {
reloadResults.addAll(results);
} else if (mayReload) {

View File

@ -18,11 +18,11 @@
package com.discordsrv.common.core.module.type;
import com.discordsrv.api.DiscordSRVApi;
import com.discordsrv.api.discord.connection.details.DiscordCacheFlag;
import com.discordsrv.api.discord.connection.details.DiscordGatewayIntent;
import com.discordsrv.api.discord.connection.details.DiscordMemberCachePolicy;
import com.discordsrv.api.module.Module;
import com.discordsrv.api.reload.ReloadResult;
import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.core.logging.NamedLogger;
import org.jetbrains.annotations.NotNull;
@ -79,7 +79,7 @@ public class ModuleDelegate extends AbstractModule<DiscordSRV> {
}
@Override
public void reload(Consumer<DiscordSRVApi.ReloadResult> resultConsumer) {
public void reload(Consumer<ReloadResult> resultConsumer) {
module.reload(resultConsumer);
}

View File

@ -21,15 +21,12 @@ package com.discordsrv.common.discord.connection;
import net.dv8tion.jda.api.JDA;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
public interface DiscordConnectionManager {
/**
* The default amount of milliseconds to wait for shutdown before ending without completing rate limited requests.
*/
long DEFAULT_SHUTDOWN_TIMEOUT = TimeUnit.SECONDS.toMillis(10);
int DEFAULT_SHUTDOWN_TIMEOUT = 10;
/**
* Gets the instance.
@ -40,33 +37,16 @@ public interface DiscordConnectionManager {
/**
* Attempts to connect to Discord.
* @return a {@link CompletableFuture}
*/
CompletableFuture<Void> connect();
/**
* Shuts down the Discord connection and connects again.
* @return a {@link CompletableFuture}
*/
CompletableFuture<Void> reconnect();
/**
* Shuts down the Discord connection after waiting for queued requests to complete. Blocks until shutdown is completed.
* @return a {@link CompletableFuture}
* @see #DEFAULT_SHUTDOWN_TIMEOUT
*/
default CompletableFuture<Void> shutdown() {
return shutdown(DEFAULT_SHUTDOWN_TIMEOUT);
}
void connect();
/**
* Shuts down the Discord connection after waiting for queued requests to complete.
* Waits the provided amount of milliseconds before running {@link #shutdownNow()}.
*
* @param timeoutMillis the maximum amount of milliseconds to wait for shut down
* @return a {@link CompletableFuture}
* @param timeoutSeconds the maximum amount of seconds to wait for JDA to shut down
*/
CompletableFuture<Void> shutdown(long timeoutMillis);
void shutdown(int timeoutSeconds);
/**
* Shuts down the Discord connection without waiting for queued requests to be completed.

View File

@ -85,7 +85,6 @@ public class JDAConnectionManager implements DiscordConnectionManager {
private ScheduledExecutorService rateLimitSchedulerPool;
private ExecutorService rateLimitElasticPool;
private CompletableFuture<Void> connectionFuture;
private JDA instance;
// Currently used intents & cache flags
@ -286,20 +285,11 @@ public class JDAConnectionManager implements DiscordConnectionManager {
//
@Override
public CompletableFuture<Void> connect() {
if (connectionFuture != null && !connectionFuture.isDone()) {
throw new IllegalStateException("Already connecting");
} else if (instance != null && instance.getStatus() != JDA.Status.SHUTDOWN) {
public void connect() {
if (instance != null && instance.getStatus() != JDA.Status.SHUTDOWN) {
throw new IllegalStateException("Cannot reconnect, still active");
}
this.connectInternal();
return CompletableFuture.completedFuture(null);
// TODO: investigate why this is broken
//return connectionFuture = discordSRV.scheduler().execute(this::connectInternal);
}
private void connectInternal() {
BotConfig botConfig = discordSRV.connectionConfig().bot;
String token = botConfig.token;
boolean defaultToken = false;
@ -412,8 +402,8 @@ public class JDAConnectionManager implements DiscordConnectionManager {
// Our own (named) threads
jdaBuilder.setCallbackPool(discordSRV.scheduler().forkJoinPool());
jdaBuilder.setGatewayPool(gatewayPool);
jdaBuilder.setRateLimitScheduler(rateLimitSchedulerPool, true);
jdaBuilder.setRateLimitElastic(rateLimitElasticPool);
jdaBuilder.setRateLimitScheduler(rateLimitSchedulerPool);
jdaBuilder.setRateLimitElastic(rateLimitElasticPool, true);
jdaBuilder.setHttpClient(discordSRV.httpClient());
WebSocketFactory webSocketFactory = new WebSocketFactory();
@ -428,27 +418,13 @@ public class JDAConnectionManager implements DiscordConnectionManager {
}
}
@Override
public CompletableFuture<Void> reconnect() {
return discordSRV.scheduler().execute(() -> {
shutdown().join();
connect().join();
});
}
@Subscribe(priority = EventPriority.LATE)
public void onDSRVShuttingDown(DiscordSRVShuttingDownEvent event) {
// This has a timeout
shutdown().join();
shutdown(DEFAULT_SHUTDOWN_TIMEOUT);
}
@Override
public CompletableFuture<Void> shutdown(long timeoutMillis) {
return discordSRV.scheduler().execute(() -> shutdownInternal(timeoutMillis));
}
@SuppressWarnings("BusyWait")
private void shutdownInternal(long timeoutMillis) {
@SuppressWarnings("BusyWait") // Known
public void shutdown(int timeoutSeconds) {
if (instance == null) {
shutdownExecutors();
return;
@ -457,14 +433,16 @@ public class JDAConnectionManager implements DiscordConnectionManager {
instance.shutdown();
try {
discordSRV.logger().info("Waiting up to " + TimeUnit.MILLISECONDS.toSeconds(timeoutMillis) + " seconds for JDA to shutdown...");
discordSRV.logger().info("Waiting up to " + timeoutSeconds + " seconds for JDA to shutdown...");
discordSRV.scheduler().run(() -> {
try {
while (instance != null && !rateLimitSchedulerPool.isShutdown()) {
while (instance != null && instance.getStatus() != JDA.Status.SHUTDOWN && !rateLimitElasticPool.isShutdown()) {
Thread.sleep(50);
}
} catch (InterruptedException ignored) {}
}).get(timeoutMillis, TimeUnit.MILLISECONDS);
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
}
}).get(timeoutSeconds, TimeUnit.SECONDS);
instance = null;
shutdownExecutors();
discordSRV.logger().info("JDA shutdown completed.");
@ -478,7 +456,9 @@ public class JDAConnectionManager implements DiscordConnectionManager {
}
discordSRV.logger().error("Failed to shutdown JDA", t);
}
} catch (InterruptedException ignored) {}
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
}
}
@Override
@ -495,10 +475,10 @@ public class JDAConnectionManager implements DiscordConnectionManager {
if (gatewayPool != null) {
gatewayPool.shutdownNow();
}
if (rateLimitSchedulerPool != null && !rateLimitSchedulerPool.isShutdown()) {
if (rateLimitSchedulerPool != null) {
rateLimitSchedulerPool.shutdownNow();
}
if (rateLimitElasticPool != null) {
if (rateLimitElasticPool != null && !rateLimitElasticPool.isShutdown()) {
rateLimitElasticPool.shutdownNow();
}
if (failureCallbackFuture != null) {

View File

@ -18,12 +18,12 @@
package com.discordsrv.common.feature;
import com.discordsrv.api.DiscordSRVApi;
import com.discordsrv.api.discord.connection.details.DiscordGatewayIntent;
import com.discordsrv.api.discord.connection.jda.errorresponse.ErrorCallbackContext;
import com.discordsrv.api.eventbus.Subscribe;
import com.discordsrv.api.placeholder.annotation.Placeholder;
import com.discordsrv.api.placeholder.format.FormattedText;
import com.discordsrv.api.reload.ReloadResult;
import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.config.main.DiscordInviteConfig;
import com.discordsrv.common.core.logging.NamedLogger;
@ -79,7 +79,7 @@ public class DiscordInviteModule extends AbstractModule<DiscordSRV> {
}
@Override
public void reload(Consumer<DiscordSRVApi.ReloadResult> resultConsumer) {
public void reload(Consumer<ReloadResult> resultConsumer) {
JDA jda = discordSRV.jda();
if (jda == null) {
logger().debug("JDA == null");

View File

@ -18,10 +18,10 @@
package com.discordsrv.common.feature;
import com.discordsrv.api.DiscordSRVApi;
import com.discordsrv.api.eventbus.EventPriority;
import com.discordsrv.api.eventbus.Subscribe;
import com.discordsrv.api.events.lifecycle.DiscordSRVShuttingDownEvent;
import com.discordsrv.api.reload.ReloadResult;
import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.config.main.PresenceUpdaterConfig;
import com.discordsrv.common.core.logging.NamedLogger;
@ -70,7 +70,7 @@ public class PresenceUpdaterModule extends AbstractModule<DiscordSRV> {
}
@Override
public void reload(Consumer<DiscordSRVApi.ReloadResult> resultConsumer) {
public void reload(Consumer<ReloadResult> resultConsumer) {
if (discordSRV.jda() == null) {
return;
}

View File

@ -18,8 +18,8 @@
package com.discordsrv.common.feature.channel;
import com.discordsrv.api.DiscordSRVApi;
import com.discordsrv.api.discord.connection.jda.errorresponse.ErrorCallbackContext;
import com.discordsrv.api.reload.ReloadResult;
import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.config.main.TimedUpdaterConfig;
import com.discordsrv.common.core.logging.NamedLogger;
@ -67,7 +67,7 @@ public class TimedUpdaterModule extends AbstractModule<DiscordSRV> {
}
@Override
public void reload(Consumer<DiscordSRVApi.ReloadResult> resultConsumer) {
public void reload(Consumer<ReloadResult> resultConsumer) {
futures.forEach(future -> future.cancel(false));
futures.clear();

View File

@ -18,10 +18,10 @@
package com.discordsrv.common.feature.console;
import com.discordsrv.api.DiscordSRVApi;
import com.discordsrv.api.discord.connection.details.DiscordGatewayIntent;
import com.discordsrv.api.eventbus.Subscribe;
import com.discordsrv.api.events.discord.message.DiscordMessageReceiveEvent;
import com.discordsrv.api.reload.ReloadResult;
import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.config.main.ConsoleConfig;
import com.discordsrv.common.config.main.generic.DestinationConfig;
@ -70,7 +70,7 @@ public class ConsoleModule extends AbstractModule<DiscordSRV> implements LogAppe
}
@Override
public void reload(Consumer<DiscordSRVApi.ReloadResult> resultConsumer) {
public void reload(Consumer<ReloadResult> resultConsumer) {
List<ConsoleConfig> configs = discordSRV.config().console;
Set<ConsoleConfig> uncheckedConfigs = new LinkedHashSet<>(configs);

View File

@ -18,7 +18,6 @@
package com.discordsrv.common.feature.customcommands;
import com.discordsrv.api.DiscordSRVApi;
import com.discordsrv.api.discord.entity.DiscordUser;
import com.discordsrv.api.discord.entity.channel.DiscordChannel;
import com.discordsrv.api.discord.entity.guild.DiscordGuildMember;
@ -28,6 +27,7 @@ import com.discordsrv.api.discord.entity.interaction.command.DiscordCommand;
import com.discordsrv.api.discord.entity.interaction.component.ComponentIdentifier;
import com.discordsrv.api.discord.entity.message.SendableDiscordMessage;
import com.discordsrv.api.events.discord.interaction.command.AbstractCommandInteractionEvent;
import com.discordsrv.api.reload.ReloadResult;
import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.config.main.CustomCommandConfig;
import com.discordsrv.common.core.logging.NamedLogger;
@ -55,7 +55,7 @@ public class CustomCommandModule extends AbstractModule<DiscordSRV> {
}
@Override
public void reload(Consumer<DiscordSRVApi.ReloadResult> resultConsumer) {
public void reload(Consumer<ReloadResult> resultConsumer) {
List<CustomCommandConfig> configs = discordSRV.config().customCommands;
List<LayerCommand> layeredCommands = new ArrayList<>();

View File

@ -18,9 +18,9 @@
package com.discordsrv.common.feature.linking.requirelinking;
import com.discordsrv.api.DiscordSRVApi;
import com.discordsrv.api.eventbus.Subscribe;
import com.discordsrv.api.events.linking.AccountUnlinkedEvent;
import com.discordsrv.api.reload.ReloadResult;
import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.abstraction.player.IPlayer;
import com.discordsrv.common.config.main.linking.RequiredLinkingConfig;
@ -101,7 +101,7 @@ public abstract class RequiredLinkingModule<T extends DiscordSRV> extends Abstra
}
@Override
public final void reload(Consumer<DiscordSRVApi.ReloadResult> resultConsumer) {
public final void reload(Consumer<ReloadResult> resultConsumer) {
List<RequirementType<?>> requirementTypes = new ArrayList<>();
requirementTypes.add(new DiscordRoleRequirementType(this));