From ddf682c1d013f2ee2480f8b64452bd81d77be5ac Mon Sep 17 00:00:00 2001 From: Zabuzard Date: Sat, 13 Aug 2022 20:44:35 +0200 Subject: [PATCH] Adding uncaught exception handling * for scheduled services, it has to be done manually since their exception gets supressed and put into the future. also, those routines shouldnt stop if one failed --- .../org/togetherjava/tjbot/Application.java | 18 ++++++++++-------- .../componentids/ComponentIdStore.java | 12 ++++++++++-- .../help/HelpThreadOverviewUpdater.java | 16 ++++++++++++---- .../tjbot/commands/system/BotCore.java | 10 +++++++--- 4 files changed, 39 insertions(+), 17 deletions(-) diff --git a/application/src/main/java/org/togetherjava/tjbot/Application.java b/application/src/main/java/org/togetherjava/tjbot/Application.java index 9bcb011b33..a4bf02d277 100644 --- a/application/src/main/java/org/togetherjava/tjbot/Application.java +++ b/application/src/main/java/org/togetherjava/tjbot/Application.java @@ -4,7 +4,7 @@ import net.dv8tion.jda.api.JDABuilder; import net.dv8tion.jda.api.requests.GatewayIntent; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; - +import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -56,11 +56,10 @@ public static void main(final String[] args) { return; } - try { - runBot(config); - } catch (Exception t) { - logger.error("Unknown error", t); - } + Thread.setDefaultUncaughtExceptionHandler(Application::onUncaughtException); + Runtime.getRuntime().addShutdownHook(new Thread(Application::onShutdown)); + + runBot(config); } /** @@ -86,8 +85,6 @@ public static void runBot(Config config) { jda.addEventListener(new BotCore(jda, database, config)); jda.awaitReady(); logger.info("Bot is ready"); - - Runtime.getRuntime().addShutdownHook(new Thread(Application::onShutdown)); } catch (LoginException e) { logger.error("Failed to login", e); } catch (InterruptedException e) { @@ -109,4 +106,9 @@ private static void onShutdown() { logger.info("Bot has been stopped"); } + private static void onUncaughtException(@NotNull Thread failingThread, + @NotNull Throwable failure) { + logger.error("Unknown error in thread {}.", failingThread.getName(), failure); + } + } diff --git a/application/src/main/java/org/togetherjava/tjbot/commands/componentids/ComponentIdStore.java b/application/src/main/java/org/togetherjava/tjbot/commands/componentids/ComponentIdStore.java index 7d1de1d526..7f93b79961 100644 --- a/application/src/main/java/org/togetherjava/tjbot/commands/componentids/ComponentIdStore.java +++ b/application/src/main/java/org/togetherjava/tjbot/commands/componentids/ComponentIdStore.java @@ -114,8 +114,16 @@ public ComponentIdStore(@NotNull Database database, long evictEveryInitialDelay, .maximumSize(CACHE_SIZE) .expireAfterAccess(EVICT_CACHE_OLDER_THAN, TimeUnit.of(EVICT_CACHE_OLDER_THAN_UNIT)) .build(); - evictionTask = evictionService.scheduleWithFixedDelay(this::evictDatabase, - evictEveryInitialDelay, evictEveryDelay, TimeUnit.of(evictEveryUnit)); + + Runnable evictCommand = () -> { + try { + evictDatabase(); + } catch (Exception e) { + logger.error("Unknown error while evicting the component ID store database.", e); + } + }; + evictionTask = evictionService.scheduleWithFixedDelay(evictCommand, evictEveryInitialDelay, + evictEveryDelay, TimeUnit.of(evictEveryUnit)); logDebugSizeStatistics(); } diff --git a/application/src/main/java/org/togetherjava/tjbot/commands/help/HelpThreadOverviewUpdater.java b/application/src/main/java/org/togetherjava/tjbot/commands/help/HelpThreadOverviewUpdater.java index 8e09234b0e..92a9c4a23f 100644 --- a/application/src/main/java/org/togetherjava/tjbot/commands/help/HelpThreadOverviewUpdater.java +++ b/application/src/main/java/org/togetherjava/tjbot/commands/help/HelpThreadOverviewUpdater.java @@ -81,10 +81,18 @@ public void onMessageReceived(@NotNull MessageReceivedEvent event) { message.delete().queue(); // Thread creation can sometimes take a bit longer than the actual message, so that - // "getThreadChannels()" - // would not pick it up, hence we execute the update with some slight delay. - UPDATE_SERVICE.schedule(() -> updateOverviewForGuild(event.getGuild()), 2, - TimeUnit.SECONDS); + // "getThreadChannels()" would not pick it up, hence we execute the update with some slight + // delay. + Runnable updateOverviewCommand = () -> { + try { + updateOverviewForGuild(event.getGuild()); + } catch (Exception e) { + logger.error( + "Unknown error while attempting to update the help overview for guild {}.", + event.getGuild().getId(), e); + } + }; + UPDATE_SERVICE.schedule(updateOverviewCommand, 2, TimeUnit.SECONDS); } private void updateOverviewForGuild(@NotNull Guild guild) { diff --git a/application/src/main/java/org/togetherjava/tjbot/commands/system/BotCore.java b/application/src/main/java/org/togetherjava/tjbot/commands/system/BotCore.java index b6847bc882..6ffcbf1be8 100644 --- a/application/src/main/java/org/togetherjava/tjbot/commands/system/BotCore.java +++ b/application/src/main/java/org/togetherjava/tjbot/commands/system/BotCore.java @@ -94,9 +94,13 @@ public BotCore(@NotNull JDA jda, @NotNull Database database, @NotNull Config con .forEach(routine -> { Runnable command = () -> { String routineName = routine.getClass().getSimpleName(); - logger.debug("Running routine %s...".formatted(routineName)); - routine.runRoutine(jda); - logger.debug("Finished routine %s.".formatted(routineName)); + try { + logger.debug("Running routine %s...".formatted(routineName)); + routine.runRoutine(jda); + logger.debug("Finished routine %s.".formatted(routineName)); + } catch (Exception e) { + logger.error("Unknown error in routine {}.", routineName, e); + } }; Routine.Schedule schedule = routine.createSchedule();