[Fix] EventBasedExecutionHandler now executes next action in same TX

This commit is contained in:
Robert von Burg 2017-05-09 12:43:32 +02:00
parent 881cce9c91
commit ade6b5374d
2 changed files with 47 additions and 20 deletions

View File

@ -12,7 +12,6 @@ import li.strolch.execution.command.SetActionToStoppedCommand;
import li.strolch.execution.command.SetActionToWarningCommand;
import li.strolch.execution.policy.ExecutionPolicy;
import li.strolch.model.Locator;
import li.strolch.model.State;
import li.strolch.model.activity.Action;
import li.strolch.model.activity.Activity;
import li.strolch.model.activity.IActivityElement;
@ -161,24 +160,23 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
});
}
private void toExecution(String realm, Locator activityLoc, PrivilegeContext ctx) {
private void toExecution(String realm, Locator elementLoc, PrivilegeContext ctx) {
try (StrolchTransaction tx = openTx(realm, ctx.getCertificate(), ExecuteActivityCommand.class)) {
Locator rootElemLoc = activityLoc.trim(3);
tx.lock(rootElemLoc);
IActivityElement elem = tx.findElement(rootElemLoc);
if (elem == null) {
logger.error("Element for locator " + activityLoc + " does not exist!");
Locator activityLoc = elementLoc.trim(3);
tx.lock(activityLoc);
Activity activity = tx.findElement(activityLoc);
if (activity == null) {
logger.error("Element for locator " + elementLoc + " does not exist!");
synchronized (this.registeredActivities) {
this.registeredActivities.removeElement(realm, rootElemLoc);
this.registeredActivities.removeElement(realm, activityLoc);
}
return;
}
DBC.INTERIM.assertEquals("toExecution only for Activity!", Activity.class, elem.getClass());
ExecuteActivityCommand command = new ExecuteActivityCommand(getContainer(), tx);
command.setActivity((Activity) elem);
command.setActivity(activity);
tx.addCommand(command);
tx.commitOnClose();
@ -190,29 +188,44 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
Locator activityLoc = actionLoc.trim(3);
try (StrolchTransaction tx = openTx(realm, ctx.getCertificate(), SetActionToExecutedCommand.class)) {
tx.lock(activityLoc);
IActivityElement elem = tx.findElement(actionLoc);
DBC.INTERIM.assertEquals("toExecuted only for Action!", Action.class, elem.getClass());
Action action = tx.findElement(actionLoc);
// set this action to executed
SetActionToExecutedCommand command = new SetActionToExecutedCommand(getContainer(), tx);
command.setAction((Action) elem);
command.setAction(action);
tx.addCommand(command);
// flush so we can see that changes performed
tx.flush();
if (elem.getRootElement().getState() == State.EXECUTED) {
// if the activity is now executed, remove it from the registered activities
if (action.getRootElement().getState().isExecuted()) {
synchronized (this.registeredActivities) {
this.registeredActivities.removeElement(realm, activityLoc);
}
logger.info("Activity " + activityLoc + " is in state " + action.getRootElement().getState());
} else {
// otherwise execute any next action(s) for this action's activity
Activity activity = tx.findElement(activityLoc);
ExecuteActivityCommand execCommand = new ExecuteActivityCommand(getContainer(), tx);
execCommand.setActivity(activity);
tx.addCommand(execCommand);
// flush so we can see that changes performed
tx.flush();
}
tx.commitOnClose();
}
// execute any next Action
toExecution(realm, activityLoc, ctx);
// now trigger a further execution of any other activities needed execution in this realm
triggerExecution(realm);
}

View File

@ -6,6 +6,7 @@ import java.util.Iterator;
import java.util.Map.Entry;
import li.strolch.agent.api.ComponentContainer;
import li.strolch.command.UpdateActivityCommand;
import li.strolch.exception.StrolchException;
import li.strolch.execution.policy.ExecutionPolicy;
import li.strolch.model.Resource;
@ -100,8 +101,21 @@ public abstract class ExecutionCommand extends Command implements TimeOrderingVi
public Void visit(Action action) {
ExecutionPolicy executionPolicy = getExecutionPolicy(action);
if (executionPolicy.isExecutable(action))
executionPolicy.toExecution(action);
if (executionPolicy.isExecutable(action)) {
// we catch all exceptions because we can't undo, thus need to set the state to ERROR in this case
// this is only required because we execute actions in same TX as we set to executed any previous actions
try {
executionPolicy.toExecution(action);
} catch (Exception e) {
logger.error("Failed to set " + action.getLocator() + " to execution due to " + e.getMessage(), e);
action.setState(State.ERROR);
UpdateActivityCommand command = new UpdateActivityCommand(getContainer(), tx());
command.setActivity(action.getRootElement());
command.doCommand();
}
}
return null;
}