mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Action tracking of execution status (Replication 78)
Support for getting the start & end execution times, status and failure reason for actions, persisted if the action is (Execution doesn't update these yet though) git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@21135 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -28,6 +28,7 @@ import java.util.Set;
|
||||
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.action.ActionCondition;
|
||||
import org.alfresco.service.cmr.action.ActionStatus;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
/**
|
||||
@@ -104,6 +105,29 @@ public class ActionImpl extends ParameterizedItemImpl implements Action
|
||||
* Action conditions
|
||||
*/
|
||||
private List<ActionCondition> actionConditions = new ArrayList<ActionCondition>();
|
||||
|
||||
/**
|
||||
* When the action started executing,
|
||||
* or null if it hasn't yet.
|
||||
*/
|
||||
private Date executionStartDate;
|
||||
|
||||
/**
|
||||
* When the action finished executing,
|
||||
* or null if it hasn't yet.
|
||||
*/
|
||||
private Date executionEndDate;
|
||||
|
||||
/**
|
||||
* The status of the action's execution
|
||||
*/
|
||||
private ActionStatus executionStatus = ActionStatus.New;
|
||||
|
||||
/**
|
||||
* Why the action failed to execute fully,
|
||||
* if exists.
|
||||
*/
|
||||
private String executionFailureMessage;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@@ -146,6 +170,10 @@ public class ActionImpl extends ParameterizedItemImpl implements Action
|
||||
this.modifier = action.getModifier();
|
||||
this.nodeRef = action.getNodeRef();
|
||||
this.title = action.getTitle();
|
||||
this.executionStartDate = action.getExecutionStartDate();
|
||||
this.executionEndDate = action.getExecutionEndDate();
|
||||
this.executionStatus = action.getExecutionStatus();
|
||||
this.executionFailureMessage = action.getExecutionFailureMessage();
|
||||
if (action instanceof ActionImpl)
|
||||
{
|
||||
ActionImpl actionImpl = (ActionImpl) action;
|
||||
@@ -437,5 +465,55 @@ public class ActionImpl extends ParameterizedItemImpl implements Action
|
||||
{
|
||||
getParameterValues().putAll(values);
|
||||
}
|
||||
|
||||
public Date getExecutionStartDate() {
|
||||
return executionStartDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Records the date when the action began execution,
|
||||
* normally called by the {@link ActionService} when
|
||||
* it starts running the action.
|
||||
*/
|
||||
public void setExecutionStartDate(Date startDate) {
|
||||
this.executionStartDate = startDate;
|
||||
}
|
||||
|
||||
public Date getExecutionEndDate() {
|
||||
return executionEndDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Records the date when the action finished execution,
|
||||
* normally called by the {@link ActionService} when
|
||||
* the action completes or fails.
|
||||
*/
|
||||
public void setExecutionEndDate(Date endDate) {
|
||||
this.executionEndDate = endDate;
|
||||
}
|
||||
|
||||
public ActionStatus getExecutionStatus() {
|
||||
return executionStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the current execution status. This is
|
||||
* normally called by the {@link ActionService} as
|
||||
* it progresses the Action's execution.
|
||||
*/
|
||||
public void setExecutionStatus(ActionStatus status) {
|
||||
this.executionStatus = status;
|
||||
}
|
||||
|
||||
public String getExecutionFailureMessage() {
|
||||
return executionFailureMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Records the message of the exception which caused the
|
||||
* Action to fail, if any.
|
||||
*/
|
||||
public void setExecutionFailureMessage(String message) {
|
||||
this.executionFailureMessage = message;
|
||||
}
|
||||
}
|
||||
|
@@ -30,6 +30,10 @@ public interface ActionModel
|
||||
static final QName PROP_ACTION_TITLE = QName.createQName(ACTION_MODEL_URI, "actionTitle");
|
||||
static final QName PROP_ACTION_DESCRIPTION = QName.createQName(ACTION_MODEL_URI, "actionDescription");
|
||||
static final QName PROP_EXECUTE_ASYNCHRONOUSLY = QName.createQName(ACTION_MODEL_URI, "executeAsynchronously");
|
||||
static final QName PROP_EXECUTION_START_DATE = QName.createQName(ACTION_MODEL_URI, "executionStartDate");
|
||||
static final QName PROP_EXECUTION_END_DATE = QName.createQName(ACTION_MODEL_URI, "executionEndDate");
|
||||
static final QName PROP_EXECUTION_ACTION_STATUS = QName.createQName(ACTION_MODEL_URI, "executionActionStatus");
|
||||
static final QName PROP_EXECUTION_FAILURE_MESSAGE = QName.createQName(ACTION_MODEL_URI, "executionFailureMessage");
|
||||
static final QName ASSOC_CONDITIONS = QName.createQName(ACTION_MODEL_URI, "conditions");
|
||||
|
||||
static final QName ASSOC_COMPENSATING_ACTION = QName.createQName(ACTION_MODEL_URI, "compensatingAction");
|
||||
|
@@ -46,6 +46,7 @@ import org.alfresco.service.cmr.action.ActionDefinition;
|
||||
import org.alfresco.service.cmr.action.ActionList;
|
||||
import org.alfresco.service.cmr.action.ActionService;
|
||||
import org.alfresco.service.cmr.action.ActionServiceException;
|
||||
import org.alfresco.service.cmr.action.ActionStatus;
|
||||
import org.alfresco.service.cmr.action.CompositeAction;
|
||||
import org.alfresco.service.cmr.action.CompositeActionCondition;
|
||||
import org.alfresco.service.cmr.action.ParameterConstraint;
|
||||
@@ -879,6 +880,12 @@ public class ActionServiceImpl implements ActionService, RuntimeActionService, A
|
||||
props.put(ActionModel.PROP_ACTION_TITLE, action.getTitle());
|
||||
props.put(ActionModel.PROP_ACTION_DESCRIPTION, action.getDescription());
|
||||
props.put(ActionModel.PROP_EXECUTE_ASYNCHRONOUSLY, action.getExecuteAsychronously());
|
||||
|
||||
props.put(ActionModel.PROP_EXECUTION_START_DATE, action.getExecutionStartDate());
|
||||
props.put(ActionModel.PROP_EXECUTION_END_DATE, action.getExecutionEndDate());
|
||||
props.put(ActionModel.PROP_EXECUTION_ACTION_STATUS, action.getExecutionStatus());
|
||||
props.put(ActionModel.PROP_EXECUTION_FAILURE_MESSAGE, action.getExecutionFailureMessage());
|
||||
|
||||
this.nodeService.setProperties(actionNodeRef, props);
|
||||
|
||||
// Update the compensating action (model should enforce the singularity
|
||||
@@ -1283,6 +1290,11 @@ public class ActionServiceImpl implements ActionService, RuntimeActionService, A
|
||||
((ActionImpl) action).setCreatedDate((Date) props.get(ContentModel.PROP_CREATED));
|
||||
((ActionImpl) action).setModifier((String) props.get(ContentModel.PROP_MODIFIER));
|
||||
((ActionImpl) action).setModifiedDate((Date) props.get(ContentModel.PROP_MODIFIED));
|
||||
|
||||
((ActionImpl) action).setExecutionStartDate((Date) props.get(ActionModel.PROP_EXECUTION_START_DATE));
|
||||
((ActionImpl) action).setExecutionEndDate((Date) props.get(ActionModel.PROP_EXECUTION_END_DATE));
|
||||
((ActionImpl) action).setExecutionStatus(ActionStatus.valueOf(props.get(ActionModel.PROP_EXECUTION_ACTION_STATUS)));
|
||||
((ActionImpl) action).setExecutionFailureMessage((String) props.get(ActionModel.PROP_EXECUTION_FAILURE_MESSAGE));
|
||||
|
||||
// Get the compensating action
|
||||
List<ChildAssociationRef> assocs = this.nodeService.getChildAssocs(actionNodeRef, RegexQNamePattern.MATCH_ALL,
|
||||
|
@@ -19,8 +19,7 @@
|
||||
package org.alfresco.repo.action;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -45,6 +44,7 @@ import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.action.ActionCondition;
|
||||
import org.alfresco.service.cmr.action.ActionConditionDefinition;
|
||||
import org.alfresco.service.cmr.action.ActionDefinition;
|
||||
import org.alfresco.service.cmr.action.ActionStatus;
|
||||
import org.alfresco.service.cmr.action.CompositeAction;
|
||||
import org.alfresco.service.cmr.action.CompositeActionCondition;
|
||||
import org.alfresco.service.cmr.action.ParameterDefinition;
|
||||
@@ -55,7 +55,6 @@ import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.alfresco.util.BaseAlfrescoSpringTest;
|
||||
|
||||
/**
|
||||
@@ -1140,6 +1139,83 @@ public class ActionServiceImplTest extends BaseAlfrescoSpringTest
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that we can read, save, load etc the various
|
||||
* execution related details such as started at,
|
||||
* ended at, status and exception
|
||||
*/
|
||||
public void testExecutionTrackingDetails() {
|
||||
Action action = this.actionService.createAction(AddFeaturesActionExecuter.NAME);
|
||||
String actionId = action.getId();
|
||||
|
||||
assertNull(action.getExecutionStartDate());
|
||||
assertNull(action.getExecutionEndDate());
|
||||
assertNull(action.getExecutionFailureMessage());
|
||||
assertEquals(ActionStatus.New, action.getExecutionStatus());
|
||||
|
||||
|
||||
// Save and load, details shouldn't have changed
|
||||
this.actionService.saveAction(this.nodeRef, action);
|
||||
action = (Action)this.actionService.getAction(this.nodeRef, actionId);
|
||||
|
||||
assertNull(action.getExecutionStartDate());
|
||||
assertNull(action.getExecutionEndDate());
|
||||
assertNull(action.getExecutionFailureMessage());
|
||||
assertEquals(ActionStatus.New, action.getExecutionStatus());
|
||||
|
||||
|
||||
// Set some details, ensure they survive a save/load
|
||||
((ActionImpl)action).setExecutionStatus(ActionStatus.Running);
|
||||
((ActionImpl)action).setExecutionStartDate(new Date(12345));
|
||||
|
||||
this.actionService.saveAction(this.nodeRef, action);
|
||||
action = (Action)this.actionService.getAction(this.nodeRef, actionId);
|
||||
|
||||
assertEquals(ActionStatus.Running, action.getExecutionStatus());
|
||||
assertEquals(12345, action.getExecutionStartDate().getTime());
|
||||
assertNull(action.getExecutionEndDate());
|
||||
assertNull(action.getExecutionFailureMessage());
|
||||
|
||||
|
||||
// Set the rest, and change some, ensure they survive a save/load
|
||||
((ActionImpl)action).setExecutionStatus(ActionStatus.Failed);
|
||||
((ActionImpl)action).setExecutionStartDate(new Date(123450));
|
||||
((ActionImpl)action).setExecutionEndDate(new Date(123455));
|
||||
((ActionImpl)action).setExecutionFailureMessage("Testing");
|
||||
|
||||
this.actionService.saveAction(this.nodeRef, action);
|
||||
action = (Action)this.actionService.getAction(this.nodeRef, actionId);
|
||||
|
||||
assertEquals(ActionStatus.Failed, action.getExecutionStatus());
|
||||
assertEquals(123450, action.getExecutionStartDate().getTime());
|
||||
assertEquals(123455, action.getExecutionEndDate().getTime());
|
||||
assertEquals("Testing", action.getExecutionFailureMessage());
|
||||
|
||||
|
||||
// Unset a few, ensure they survive a save/load
|
||||
((ActionImpl)action).setExecutionStatus(null);
|
||||
((ActionImpl)action).setExecutionStartDate(new Date(123450));
|
||||
((ActionImpl)action).setExecutionFailureMessage(null);
|
||||
|
||||
this.actionService.saveAction(this.nodeRef, action);
|
||||
action = (Action)this.actionService.getAction(this.nodeRef, actionId);
|
||||
|
||||
assertEquals(ActionStatus.New, action.getExecutionStatus()); // Default
|
||||
assertEquals(123450, action.getExecutionStartDate().getTime());
|
||||
assertEquals(123455, action.getExecutionEndDate().getTime());
|
||||
assertEquals(null, action.getExecutionFailureMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that when we run an action, either
|
||||
* synchronously or asynchronously, with it
|
||||
* working or failing, that the action execution
|
||||
* service correctly sets the flags
|
||||
*/
|
||||
public void testExecutionTrackingOnExecution() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is only used during JUnit testing.
|
||||
*
|
||||
|
@@ -15,6 +15,20 @@
|
||||
<namespace uri="http://www.alfresco.org/model/action/1.0" prefix="act"/>
|
||||
</namespaces>
|
||||
|
||||
<constraints>
|
||||
<constraint name="act:allowedExecutionstatuses" type="LIST">
|
||||
<parameter name="allowedValues">
|
||||
<list>
|
||||
<value>New</value>
|
||||
<value>Pending</value>
|
||||
<value>Running</value>
|
||||
<value>Completed</value>
|
||||
<value>Cancelled</value>
|
||||
<value>Failed</value>
|
||||
</list>
|
||||
</parameter>
|
||||
</constraint>
|
||||
</constraints>
|
||||
|
||||
<types>
|
||||
|
||||
@@ -64,6 +78,25 @@
|
||||
<type>d:text</type>
|
||||
<mandatory>false</mandatory>
|
||||
</property>
|
||||
<property name="act:executionStartDate">
|
||||
<type>d:date</type>
|
||||
<mandatory>false</mandatory>
|
||||
</property>
|
||||
<property name="act:executionEndDate">
|
||||
<type>d:date</type>
|
||||
<mandatory>false</mandatory>
|
||||
</property>
|
||||
<property name="act:executionActionStatus">
|
||||
<type>d:text</type>
|
||||
<mandatory>false</mandatory>
|
||||
<constraints>
|
||||
<constraint ref="act:allowedExecutionstatuses" />
|
||||
</constraints>
|
||||
</property>
|
||||
<property name="act:executionFailureMessage">
|
||||
<type>d:text</type>
|
||||
<mandatory>false</mandatory>
|
||||
</property>
|
||||
</properties>
|
||||
<associations>
|
||||
<child-association name="act:conditions">
|
||||
|
@@ -208,4 +208,38 @@ public interface Action extends ParameterizedItem
|
||||
* @param values A map of values to be added
|
||||
*/
|
||||
void addParameterValues(Map<String, Serializable> values);
|
||||
|
||||
/**
|
||||
* Gets the date that the action (last) began executing at.
|
||||
* Null if the action has not yet been run.
|
||||
* For a saved action, this will be the last time at ran.
|
||||
* @return The date the action (last) began executing at, or null.
|
||||
*/
|
||||
Date getExecutionStartDate();
|
||||
|
||||
/**
|
||||
* Gets the date that the action (last) finished
|
||||
* execution at.
|
||||
* Null if the action has not yet been run, or is
|
||||
* currently running.
|
||||
* For a saved action, this will normally be the last
|
||||
* time it finished running.
|
||||
* @return The date the action last finished exeucting at, or null.
|
||||
*/
|
||||
Date getExecutionEndDate();
|
||||
|
||||
/**
|
||||
* Gets the current execution status of the action,
|
||||
* such as Running or Completed.
|
||||
* @return The current execution status
|
||||
*/
|
||||
ActionStatus getExecutionStatus();
|
||||
|
||||
/**
|
||||
* Gets the message of the exception which caused the
|
||||
* Action execution failure, or null if the Action
|
||||
* hasn't failed / has been retried.
|
||||
* @return The exception message, if the action has failed
|
||||
*/
|
||||
String getExecutionFailureMessage();
|
||||
}
|
||||
|
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.service.cmr.action;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The various states an Action can be in.
|
||||
*
|
||||
* @author Nick Burch
|
||||
*/
|
||||
public enum ActionStatus
|
||||
{
|
||||
/**
|
||||
* A new Action, which has never been run
|
||||
*/
|
||||
New,
|
||||
/**
|
||||
* An Action which has been scheduled for
|
||||
* Asynchronous execution, but not yet run.
|
||||
*/
|
||||
Pending,
|
||||
/**
|
||||
* Indicates that the Action is currently being
|
||||
* executed by the {@link ActionService}
|
||||
*/
|
||||
Running,
|
||||
/**
|
||||
* The Action was run without error
|
||||
*/
|
||||
Completed,
|
||||
/**
|
||||
* The Action, which must implement
|
||||
* {@link CancellableAction}, detected that a
|
||||
* cancellation was requested and cancelled itself.
|
||||
*/
|
||||
Cancelled,
|
||||
/**
|
||||
* The Action failed to run to completion. Call
|
||||
* {@link Action#getExecutionFailureCause()} to find
|
||||
* out why.
|
||||
*/
|
||||
Failed
|
||||
;
|
||||
|
||||
public static ActionStatus valueOf(Serializable s)
|
||||
{
|
||||
if(s == null) return New;
|
||||
return valueOf((String)s);
|
||||
}
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.service.cmr.action;
|
||||
|
||||
/**
|
||||
* A marker interface that forms part of the Cancel Action contract.
|
||||
* An action that implements this interface commits to periodically
|
||||
* asking the {@link ActionService} if a cancel of it has been
|
||||
* requested, and orderly terminating itself if so.
|
||||
*
|
||||
* @author Nick Burch
|
||||
*/
|
||||
public interface CancellableAction extends Action
|
||||
{
|
||||
}
|
Reference in New Issue
Block a user