mirror of
https://github.com/System-End/Discord-MC-Chat.git
synced 2026-04-19 20:55:13 +00:00
Enhance DiscordManager initialization with custom executor and improved thread handling
This commit is contained in:
parent
6a0e4ed629
commit
4d92192413
2 changed files with 56 additions and 31 deletions
|
|
@ -1,5 +1,6 @@
|
|||
package com.xujiayao.discord_mc_chat.server.discord;
|
||||
|
||||
import com.xujiayao.discord_mc_chat.utils.ExecutorServiceUtils;
|
||||
import com.xujiayao.discord_mc_chat.utils.config.ConfigManager;
|
||||
import com.xujiayao.discord_mc_chat.utils.config.ModeManager;
|
||||
import com.xujiayao.discord_mc_chat.utils.i18n.I18nManager;
|
||||
|
|
@ -42,9 +43,10 @@ public class DiscordManager {
|
|||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// Blocks until JDA is ready
|
||||
try (ExecutorService executor = Executors.newSingleThreadExecutor(r -> new Thread(r, "DMCC-FutureChecker"))) {
|
||||
// Use a custom executor with our special ThreadFactory to ensure ClassLoader is correct
|
||||
try (ExecutorService executor = Executors.newCachedThreadPool(ExecutorServiceUtils.newThreadFactory("DMCC-DiscordInit"))) {
|
||||
try {
|
||||
// Blocks until JDA is ready
|
||||
CompletableFuture<Void> readyFuture = CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
jda = JDABuilder.createDefault(token)
|
||||
|
|
@ -60,7 +62,7 @@ public class DiscordManager {
|
|||
} catch (InterruptedException e) {
|
||||
LOGGER.error(I18nManager.getDmccTranslation("discord.manager.init_interrupted"), e);
|
||||
}
|
||||
});
|
||||
}, executor);
|
||||
|
||||
CompletableFuture<Void> checkFuture = CompletableFuture.runAsync(() -> {
|
||||
if (!readyFuture.isDone()) {
|
||||
|
|
@ -70,39 +72,42 @@ public class DiscordManager {
|
|||
|
||||
readyFuture.join();
|
||||
checkFuture.cancel(false);
|
||||
|
||||
LOGGER.info(I18nManager.getDmccTranslation("discord.manager.ready", jda.getSelfUser().getAsTag()));
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(I18nManager.getDmccTranslation("discord.manager.init_interrupted"), e);
|
||||
}
|
||||
|
||||
LOGGER.info(I18nManager.getDmccTranslation("discord.manager.ready", jda.getSelfUser().getAsTag()));
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(I18nManager.getDmccTranslation("discord.manager.init_interrupted"), e);
|
||||
}
|
||||
|
||||
if (jda == null || jda.getStatus() != JDA.Status.CONNECTED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Blocks until commands are updated
|
||||
try (ExecutorService executor = Executors.newSingleThreadExecutor(r -> new Thread(r, "DMCC-FutureChecker"))) {
|
||||
List<CommandData> commands = new ArrayList<>();
|
||||
commands.add(Commands.slash("help", I18nManager.getDmccTranslation("commands.help.description")));
|
||||
commands.add(Commands.slash("reload", I18nManager.getDmccTranslation("commands.reload.description")));
|
||||
if ("standalone".equals(ModeManager.getMode())) {
|
||||
commands.add(Commands.slash("shutdown", I18nManager.getDmccTranslation("commands.shutdown.description")));
|
||||
if (jda == null || jda.getStatus() != JDA.Status.CONNECTED) {
|
||||
// Don't forget to shut down the temporary executor
|
||||
executor.shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
CompletableFuture<List<Command>> updateFuture = jda.updateCommands().addCommands(commands).submit();
|
||||
CompletableFuture<Void> checkFuture = CompletableFuture.runAsync(() -> {
|
||||
if (!updateFuture.isDone()) {
|
||||
LOGGER.warn(I18nManager.getDmccTranslation("discord.manager.registering_commands"));
|
||||
// Blocks until commands are updated
|
||||
try {
|
||||
List<CommandData> commands = new ArrayList<>();
|
||||
commands.add(Commands.slash("help", I18nManager.getDmccTranslation("commands.help.description")));
|
||||
commands.add(Commands.slash("reload", I18nManager.getDmccTranslation("commands.reload.description")));
|
||||
if ("standalone".equals(ModeManager.getMode())) {
|
||||
commands.add(Commands.slash("shutdown", I18nManager.getDmccTranslation("commands.shutdown.description")));
|
||||
}
|
||||
}, CompletableFuture.delayedExecutor(5, TimeUnit.SECONDS, executor));
|
||||
updateFuture.join();
|
||||
checkFuture.cancel(false);
|
||||
|
||||
LOGGER.info(I18nManager.getDmccTranslation("discord.manager.commands_success"));
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(I18nManager.getDmccTranslation("discord.manager.commands_failed"), e);
|
||||
CompletableFuture<List<Command>> updateFuture = jda.updateCommands().addCommands(commands).submit();
|
||||
CompletableFuture<Void> checkFuture = CompletableFuture.runAsync(() -> {
|
||||
if (!updateFuture.isDone()) {
|
||||
LOGGER.warn(I18nManager.getDmccTranslation("discord.manager.registering_commands"));
|
||||
}
|
||||
}, CompletableFuture.delayedExecutor(5, TimeUnit.SECONDS, executor));
|
||||
|
||||
updateFuture.join();
|
||||
checkFuture.cancel(false);
|
||||
|
||||
LOGGER.info(I18nManager.getDmccTranslation("discord.manager.commands_success"));
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(I18nManager.getDmccTranslation("discord.manager.commands_failed"), e);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.xujiayao.discord_mc_chat.utils;
|
|||
import com.xujiayao.discord_mc_chat.utils.config.ConfigManager;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
|
|
@ -12,6 +13,25 @@ import java.util.concurrent.TimeUnit;
|
|||
*/
|
||||
public class ExecutorServiceUtils {
|
||||
|
||||
/**
|
||||
* Creates a ThreadFactory that ensures all created threads inherit the current Mod ClassLoader.
|
||||
* This fixes issues with SLF4J/ServiceLoader not finding resources in async threads within Minecraft.
|
||||
*
|
||||
* @param name The thread name.
|
||||
* @return A ThreadFactory with the correct Context ClassLoader set.
|
||||
*/
|
||||
public static ThreadFactory newThreadFactory(String name) {
|
||||
// Capture the correct ClassLoader NOW (while we are on the main/mod thread)
|
||||
final ClassLoader modClassLoader = ExecutorServiceUtils.class.getClassLoader();
|
||||
|
||||
return r -> {
|
||||
Thread t = new Thread(r, name);
|
||||
// Force the new thread to use the Mod ClassLoader captured above
|
||||
t.setContextClassLoader(modClassLoader);
|
||||
return t;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuts down the given ExecutorService gracefully based on configuration.
|
||||
*
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue