boomermath
boomermath

Reputation: 82

Reactively handle errors in Discord4J without error propagation

I am making a discord bot in Discord4J, with a command handler that returns the valid command:

return Mono.just(event.getCommandName())
        .filter(commandRegistry::has)
        .map(commandRegistry::get)
        .flatMap(discordCommand -> {
            try {
                return discordCommand.executeCommand(event);
            } catch (Exception e) {
                logger.error(e.getMessage());
                return event.reply("Error occurred!").then();
            }
        })
        .then();

(discordCommand.executeCommand returns Mono)

If I try to handle the error with doOnError the error propagates and crashes the program. My question is, how do I make this reactive without the error propagating. Surrounding the entire block with try/catch doesn't work either.

Upvotes: 1

Views: 286

Answers (2)

Azn9
Azn9

Reputation: 91

You can use onErrorResume to convert the error into "nothing" (Mono.empty()):

.onErrorResume(throwable -> {
    //Do whatever you want with the error
    return Mono.empty();
})

Upvotes: 1

NovaFox161
NovaFox161

Reputation: 175

All .doOnX methods are what we call "side effects". They don't subscribe to anything, instead they are called whenever the condition is met.

So instead of using try/catch, for reactive we can do the following:

return Mono.just(event.getCommandName())
    .filter(commandRegistry::has)
    .map(commandRegistry::get)
    .flatMap(discordCommand ->> discordCommand.executeCommand(event);})
    .doOnError(e -> logger.error("an error happened", e))
    .onErrorResume(e -> event.reply("Sorry, an error occurred"));

In the above, we use .doOnError as a side effect to log the error since there is no further reactive actions we wish to take when logging. Then, we use onErrorResume which allows us to gracefully handle the error by sending the user a reply instead of the error propagating.

Upvotes: 2

Related Questions