Optimization Server - Run Add Issue Task
This task takes scenarioId and a text message as input, adds the message to the scenario issues collection, then returns an output collector of the modified scenario as a result.
@Configuration
public class Tasks {
@Bean
public ScriptedTaskDescription addIssueWithOptimizationServerTask() {
ScriptedTaskDescription task = new ScriptedTaskDescription("addIssueWithOptimizationServer", "Add Issue with OptimizationServer");
task.setDescription("Add an issue to the selected scenario, using an OptimizationServer task");
task.getScript()
.addStatement(AskInputStatement.of("scenario", true, JobInputType.scenarioId(WRITABLE)))
.addStatement(AskInputStatement.of("Issue Message", true, JobInputType.TEXT, "The text of the issue to add"))
.addStatement(ExecuteOptimizationServerTaskStatement
.forTaskId(StringExpression.of("Add Issue with OptimizationServer"))
.withInput("Issue Message", VariableAccessExpression.of("Issue Message"))
.withInput("inputCollector", ScenarioDataExpression.of(VariableAccessExpression.of("scenario")))
.withOutputScenario("outputCollector", VariableAccessExpression.of("scenario"), StringExpression.of("GeneIssue"), StringExpression.of("Activity")));
return task;
}
}
Note that the table names mentioned in the arguments of withOutputScenario can include list expressions. That is, the corresponding line in the example above could have been written as follows:
.withOutputScenario("outputCollector", VariableAccessExpression.of("scenario"), ListExpression.of(StringExpression.of("GeneIssue"), StringExpression.of("Activity")))
A slightly different version of this task is a task that creates a new scenario (with a name given as input) and adds an issue message to the newly created scenario. To create a new scenario, we use StringExpression.idOfNewScenario() as in the following task:
@Configuration
public class Tasks {
@Bean
public ScriptedTaskDescription addIssueToNewScenarioWithOptimizationServerTask() {
ScriptedTaskDescription task = new ScriptedTaskDescription("createScenarioAndAddIssueWithOptimizationServer", "Add Issue to new scenario");
task.setDescription("Add an issue to a new scenario, using an OptimizationServer task");
task.getScript()
.addStatement(AskInputStatement.of("Issue Message", true, JobInputType.TEXT, "The text of the issue to add"))
.addStatement(AskInputStatement.of("Scenario Name", true, JobInputType.TEXT, "The name of the scenario to create"))
.addStatement(AskInputStatement.of("workspace", true, JobInputType.WORKSPACE_ID, "The Workspace where to create the new Scenario"))
.addStatement(SetVariableStatement.of("scenarioId", StringExpression.idOfNewScenario(VariableAccessExpression.of("Scenario Name"), VariableAccessExpression.of("workspace"))))
.addStatement(ExecuteOptimizationServerTaskStatement
.forTaskId(StringExpression.of("Add Issue with OptimizationServer"))
.withInput("Issue Message", VariableAccessExpression.of("Issue Message"))
.withInput("inputCollector", ScenarioDataExpression.of(VariableAccessExpression.of("scenarioId")))
.withOutputScenario("outputCollector", VariableAccessExpression.of("scenarioId"), StringExpression.of("GeneIssue")));
return task;
}
}
The OptimizationServer task with id "Add Issue with OptimizationServer" (for both versions above) is defined in OptimizationServer tasks configuration in worker.yml as follows:
tasks:
- id: Add Issue with OptimizationServer
implementationClassName: com.decisionbrain.gene.execution.worker.AddIssueTask
description: This task adds an issue to the provided scenario
inputs:
- name: Issue Message
type: TEXT
description: The text of the issue to add
required: true
- name: inputCollector
type: BINARY
description: Collector with initial data
required: true
outputs:
- name: outputCollector
type: BINARY
description: Collector with initial data plus added issue
required: true
With the following implementation class:
import com.decisionbrain.optimserver.common.parameter.Parameter;
import com.decisionbrain.optimserver.worker.api.ExecutionContext;
import com.decisionbrain.optimserver.worker.api.Task;
import com.decisionbrain.sample.model.Activity;
import com.decisionbrain.sample.model.CapacityPlanning;
import com.decisionbrain.sample.model.GeneIssue;
import com.decisionbrain.sample.model.impl.CapacityPlanningFactoryImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.Arrays;
public class AddIssueTask implements Task {
private static final Logger LOGGER = LoggerFactory.getLogger("AddIssueTask");
@Override
public void execute(Parameter input, Parameter output, ExecutionContext context) {
CapacityPlanning collector = getInputCollector(input);
LOGGER.info("Seeing {} existing issues", collector.getIssues().size());
GeneIssue issue = collector.createGeneIssue();
issue.setSeverity("INFO");
issue.setMessage(new String(input.get("Issue Message")));
emitOutputCollector(output, collector);
}
private CapacityPlanning getInputCollector(Parameter input) {
try {
CapacityPlanning collector = new CapacityPlanningFactoryImpl().createCollector();
byte[] inputData = input.get("inputCollector");
collector.loadSnapshot(inputData);
return collector;
} catch (Exception e) {
throw new RuntimeException("Error while preparing data", e);
}
}
private void emitOutputCollector(Parameter output, CapacityPlanning collector) {
try {
output.emit("outputCollector", collector.saveSnapshot(Arrays.asList(Activity.class, GeneIssue.class)));
} catch (IOException e) {
throw new RuntimeException("Error while saving data", e);
}
}
}