From 2bfa74df801c45eadeacf5de00418205dab9c2b9 Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Mon, 19 Jul 2010 09:32:26 +0000 Subject: [PATCH] Action execution tracking update Push the logic out to another service, which will shortly also handle cluster wide information on which actions are running (Workflow task 79) git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@21254 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/action-services-context.xml | 16 +- .../repo/action/ActionServiceImpl.java | 114 ++---------- .../action/ActionTrackingServiceImpl.java | 166 ++++++++++++++++++ .../cmr/action/ActionTrackingService.java | 62 +++++++ 4 files changed, 258 insertions(+), 100 deletions(-) create mode 100644 source/java/org/alfresco/repo/action/ActionTrackingServiceImpl.java create mode 100644 source/java/org/alfresco/service/cmr/action/ActionTrackingService.java diff --git a/config/alfresco/action-services-context.xml b/config/alfresco/action-services-context.xml index 0c78de8370..5bf23666ca 100644 --- a/config/alfresco/action-services-context.xml +++ b/config/alfresco/action-services-context.xml @@ -95,12 +95,12 @@ + + + - - - @@ -115,6 +115,16 @@ + + + + + + + + + + diff --git a/source/java/org/alfresco/repo/action/ActionServiceImpl.java b/source/java/org/alfresco/repo/action/ActionServiceImpl.java index c1ece9f01c..26d5676ef3 100644 --- a/source/java/org/alfresco/repo/action/ActionServiceImpl.java +++ b/source/java/org/alfresco/repo/action/ActionServiceImpl.java @@ -38,11 +38,7 @@ import org.alfresco.repo.copy.DefaultCopyBehaviourCallback; import org.alfresco.repo.policy.JavaBehaviour; import org.alfresco.repo.policy.PolicyComponent; import org.alfresco.repo.security.authentication.AuthenticationContext; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.transaction.AlfrescoTransactionSupport; -import org.alfresco.repo.transaction.TransactionListenerAdapter; -import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.ActionCondition; import org.alfresco.service.cmr.action.ActionConditionDefinition; @@ -51,6 +47,7 @@ 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.ActionTrackingService; import org.alfresco.service.cmr.action.CompositeAction; import org.alfresco.service.cmr.action.CompositeActionCondition; import org.alfresco.service.cmr.action.ParameterConstraint; @@ -66,12 +63,12 @@ import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.RegexQNamePattern; import org.alfresco.service.transaction.TransactionService; import org.alfresco.util.GUID; +import org.alfresco.util.PropertyCheck; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; -import org.alfresco.util.PropertyCheck; /** * Action service implementation @@ -108,8 +105,8 @@ public class ActionServiceImpl implements ActionService, RuntimeActionService, A private NodeService nodeService; private SearchService searchService; private DictionaryService dictionaryService; - private TransactionService transactionService; private AuthenticationContext authenticationContext; + private ActionTrackingService actionTrackingService; private PolicyComponent policyComponent; /** @@ -177,6 +174,16 @@ public class ActionServiceImpl implements ActionService, RuntimeActionService, A this.authenticationContext = authenticationContext; } + /** + * Set the action tracking service + * + * @param actionTrackingService the action tracking service + */ + public void setActionTrackingService(ActionTrackingService actionTrackingService) + { + this.actionTrackingService = actionTrackingService; + } + /** * Set the dictionary service * @@ -187,16 +194,6 @@ public class ActionServiceImpl implements ActionService, RuntimeActionService, A this.dictionaryService = dictionaryService; } - /** - * Set the transaction service - * - * @param transactionService the transaction service - */ - public void setTransactionService(TransactionService transactionService) - { - this.transactionService = transactionService; - } - /** * @param policyComponent used to set up the action-based policy behaviour */ @@ -672,20 +669,13 @@ public class ActionServiceImpl implements ActionService, RuntimeActionService, A if (checkConditions == false || evaluateAction(action, actionedUponNodeRef) == true) { // Mark the action as starting - ((ActionImpl)action).setExecutionStartDate(new Date()); - ((ActionImpl)action).setExecutionStatus(ActionStatus.Running); + actionTrackingService.recordActionExecuting(action); // Execute the action directActionExecution(action, actionedUponNodeRef); // Mark it as having worked - ((ActionImpl)action).setExecutionEndDate(new Date()); - ((ActionImpl)action).setExecutionStatus(ActionStatus.Completed); - ((ActionImpl)action).setExecutionFailureMessage(null); - if(action.getNodeRef() != null) - { - saveActionImpl(action.getNodeRef(), action); - } + actionTrackingService.recordActionComplete(action); } } finally @@ -724,7 +714,7 @@ public class ActionServiceImpl implements ActionService, RuntimeActionService, A } // Have the failure logged on the action - recordActionFailure(action, exception); + actionTrackingService.recordActionFailure(action, exception); // Rethrow the exception if (exception instanceof RuntimeException) @@ -740,76 +730,6 @@ public class ActionServiceImpl implements ActionService, RuntimeActionService, A } } - /** - * Schedule the recording of the action failure to occur - * in another transaction - */ - protected void recordActionFailure(Action action, Throwable exception) - { - if (logger.isDebugEnabled() == true) - { - logger.debug("Will shortly record failure of action " + action + " due to " + exception.getMessage()); - } - - ((ActionImpl)action).setExecutionEndDate(new Date()); - ((ActionImpl)action).setExecutionStatus(ActionStatus.Failed); - ((ActionImpl)action).setExecutionFailureMessage(exception.getMessage()); - - if(action.getNodeRef() != null) - { - // Take a local copy of the details - // (That way, if someone has a reference to the - // action and plays with it, we still save the - // correct information) - final String actionId = action.getId(); - final Date startedAt = action.getExecutionStartDate(); - final Date endedAt = action.getExecutionEndDate(); - final String message = action.getExecutionFailureMessage(); - final NodeRef actionNode = action.getNodeRef(); - - // Have the details updated on the action as soon - // as the transaction has finished rolling back - AlfrescoTransactionSupport.bindListener( - new TransactionListenerAdapter() { - public void afterRollback() - { - transactionService.getRetryingTransactionHelper().doInTransaction( - new RetryingTransactionCallback() - { - public Object execute() throws Throwable - { - // Update the action as the system user - return AuthenticationUtil.runAs(new RunAsWork() { - public Action doWork() throws Exception - { - // Grab the latest version of the action - ActionImpl action = (ActionImpl)createAction(actionNode); - - // Update it - action.setExecutionStartDate(startedAt); - action.setExecutionEndDate(endedAt); - action.setExecutionStatus(ActionStatus.Failed); - action.setExecutionFailureMessage(message); - saveActionImpl(actionNode, action); - - if (logger.isDebugEnabled() == true) - { - logger.debug("Recorded failure of action " + actionId + ", node " + actionNode + " due to " + message); - } - - // All done - return action; - } - }, AuthenticationUtil.SYSTEM_USER_NAME); - } - }, false, true - ); - } - } - ); - } - } - /** * @see org.alfresco.repo.action.RuntimeActionService#directActionExecution(org.alfresco.service.cmr.action.Action, * org.alfresco.service.cmr.repository.NodeRef) @@ -1633,7 +1553,7 @@ public class ActionServiceImpl implements ActionService, RuntimeActionService, A if (pendingActions.contains(pendingAction) == false) { pendingActions.add(pendingAction); - ((ActionImpl)action).setExecutionStatus(ActionStatus.Pending); + actionTrackingService.recordActionPending(action); } } } diff --git a/source/java/org/alfresco/repo/action/ActionTrackingServiceImpl.java b/source/java/org/alfresco/repo/action/ActionTrackingServiceImpl.java new file mode 100644 index 0000000000..3f4d634116 --- /dev/null +++ b/source/java/org/alfresco/repo/action/ActionTrackingServiceImpl.java @@ -0,0 +1,166 @@ +/* + * 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 . + */ +package org.alfresco.repo.action; + +import java.util.Date; + +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.repo.transaction.AlfrescoTransactionSupport; +import org.alfresco.repo.transaction.TransactionListenerAdapter; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.service.cmr.action.Action; +import org.alfresco.service.cmr.action.ActionStatus; +import org.alfresco.service.cmr.action.ActionTrackingService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.transaction.TransactionService; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Action execution tracking service implementation + * + * @author Nick Burch + */ +public class ActionTrackingServiceImpl implements ActionTrackingService +{ + /** + * The logger + */ + private static Log logger = LogFactory.getLog(ActionTrackingServiceImpl.class); + + private TransactionService transactionService; + private RuntimeActionService runtimeActionService; + + /** + * Set the transaction service + * + * @param transactionService the transaction service + */ + public void setTransactionService(TransactionService transactionService) + { + this.transactionService = transactionService; + } + + /** + * Set the runtime action service + * + * @param runtimeActionService the runtime action service + */ + public void setRuntimeActionService(RuntimeActionService runtimeActionService) + { + this.runtimeActionService = runtimeActionService; + } + + + public void recordActionPending(Action action) + { + ((ActionImpl)action).setExecutionStatus(ActionStatus.Pending); + } + + public void recordActionComplete(Action action) + { + // Mark it as having worked + ((ActionImpl)action).setExecutionEndDate(new Date()); + ((ActionImpl)action).setExecutionStatus(ActionStatus.Completed); + ((ActionImpl)action).setExecutionFailureMessage(null); + if(action.getNodeRef() != null) + { + runtimeActionService.saveActionImpl(action.getNodeRef(), action); + } + } + + public void recordActionExecuting(Action action) + { + // Mark the action as starting + ((ActionImpl)action).setExecutionStartDate(new Date()); + ((ActionImpl)action).setExecutionStatus(ActionStatus.Running); + } + + /** + * Schedule the recording of the action failure to occur + * in another transaction + */ + public void recordActionFailure(Action action, Throwable exception) + { + if (logger.isDebugEnabled() == true) + { + logger.debug("Will shortly record failure of action " + action + " due to " + exception.getMessage()); + } + + ((ActionImpl)action).setExecutionEndDate(new Date()); + ((ActionImpl)action).setExecutionStatus(ActionStatus.Failed); + ((ActionImpl)action).setExecutionFailureMessage(exception.getMessage()); + + if(action.getNodeRef() != null) + { + // Take a local copy of the details + // (That way, if someone has a reference to the + // action and plays with it, we still save the + // correct information) + final String actionId = action.getId(); + final Date startedAt = action.getExecutionStartDate(); + final Date endedAt = action.getExecutionEndDate(); + final String message = action.getExecutionFailureMessage(); + final NodeRef actionNode = action.getNodeRef(); + + // Have the details updated on the action as soon + // as the transaction has finished rolling back + AlfrescoTransactionSupport.bindListener( + new TransactionListenerAdapter() { + public void afterRollback() + { + transactionService.getRetryingTransactionHelper().doInTransaction( + new RetryingTransactionCallback() + { + public Object execute() throws Throwable + { + // Update the action as the system user + return AuthenticationUtil.runAs(new RunAsWork() { + public Action doWork() throws Exception + { + // Grab the latest version of the action + ActionImpl action = (ActionImpl) + runtimeActionService.createAction(actionNode); + + // Update it + action.setExecutionStartDate(startedAt); + action.setExecutionEndDate(endedAt); + action.setExecutionStatus(ActionStatus.Failed); + action.setExecutionFailureMessage(message); + runtimeActionService.saveActionImpl(actionNode, action); + + if (logger.isDebugEnabled() == true) + { + logger.debug("Recorded failure of action " + actionId + ", node " + actionNode + " due to " + message); + } + + // All done + return action; + } + }, AuthenticationUtil.SYSTEM_USER_NAME); + } + }, false, true + ); + } + } + ); + } + } +} diff --git a/source/java/org/alfresco/service/cmr/action/ActionTrackingService.java b/source/java/org/alfresco/service/cmr/action/ActionTrackingService.java new file mode 100644 index 0000000000..843e88bb20 --- /dev/null +++ b/source/java/org/alfresco/service/cmr/action/ActionTrackingService.java @@ -0,0 +1,62 @@ +/* + * 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 . + */ +package org.alfresco.service.cmr.action; + +import org.alfresco.service.PublicService; + +/** + * Service interface for tracking when actions + * begin to run, complete or fail. + * + * @author Nick Burch + */ +@PublicService +public interface ActionTrackingService +{ + /** + * Record that an action has been scheduled for + * asynchronous execution, and is pending + * being executed. + * + * @param action the action that has been scheduled + */ + void recordActionPending(Action action); + + /** + * Record that an action has begun execution. + * + * @param action the action that has begun execution + */ + void recordActionExecuting(Action action); + + /** + * Record that an action has completed execution + * without error. + * + * @param action the action that has been finished + */ + void recordActionComplete(Action action); + + /** + * Record that an action failed during execution + * + * @param action the action that has failed + */ + void recordActionFailure(Action action, Throwable problem); +}