From 6b5fb0f841932afd18b1ee9b29a1bbbf3114f86d Mon Sep 17 00:00:00 2001 From: Viktor Lofgren Date: Mon, 31 Jul 2023 14:18:52 +0200 Subject: [PATCH] (control) Disable the start button for actors that aren't directly initializable. (control) Disable the start button for actors that aren't directly initializable. --- .../java/nu/marginalia/mqsm/StateMachine.java | 7 +++++++ .../marginalia/mqsm/graph/AbstractStateGraph.java | 15 +++++++++++++++ .../marginalia/control/actor/ControlActors.java | 4 ++++ .../marginalia/control/model/ActorRunState.java | 2 +- .../control/svc/ControlActorService.java | 3 ++- .../templates/control/partials/actors-table.hdb | 14 +++++++++++++- 6 files changed, 42 insertions(+), 3 deletions(-) diff --git a/code/common/message-queue/src/main/java/nu/marginalia/mqsm/StateMachine.java b/code/common/message-queue/src/main/java/nu/marginalia/mqsm/StateMachine.java index 1ef80abb..a2567698 100644 --- a/code/common/message-queue/src/main/java/nu/marginalia/mqsm/StateMachine.java +++ b/code/common/message-queue/src/main/java/nu/marginalia/mqsm/StateMachine.java @@ -42,6 +42,7 @@ public class StateMachine { private final List> stateChangeListeners = new ArrayList<>(); private final Map allStates = new HashMap<>(); + private final boolean isDirectlyInitializable; public StateMachine(MessageQueueFactory messageQueueFactory, String queueName, @@ -57,6 +58,7 @@ public class StateMachine { registerStates(List.of(errorState, finalState, resumingState)); registerStates(stateGraph); + isDirectlyInitializable = stateGraph.isDirectlyInitializable(); for (var declaredState : stateGraph.declaredStates()) { if (!allStates.containsKey(declaredState.name())) { @@ -339,6 +341,11 @@ public class StateMachine { smInbox.abortCurrentTask(); } + /** Returns true if there is an INITIAL state that requires no parameters */ + public boolean isDirectlyInitializable() { + return isDirectlyInitializable; + } + private class StateEventSubscription implements MqSubscription { @Override diff --git a/code/common/message-queue/src/main/java/nu/marginalia/mqsm/graph/AbstractStateGraph.java b/code/common/message-queue/src/main/java/nu/marginalia/mqsm/graph/AbstractStateGraph.java index 098c4333..477788ef 100644 --- a/code/common/message-queue/src/main/java/nu/marginalia/mqsm/graph/AbstractStateGraph.java +++ b/code/common/message-queue/src/main/java/nu/marginalia/mqsm/graph/AbstractStateGraph.java @@ -39,6 +39,21 @@ public abstract class AbstractStateGraph { throw new ControlFlowException("ERROR", ex.getClass().getSimpleName() + ":" + ex.getMessage()); } + /** Check whether there is an INITIAL state that can be directly initialized + * without declared parameters. */ + public boolean isDirectlyInitializable() { + for (var method : getClass().getMethods()) { + var gs = method.getAnnotation(GraphState.class); + if (gs == null) { + continue; + } + if ("INITIAL".equals(gs.name()) && method.getParameterCount() == 0) { + return true; + } + } + return false; + } + public Set declaredStates() { Set ret = new HashSet<>(); diff --git a/code/services-satellite/control-service/src/main/java/nu/marginalia/control/actor/ControlActors.java b/code/services-satellite/control-service/src/main/java/nu/marginalia/control/actor/ControlActors.java index 052ca2cb..12f15bf9 100644 --- a/code/services-satellite/control-service/src/main/java/nu/marginalia/control/actor/ControlActors.java +++ b/code/services-satellite/control-service/src/main/java/nu/marginalia/control/actor/ControlActors.java @@ -112,6 +112,10 @@ public class ControlActors { ); } + public boolean isDirectlyInitializable(Actor actor) { + return actorDefinitions.get(actor).isDirectlyInitializable(); + } + public AbstractStateGraph getActorDefinition(Actor actor) { return actorDefinitions.get(actor); } diff --git a/code/services-satellite/control-service/src/main/java/nu/marginalia/control/model/ActorRunState.java b/code/services-satellite/control-service/src/main/java/nu/marginalia/control/model/ActorRunState.java index 69903ef0..152af472 100644 --- a/code/services-satellite/control-service/src/main/java/nu/marginalia/control/model/ActorRunState.java +++ b/code/services-satellite/control-service/src/main/java/nu/marginalia/control/model/ActorRunState.java @@ -1,6 +1,6 @@ package nu.marginalia.control.model; -public record ActorRunState(String name, String state, boolean terminal) { +public record ActorRunState(String name, String state, boolean terminal, boolean canStart) { public String stateIcon() { if (terminal) { return "\uD83D\uDE34"; diff --git a/code/services-satellite/control-service/src/main/java/nu/marginalia/control/svc/ControlActorService.java b/code/services-satellite/control-service/src/main/java/nu/marginalia/control/svc/ControlActorService.java index 25461e58..aa0ed905 100644 --- a/code/services-satellite/control-service/src/main/java/nu/marginalia/control/svc/ControlActorService.java +++ b/code/services-satellite/control-service/src/main/java/nu/marginalia/control/svc/ControlActorService.java @@ -90,8 +90,9 @@ public class ControlActorService { final String machineName = e.getKey().name(); final String stateName = state.name(); final boolean terminal = state.isFinal(); + final boolean canStart = controlActors.isDirectlyInitializable(e.getKey()) && terminal; - return new ActorRunState(machineName, stateName, terminal); + return new ActorRunState(machineName, stateName, terminal, canStart); }).toList(); } diff --git a/code/services-satellite/control-service/src/main/resources/templates/control/partials/actors-table.hdb b/code/services-satellite/control-service/src/main/resources/templates/control/partials/actors-table.hdb index 9fe27aa6..e77b7b70 100644 --- a/code/services-satellite/control-service/src/main/resources/templates/control/partials/actors-table.hdb +++ b/code/services-satellite/control-service/src/main/resources/templates/control/partials/actors-table.hdb @@ -23,7 +23,19 @@ action="/fsms/{{name}}/start" method="post" onsubmit="return toggleActorSwitch('{{name}}')"> - + {{/if}}