(control) Disable the start button for actors that aren't directly initializable.

(control) Disable the start button for actors that aren't directly initializable.
This commit is contained in:
Viktor Lofgren 2023-07-31 14:18:52 +02:00
parent 12bd74d4f3
commit 6b5fb0f841
6 changed files with 42 additions and 3 deletions

View File

@ -42,6 +42,7 @@ public class StateMachine {
private final List<BiConsumer<String, String>> stateChangeListeners = new ArrayList<>();
private final Map<String, MachineState> 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

View File

@ -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<GraphState> declaredStates() {
Set<GraphState> ret = new HashSet<>();

View File

@ -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);
}

View File

@ -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";

View File

@ -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();
}

View File

@ -23,7 +23,19 @@
action="/fsms/{{name}}/start"
method="post"
onsubmit="return toggleActorSwitch('{{name}}')">
<input type="submit" value="Off" class="toggle-switch-off" id="toggle-{{name}}-button">
<input
type="submit"
{{#unless canStart}}
disabled
value="Stop"
title="This actor cannot be started here"
{{/unless}}
{{#if canStart}}
value="Off"
{{/if}}
class="toggle-switch-off"
id="toggle-{{name}}-button">
</form>
{{/if}}