use of io.automatiko.engine.workflow.process.core.NodeContainer in project automatiko-engine by automatiko-io.
the class ServerlessWorkflowFactory method stateDataFilterActionNode.
public ActionNode stateDataFilterActionNode(long id, String name, NodeContainer nodeContainer, String outputFilterString) {
ActionNode actionNode = new ActionNode();
actionNode.setId(id);
actionNode.setName(name);
String outputFilter = unwrapExpression(outputFilterString);
ConsequenceAction processAction = new ConsequenceAction(null, "new io.automatiko.engine.workflow.base.instance.impl.jq.OutputJqAssignmentAction(" + escapeExpression(outputFilter) + ").execute(null, context);");
io.automatiko.engine.workflow.base.instance.impl.Action injectAction = context -> {
new OutputJqAssignmentAction(outputFilter).execute(null, context);
};
processAction.setMetaData(ACTION, injectAction);
actionNode.setAction(processAction);
nodeContainer.addNode(actionNode);
return actionNode;
}
use of io.automatiko.engine.workflow.process.core.NodeContainer in project automatiko-engine by automatiko-io.
the class ServerlessWorkflowParser method buildActionsForState.
protected void buildActionsForState(Workflow workflow, List<Action> actions, NodeContainer embeddedSubProcess, ServerlessWorkflowFactory factory, AtomicLong ids, BiConsumer<Node, Node> firstLastNodeConsumer, BiConsumer<Node, Node> actionConsumer, boolean isParallel) {
Node firstNode = null;
Node lastNode = null;
Node prevNode = null;
for (Action action : actions) {
if (action.getFunctionRef() != null) {
// handle function based action
Optional<FunctionDefinition> functionDefinition = workflow.getFunctions().getFunctionDefs().stream().filter(functionDef -> functionDef.getName().equals(action.getFunctionRef().getRefName())).distinct().findFirst();
if (functionDefinition.get().getType() == FunctionDefinition.Type.EXPRESSION) {
ActionNode actionNode = factory.expressionActionStateNode(ids.getAndIncrement(), action.getName(), embeddedSubProcess, functionDefinition.get().getOperation(), action);
if (firstNode == null) {
firstNode = actionNode;
}
lastNode = actionNode;
} else if (functionDefinition.get().getType() == null || functionDefinition.get().getType() == FunctionDefinition.Type.REST) {
WorkItemNode serviceNode = factory.serviceNode(ids.getAndIncrement(), action, functionDefinition.get(), embeddedSubProcess);
if (firstNode == null) {
firstNode = serviceNode;
}
lastNode = serviceNode;
if (workflow.getTimeouts() != null && workflow.getTimeouts().getActionExecTimeout() != null) {
serviceNode.setMetaData("timeout", String.valueOf(DateTimeUtils.parseDuration(workflow.getTimeouts().getActionExecTimeout())));
}
if (action.getRetryableErrors() != null && !action.getRetryableErrors().isEmpty()) {
List<ErrorDefinition> defs = new ArrayList<>();
for (String errorRef : action.getRetryableErrors()) {
ErrorDefinition errorDef = workflow.getErrors().getErrorDefs().stream().filter(error -> error.getName().equals(errorRef)).findFirst().orElseThrow(() -> new IllegalStateException("Missing error definition for " + errorRef));
defs.add(errorDef);
}
RetryDefinition retry = null;
BoundaryEventNode errorNode = factory.errorBoundaryEventNode(ids.getAndIncrement(), defs, retry, embeddedSubProcess, serviceNode, workflow);
EndNode onErrorEnd = factory.endNode(ids.getAndIncrement(), action.getName() + "onErrorEnd", false, embeddedSubProcess);
factory.connect(errorNode.getId(), onErrorEnd.getId(), "connect_" + errorNode.getId() + "_" + onErrorEnd.getId(), embeddedSubProcess, false);
}
} else {
throw new UnsupportedOperationException(functionDefinition.get().getType() + " is not yet supported");
}
} else if (action.getSubFlowRef() != null) {
// handler sub workflow action definition
String workflowId = Objects.requireNonNull(action.getSubFlowRef().getWorkflowId(), "Workflow id for subworkflow is mandatory");
boolean independent = false;
if (action.getSubFlowRef().getOnParentComplete() != null && action.getSubFlowRef().getOnParentComplete().equals(OnParentComplete.CONTINUE)) {
independent = true;
}
boolean waitForCompletion = true;
if (action.getSubFlowRef().getInvoke().equals(Invoke.ASYNC)) {
waitForCompletion = false;
}
SubProcessNode callactivity = factory.callActivity(ids.getAndIncrement(), action.getName(), workflowId, waitForCompletion, embeddedSubProcess);
callactivity.setIndependent(independent);
callactivity.setProcessVersion(action.getSubFlowRef().getVersion());
if (firstNode == null) {
firstNode = callactivity;
}
lastNode = callactivity;
}
if (action.getSleep() != null && action.getSleep().getBefore() != null) {
TimerNode sleep = factory.timerNode(ids.getAndIncrement(), "sleep-before-" + action.getName(), action.getSleep().getBefore(), embeddedSubProcess);
factory.connect(sleep.getId(), firstNode.getId(), "connection_" + sleep.getId() + "_" + firstNode.getId(), embeddedSubProcess, false);
firstNode = sleep;
}
if (action.getSleep() != null && action.getSleep().getAfter() != null) {
TimerNode sleep = factory.timerNode(ids.getAndIncrement(), "sleep-after-" + action.getName(), action.getSleep().getAfter(), embeddedSubProcess);
factory.connect(lastNode.getId(), sleep.getId(), "connection_" + lastNode.getId() + "_" + sleep.getId(), embeddedSubProcess, false);
lastNode = sleep;
}
actionConsumer.accept(firstNode, lastNode);
if (isParallel && actions.size() > 1) {
// reset first node as all of action nodes will be first nodes
firstNode = null;
} else {
if (prevNode != null) {
factory.connect(prevNode.getId(), lastNode.getId(), "connect_" + prevNode.getId() + "_" + lastNode.getId(), embeddedSubProcess, false);
}
}
prevNode = lastNode;
}
firstLastNodeConsumer.accept(firstNode, lastNode);
}
use of io.automatiko.engine.workflow.process.core.NodeContainer in project automatiko-engine by automatiko-io.
the class ServerlessWorkflowFactory method errorBoundaryEventNode.
public BoundaryEventNode errorBoundaryEventNode(long id, List<ErrorDefinition> defs, RetryDefinition retry, NodeContainer nodeContainer, Node attachedTo, Workflow workflow) {
BoundaryEventNode boundaryEventNode = new BoundaryEventNode();
boundaryEventNode.setId(id);
boundaryEventNode.setName(defs.stream().map(def -> def.getName()).collect(Collectors.joining("|")));
String errorCodes = defs.stream().map(def -> def.getCode()).collect(Collectors.joining(","));
String attachedToId = (String) attachedTo.getMetaData().getOrDefault(UNIQUE_ID_PARAM, Long.toString(attachedTo.getId()));
EventTypeFilter filter = new EventTypeFilter();
filter.setType("Error-" + attachedToId + "-" + errorCodes);
boundaryEventNode.addEventFilter(filter);
boundaryEventNode.setAttachedToNodeId(attachedToId);
boundaryEventNode.setMetaData(UNIQUE_ID_PARAM, Long.toString(id));
boundaryEventNode.setMetaData("EventType", "error");
boundaryEventNode.setMetaData("ErrorEvent", errorCodes);
boundaryEventNode.setMetaData("AttachedTo", attachedToId);
boundaryEventNode.setMetaData("HasErrorEvent", true);
if (retry != null) {
int delayAsInt = ((Long) DateTimeUtils.parseDuration(retry.getDelay())).intValue();
boundaryEventNode.setMetaData("ErrorRetry", retry.getDelay() == null ? DEFAULT_RETRY_AFTER : delayAsInt);
boundaryEventNode.setMetaData("ErrorRetryLimit", retry.getMaxAttempts() == null ? DEFAULT_RETRY_LIMIT : Integer.parseInt(retry.getMaxAttempts()));
if (retry.getMultiplier() != null) {
boundaryEventNode.setMetaData("ErrorRetryIncrementMultiplier", Float.parseFloat(retry.getMultiplier()));
}
}
nodeContainer.addNode(boundaryEventNode);
return boundaryEventNode;
}
use of io.automatiko.engine.workflow.process.core.NodeContainer in project automatiko-engine by automatiko-io.
the class AbstractNodeHandler method start.
public Object start(final String uri, final String localName, final Attributes attrs, final ExtensibleXmlParser parser) throws SAXException {
parser.startElementBuilder(localName, attrs);
NodeContainer nodeContainer = (NodeContainer) parser.getParent();
final Node node = createNode();
final String id = attrs.getValue("id");
node.setId(new Long(id));
final String name = attrs.getValue("name");
node.setName(name);
nodeContainer.addNode(node);
return node;
}
use of io.automatiko.engine.workflow.process.core.NodeContainer in project automatiko-engine by automatiko-io.
the class SequenceFlowHandler method start.
@SuppressWarnings("unchecked")
public Object start(final String uri, final String localName, final Attributes attrs, final ExtensibleXmlParser parser) throws SAXException {
parser.startElementBuilder(localName, attrs);
final String id = attrs.getValue("id");
final String sourceRef = attrs.getValue("sourceRef");
final String targetRef = attrs.getValue("targetRef");
final String bendpoints = attrs.getValue("g:bendpoints");
final String name = attrs.getValue("name");
final String priority = attrs.getValue("https://automatiko.io", "priority");
NodeContainer nodeContainer = (NodeContainer) parser.getParent();
List<SequenceFlow> connections = null;
if (nodeContainer instanceof ExecutableProcess) {
ExecutableProcess process = (ExecutableProcess) nodeContainer;
connections = (List<SequenceFlow>) process.getMetaData(ProcessHandler.CONNECTIONS);
if (connections == null) {
connections = new ArrayList<>();
process.setMetaData(ProcessHandler.CONNECTIONS, connections);
}
} else if (nodeContainer instanceof CompositeNode) {
CompositeNode compositeNode = (CompositeNode) nodeContainer;
connections = (List<SequenceFlow>) compositeNode.getMetaData(ProcessHandler.CONNECTIONS);
if (connections == null) {
connections = new ArrayList<>();
compositeNode.setMetaData(ProcessHandler.CONNECTIONS, connections);
}
}
SequenceFlow connection = new SequenceFlow(id, sourceRef, targetRef);
connection.setBendpoints(bendpoints);
connection.setName(name);
if (priority != null) {
connection.setPriority(Integer.parseInt(priority));
}
if (connections != null) {
connections.add(connection);
}
return connection;
}
Aggregations