Wrap reply calls with a try-catch clause to avoid dynamic exceptions

This commit is contained in:
Abbas Abou Daya 2020-07-17 22:55:25 -07:00
parent 023772142a
commit 2c1ba312b3
2 changed files with 25 additions and 6 deletions

View File

@ -27,6 +27,7 @@ import org.telegram.telegrambots.meta.api.objects.User;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.*; import java.util.*;
import java.util.concurrent.Callable;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
@ -557,15 +558,25 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
boolean filterReply(Update update) { boolean filterReply(Update update) {
return replies.stream() return replies.stream()
.filter(reply -> reply.isOkFor(update)) .filter(reply -> runSilently(() -> reply.isOkFor(update), reply.name()))
.map(reply -> { .map(reply -> runSilently(() -> {
reply.actOn(update); reply.actOn(update);
updateReplyStats(reply); updateReplyStats(reply);
return false; return false;
}) }, reply.name()))
.reduce(true, Boolean::logicalAnd); .reduce(true, Boolean::logicalAnd);
} }
boolean runSilently(Callable<Boolean> callable, String name) {
try {
return callable.call();
} catch(Exception ex) {
log.error(format("Reply [%s] failed to check for conditions. " +
"Make sure you're safeguarding against all possible updates.", name));
}
return false;
}
boolean checkMessageFlags(Trio<Update, Ability, String[]> trio) { boolean checkMessageFlags(Trio<Update, Ability, String[]> trio) {
Ability ability = trio.b(); Ability ability = trio.b();
Update update = trio.a(); Update update = trio.a();

View File

@ -146,10 +146,8 @@ public class ReplyFlowTest {
@Test @Test
void replyFlowsPertainNames() { void replyFlowsPertainNames() {
Update update1 = mockFullUpdate(bot, USER, "one");
long chatId = getChatId(update1);
Set<String> replyNames = bot.replies().stream().map(Reply::name).collect(Collectors.toSet()); Set<String> replyNames = bot.replies().stream().map(Reply::name).collect(Collectors.toSet());
replyNames.containsAll(newHashSet("FIRST", "SECOND")); assertTrue(replyNames.containsAll(newHashSet("FIRST", "SECOND")));
} }
public static class ReplyFlowBot extends AbilityBot { public static class ReplyFlowBot extends AbilityBot {
@ -183,6 +181,16 @@ public class ReplyFlowTest {
.build(); .build();
} }
public Reply errantReply() {
return Reply.of(
upd -> {
throw new RuntimeException("Throwing an exception inside the update consumer");
},
upd -> {
throw new RuntimeException("Throwing an exception inside the reply conditions (flags)");
});
}
public Ability replyFlowsWithAbility() { public Ability replyFlowsWithAbility() {
Reply replyWithVk = ReplyFlow.builder(db, 2) Reply replyWithVk = ReplyFlow.builder(db, 2)
.enableStats("SECOND") .enableStats("SECOND")