From c5aa330421c1aa8da561c2a11d31ce91a4381f01 Mon Sep 17 00:00:00 2001 From: Ivan Galushko Date: Sun, 24 Nov 2024 00:03:29 +0300 Subject: [PATCH] [FIX]: fix scenario event handling and add docs --- README.md | 3 ++ .../exception/type/ScenarioException.java | 19 ++++++++++++ .../telegram/handler/scenario/Scenario.java | 4 +-- .../handler/scenario/ScenarioEventResult.java | 31 +++++++++++++++++++ .../scenario/ScenarioUpdateHandler.java | 15 ++++++--- .../handler/scenario/SimpleScenario.java | 16 ++++++---- .../handler/scenario/ScenarioTest.java | 8 ++--- 7 files changed, 79 insertions(+), 17 deletions(-) create mode 100644 src/main/java/io/github/drednote/telegram/exception/type/ScenarioException.java create mode 100644 src/main/java/io/github/drednote/telegram/handler/scenario/ScenarioEventResult.java diff --git a/README.md b/README.md index 8be04eb..d63fbe6 100644 --- a/README.md +++ b/README.md @@ -499,6 +499,9 @@ handling. Here are some important rules to keep in mind: process - Methods marked with `@TelegramExceptionHandler` annotation can accept a specific set of inputs parameters as defined in the [Argument resolving](#argument-resolving) section +- Methods marked with `@TelegramExceptionHandler` annotation can return any object, as a result. The + response processing mechanism is detailed in the [Response Processing](#response-processing) + section ### Argument resolving diff --git a/src/main/java/io/github/drednote/telegram/exception/type/ScenarioException.java b/src/main/java/io/github/drednote/telegram/exception/type/ScenarioException.java new file mode 100644 index 0000000..0a076f8 --- /dev/null +++ b/src/main/java/io/github/drednote/telegram/exception/type/ScenarioException.java @@ -0,0 +1,19 @@ +package io.github.drednote.telegram.exception.type; + +/** + * Exception that throws during scenario processing. + */ +public class ScenarioException extends TelegramException { + + public ScenarioException(String message) { + super(message); + } + + public ScenarioException(String message, Throwable cause) { + super(message, cause); + } + + public ScenarioException(Throwable cause) { + super(cause); + } +} diff --git a/src/main/java/io/github/drednote/telegram/handler/scenario/Scenario.java b/src/main/java/io/github/drednote/telegram/handler/scenario/Scenario.java index 4fd4972..6027ec2 100644 --- a/src/main/java/io/github/drednote/telegram/handler/scenario/Scenario.java +++ b/src/main/java/io/github/drednote/telegram/handler/scenario/Scenario.java @@ -29,9 +29,9 @@ public interface Scenario { * Sends an event to the scenario. * * @param request the update request to be processed - * @return true if the event was successfully handled, false otherwise + * @return the result of event handling. */ - boolean sendEvent(UpdateRequest request); + ScenarioEventResult sendEvent(UpdateRequest request); /** * Checks if the scenario matches the specified update request. diff --git a/src/main/java/io/github/drednote/telegram/handler/scenario/ScenarioEventResult.java b/src/main/java/io/github/drednote/telegram/handler/scenario/ScenarioEventResult.java new file mode 100644 index 0000000..f16ad11 --- /dev/null +++ b/src/main/java/io/github/drednote/telegram/handler/scenario/ScenarioEventResult.java @@ -0,0 +1,31 @@ +package io.github.drednote.telegram.handler.scenario; + +import io.github.drednote.telegram.core.request.UpdateRequest; +import org.springframework.lang.Nullable; + +/** + * Result of a handling event. + * + * @author Ivan Galushko + * @see Scenario#sendEvent(UpdateRequest) + */ +public interface ScenarioEventResult { + + /** + * @return true if the event was successfully handled, false otherwise. + */ + boolean success(); + + /** + * @return exception that thrown during scenario processing, null otherwise. + */ + @Nullable + Exception exception(); + + /** + * Default realization of {@code ScenarioEventResult} + */ + record SimpleScenarioEventResult( + boolean success, @Nullable Exception exception + ) implements ScenarioEventResult {} +} diff --git a/src/main/java/io/github/drednote/telegram/handler/scenario/ScenarioUpdateHandler.java b/src/main/java/io/github/drednote/telegram/handler/scenario/ScenarioUpdateHandler.java index 1ac0e69..afed6d2 100644 --- a/src/main/java/io/github/drednote/telegram/handler/scenario/ScenarioUpdateHandler.java +++ b/src/main/java/io/github/drednote/telegram/handler/scenario/ScenarioUpdateHandler.java @@ -13,14 +13,19 @@ public class ScenarioUpdateHandler implements UpdateHandler { @Override - public void onUpdate(UpdateRequest request) { + public void onUpdate(UpdateRequest request) throws Exception { Scenario scenario = request.getScenario(); if (scenario != null) { - ScenarioIdResolver idResolver = scenario.getAccessor().getIdResolver(); - final String id = scenario.getId(); - boolean sendEvent = scenario.sendEvent(request); - if (sendEvent) { + ScenarioEventResult eventResult = scenario.sendEvent(request); + if (eventResult.success()) { + String id = scenario.getId(); + ScenarioIdResolver idResolver = scenario.getAccessor().getIdResolver(); idResolver.saveNewId(request, id); + } else { + Exception exception = eventResult.exception(); + if (exception != null) { + throw exception; + } } } } diff --git a/src/main/java/io/github/drednote/telegram/handler/scenario/SimpleScenario.java b/src/main/java/io/github/drednote/telegram/handler/scenario/SimpleScenario.java index 7afb134..f36fac9 100644 --- a/src/main/java/io/github/drednote/telegram/handler/scenario/SimpleScenario.java +++ b/src/main/java/io/github/drednote/telegram/handler/scenario/SimpleScenario.java @@ -4,6 +4,8 @@ import io.github.drednote.telegram.core.request.UpdateRequest; import io.github.drednote.telegram.core.request.UpdateRequestMapping; import io.github.drednote.telegram.core.request.UpdateRequestMappingAccessor; +import io.github.drednote.telegram.exception.type.ScenarioException; +import io.github.drednote.telegram.handler.scenario.ScenarioEventResult.SimpleScenarioEventResult; import io.github.drednote.telegram.handler.scenario.data.SimpleState; import io.github.drednote.telegram.handler.scenario.data.State; import io.github.drednote.telegram.handler.scenario.data.Transition; @@ -37,14 +39,16 @@ public SimpleScenario( } @Override - public boolean sendEvent(UpdateRequest request) { + public ScenarioEventResult sendEvent(UpdateRequest request) { synchronized (this) { if (isTerminated()) { - return false; + return new SimpleScenarioEventResult(false, + new ScenarioException("Scenario has been terminated")); } Optional> optionalSTransition = findTransition(request); if (optionalSTransition.isEmpty()) { - return false; + return new SimpleScenarioEventResult(false, + new ScenarioException("Transition not found")); } Transition transition = optionalSTransition.get(); State target = transition.getTarget(); @@ -54,12 +58,12 @@ public boolean sendEvent(UpdateRequest request) { Object response = target.execute(context); ResponseSetter.setResponse(request, response); } catch (Exception e) { - log.error("Unhandled exception", e); - return false; + return new SimpleScenarioEventResult(false, + new ScenarioException("During scenario event unhandled exception happened", e)); } this.state = target; - return true; + return new SimpleScenarioEventResult(true, null); } } diff --git a/src/test/java/io/github/drednote/telegram/handler/scenario/ScenarioTest.java b/src/test/java/io/github/drednote/telegram/handler/scenario/ScenarioTest.java index bdf438d..d8cc157 100644 --- a/src/test/java/io/github/drednote/telegram/handler/scenario/ScenarioTest.java +++ b/src/test/java/io/github/drednote/telegram/handler/scenario/ScenarioTest.java @@ -69,9 +69,9 @@ void shouldCorrectChooseNextStateIfPersisterEmpty() { Scenario scenario = factory.create(id); persister.restore(scenario, id); - boolean sendEvent = scenario.sendEvent(updateRequest); + ScenarioEventResult sendEvent = scenario.sendEvent(updateRequest); - assertThat(sendEvent).isTrue(); + assertThat(sendEvent.success()).isTrue(); assertThat(scenario.getState().getId()).isEqualTo("3"); } @@ -85,9 +85,9 @@ void shouldCorrectChooseNextStateIfPersisterNotEmpty() throws IOException { Scenario scenario = factory.create(id); persister.restore(scenario, id); - boolean sendEvent = scenario.sendEvent(updateRequest); + ScenarioEventResult sendEvent = scenario.sendEvent(updateRequest); - assertThat(sendEvent).isTrue(); + assertThat(sendEvent.success()).isTrue(); assertThat(scenario.getState().getId()).isEqualTo("4"); }