in genie-agent/src/main/java/com/netflix/genie/agent/cli/InfoCommand.java [215:338]
private void createStateMachineDotGraph(
final List<ExecutionStage> stages,
final StringBuilder messageBuilder
) {
final List<States> states = Lists.newArrayList();
states.add(States.INITIAL_STATE);
stages.forEach(stage -> states.add(stage.getState()));
states.add(States.FINAL_STATE);
final List<Pair<States, States>> transitions = Lists.newArrayList();
for (int i = 0; i < states.size() - 1; i++) {
transitions.add(Pair.of(states.get(i), states.get(i + 1)));
}
messageBuilder
.append("digraph state_machine {")
.append(NEWLINE);
messageBuilder
.append(" // States")
.append(NEWLINE);
states.forEach(
state -> {
final String shape;
if (state == States.INITIAL_STATE) {
shape = "shape=diamond";
} else if (state == States.FINAL_STATE) {
shape = "shape=rectangle";
} else {
shape = "";
}
final String edgeTickness;
if (state.isCriticalState()) {
edgeTickness = "penwidth=3.0";
} else {
edgeTickness = "";
}
messageBuilder
.append(" ")
.append(state.name())
.append(" [label=")
.append(state.name())
.append(" ")
.append(shape)
.append(" ")
.append(edgeTickness)
.append("]")
.append(NEWLINE);
}
);
messageBuilder
.append(" // Transitions")
.append(NEWLINE);
transitions.forEach(
transition ->
messageBuilder
.append(" ")
.append(transition.getLeft())
.append(" -> ")
.append(transition.getRight())
.append(NEWLINE)
);
messageBuilder
.append(" // Skip transitions")
.append(NEWLINE);
// Draw an edge from a state whose next state is skippable to the next non-skippable state.
for (int i = 0; i < states.size() - 2; i++) {
final States state = states.get(i);
final boolean skipNext = states.get(i + 1).isSkippedDuringAbortedExecution();
if (skipNext) {
// Find the next non-skipped stage
for (int j = i + 1; j < states.size() - 1; j++) {
final States nextState = states.get(j);
if (!nextState.isSkippedDuringAbortedExecution()) {
messageBuilder
.append(" ")
.append(state)
.append(" -> ")
.append(nextState)
.append(" [style=dotted]")
.append(NEWLINE);
break;
}
}
}
}
messageBuilder
.append(" // Retry transitions")
.append(NEWLINE);
states.forEach(
state -> {
final @Min(0) int retries = state.getTransitionRetries();
if (retries > 0) {
messageBuilder
.append(" ")
.append(state)
.append(" -> ")
.append(state)
.append(" [style=dashed label=\"")
.append(retries)
.append(" retries\"]")
.append(NEWLINE);
}
}
);
messageBuilder
.append("}")
.append(NEWLINE)
.append("// ------------------------------------------------------------------------")
.append(NEWLINE);
}