mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
ActionTrackingService test updates
Make the cache key generation less brittle, add unit tests for listing functions, and stub out the cancel related tests git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@21332 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -47,6 +47,8 @@ import org.alfresco.service.cmr.action.ActionConditionDefinition;
|
|||||||
import org.alfresco.service.cmr.action.ActionDefinition;
|
import org.alfresco.service.cmr.action.ActionDefinition;
|
||||||
import org.alfresco.service.cmr.action.ActionService;
|
import org.alfresco.service.cmr.action.ActionService;
|
||||||
import org.alfresco.service.cmr.action.ActionStatus;
|
import org.alfresco.service.cmr.action.ActionStatus;
|
||||||
|
import org.alfresco.service.cmr.action.ActionTrackingService;
|
||||||
|
import org.alfresco.service.cmr.action.CancellableAction;
|
||||||
import org.alfresco.service.cmr.action.CompositeAction;
|
import org.alfresco.service.cmr.action.CompositeAction;
|
||||||
import org.alfresco.service.cmr.action.CompositeActionCondition;
|
import org.alfresco.service.cmr.action.CompositeActionCondition;
|
||||||
import org.alfresco.service.cmr.action.ParameterDefinition;
|
import org.alfresco.service.cmr.action.ParameterDefinition;
|
||||||
@@ -1228,7 +1230,8 @@ public class ActionServiceImplTest extends BaseAlfrescoSpringTest
|
|||||||
return createWorkingSleepAction(id, this.actionService);
|
return createWorkingSleepAction(id, this.actionService);
|
||||||
}
|
}
|
||||||
protected static Action createWorkingSleepAction(String id, ActionService actionService) throws Exception {
|
protected static Action createWorkingSleepAction(String id, ActionService actionService) throws Exception {
|
||||||
Action workingAction = actionService.createAction(SleepActionExecuter.NAME);
|
Action workingAction = new CancellableSleepAction(
|
||||||
|
actionService.createAction(SleepActionExecuter.NAME));
|
||||||
if(id != null) {
|
if(id != null) {
|
||||||
Field idF = ParameterizedItemImpl.class.getDeclaredField("id");
|
Field idF = ParameterizedItemImpl.class.getDeclaredField("id");
|
||||||
idF.setAccessible(true);
|
idF.setAccessible(true);
|
||||||
@@ -1267,6 +1270,8 @@ public class ActionServiceImplTest extends BaseAlfrescoSpringTest
|
|||||||
public int getTimesExecuted() {return timesExecuted;}
|
public int getTimesExecuted() {return timesExecuted;}
|
||||||
private Thread executingThread;
|
private Thread executingThread;
|
||||||
|
|
||||||
|
private ActionTrackingService actionTrackingService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads this executor into the ApplicationContext, if it
|
* Loads this executor into the ApplicationContext, if it
|
||||||
* isn't already there
|
* isn't already there
|
||||||
@@ -1275,9 +1280,14 @@ public class ActionServiceImplTest extends BaseAlfrescoSpringTest
|
|||||||
{
|
{
|
||||||
if(!ctx.containsBean(SleepActionExecuter.NAME))
|
if(!ctx.containsBean(SleepActionExecuter.NAME))
|
||||||
{
|
{
|
||||||
|
// Create, and do dependencies
|
||||||
|
SleepActionExecuter executor = new SleepActionExecuter();
|
||||||
|
executor.actionTrackingService = (ActionTrackingService)
|
||||||
|
ctx.getBean("actionTrackingService");
|
||||||
|
// Register
|
||||||
ctx.getBeanFactory().registerSingleton(
|
ctx.getBeanFactory().registerSingleton(
|
||||||
SleepActionExecuter.NAME,
|
SleepActionExecuter.NAME,
|
||||||
new SleepActionExecuter()
|
executor
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1329,6 +1339,19 @@ public class ActionServiceImplTest extends BaseAlfrescoSpringTest
|
|||||||
{
|
{
|
||||||
throw new RuntimeException("Bang!");
|
throw new RuntimeException("Bang!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CancellableSleepAction ca = (CancellableSleepAction)action;
|
||||||
|
boolean cancelled = actionTrackingService.isCancellationRequested(ca);
|
||||||
|
if(cancelled)
|
||||||
|
{
|
||||||
|
throw new RuntimeException("Cancelled!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected static class CancellableSleepAction extends ActionImpl implements CancellableAction
|
||||||
|
{
|
||||||
|
public CancellableSleepAction(Action action) {
|
||||||
|
super(action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -65,6 +65,9 @@ public class ActionTrackingServiceImpl implements ActionTrackingService
|
|||||||
*/
|
*/
|
||||||
private short nextExecutionId = 1;
|
private short nextExecutionId = 1;
|
||||||
|
|
||||||
|
/** How we separate bits of the cache key */
|
||||||
|
private static final char cacheKeyPartSeparator = '=';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the transaction service
|
* Set the transaction service
|
||||||
*
|
*
|
||||||
@@ -291,7 +294,8 @@ public class ActionTrackingServiceImpl implements ActionTrackingService
|
|||||||
public List<ExecutionSummary> getExecutingActions(Action action) {
|
public List<ExecutionSummary> getExecutingActions(Action action) {
|
||||||
Collection<String> actions = executingActionsCache.getKeys();
|
Collection<String> actions = executingActionsCache.getKeys();
|
||||||
List<ExecutionSummary> details = new ArrayList<ExecutionSummary>();
|
List<ExecutionSummary> details = new ArrayList<ExecutionSummary>();
|
||||||
String match = action.getActionDefinitionName() + "-" + action.getId();
|
String match = action.getActionDefinitionName() + cacheKeyPartSeparator +
|
||||||
|
action.getId() + cacheKeyPartSeparator;
|
||||||
for(String key : actions) {
|
for(String key : actions) {
|
||||||
if(key.startsWith(match)) {
|
if(key.startsWith(match)) {
|
||||||
details.add( buildExecutionSummary(key) );
|
details.add( buildExecutionSummary(key) );
|
||||||
@@ -303,8 +307,9 @@ public class ActionTrackingServiceImpl implements ActionTrackingService
|
|||||||
public List<ExecutionSummary> getExecutingActions(String type) {
|
public List<ExecutionSummary> getExecutingActions(String type) {
|
||||||
Collection<String> actions = executingActionsCache.getKeys();
|
Collection<String> actions = executingActionsCache.getKeys();
|
||||||
List<ExecutionSummary> details = new ArrayList<ExecutionSummary>();
|
List<ExecutionSummary> details = new ArrayList<ExecutionSummary>();
|
||||||
|
String match = type + cacheKeyPartSeparator;
|
||||||
for(String key : actions) {
|
for(String key : actions) {
|
||||||
if(key.startsWith(type)) {
|
if(key.startsWith(match)) {
|
||||||
details.add( buildExecutionSummary(key) );
|
details.add( buildExecutionSummary(key) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -327,16 +332,16 @@ public class ActionTrackingServiceImpl implements ActionTrackingService
|
|||||||
protected static String generateCacheKey(Action action)
|
protected static String generateCacheKey(Action action)
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
action.getActionDefinitionName() + "=" +
|
action.getActionDefinitionName() + cacheKeyPartSeparator +
|
||||||
action.getId() + "=" +
|
action.getId() + cacheKeyPartSeparator +
|
||||||
"1"//action.getExecutionInstance // TODO
|
"1"//action.getExecutionInstance // TODO
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
protected static String generateCacheKey(ExecutionSummary summary)
|
protected static String generateCacheKey(ExecutionSummary summary)
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
summary.getActionType() + "=" +
|
summary.getActionType() + cacheKeyPartSeparator +
|
||||||
summary.getActionId() + "=" +
|
summary.getActionId() + cacheKeyPartSeparator +
|
||||||
summary.getExecutionInstance()
|
summary.getExecutionInstance()
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
@@ -364,7 +369,7 @@ public class ActionTrackingServiceImpl implements ActionTrackingService
|
|||||||
*/
|
*/
|
||||||
protected static ExecutionSummary buildExecutionSummary(String key)
|
protected static ExecutionSummary buildExecutionSummary(String key)
|
||||||
{
|
{
|
||||||
StringTokenizer st = new StringTokenizer(key, "=");
|
StringTokenizer st = new StringTokenizer(key, new String(new char[]{cacheKeyPartSeparator}));
|
||||||
String actionType = st.nextToken();
|
String actionType = st.nextToken();
|
||||||
String actionId = st.nextToken();
|
String actionId = st.nextToken();
|
||||||
int executionInstance = Integer.parseInt(st.nextToken());
|
int executionInstance = Integer.parseInt(st.nextToken());
|
||||||
|
@@ -27,6 +27,7 @@ import javax.transaction.UserTransaction;
|
|||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.action.ActionServiceImplTest.CancellableSleepAction;
|
||||||
import org.alfresco.repo.action.ActionServiceImplTest.SleepActionExecuter;
|
import org.alfresco.repo.action.ActionServiceImplTest.SleepActionExecuter;
|
||||||
import org.alfresco.repo.action.executer.MoveActionExecuter;
|
import org.alfresco.repo.action.executer.MoveActionExecuter;
|
||||||
import org.alfresco.repo.cache.EhCacheAdapter;
|
import org.alfresco.repo.cache.EhCacheAdapter;
|
||||||
@@ -69,12 +70,10 @@ public class ActionTrackingServiceImplTest extends TestCase
|
|||||||
private TransactionService transactionService;
|
private TransactionService transactionService;
|
||||||
private RuntimeActionService runtimeActionService;
|
private RuntimeActionService runtimeActionService;
|
||||||
private ActionTrackingService actionTrackingService;
|
private ActionTrackingService actionTrackingService;
|
||||||
private RetryingTransactionHelper transactionHelper;
|
|
||||||
private EhCacheAdapter<String, ExecutionDetails> executingActionsCache;
|
private EhCacheAdapter<String, ExecutionDetails> executingActionsCache;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
this.transactionHelper = (RetryingTransactionHelper)ctx.getBean("retryingTransactionHelper");
|
|
||||||
this.nodeService = (NodeService)ctx.getBean("nodeService");
|
this.nodeService = (NodeService)ctx.getBean("nodeService");
|
||||||
this.actionService = (ActionService)ctx.getBean("actionService");
|
this.actionService = (ActionService)ctx.getBean("actionService");
|
||||||
this.runtimeActionService = (RuntimeActionService)ctx.getBean("actionService");
|
this.runtimeActionService = (RuntimeActionService)ctx.getBean("actionService");
|
||||||
@@ -109,6 +108,11 @@ public class ActionTrackingServiceImplTest extends TestCase
|
|||||||
|
|
||||||
txn.commit();
|
txn.commit();
|
||||||
|
|
||||||
|
// Cache should start empty each time
|
||||||
|
for(String key : executingActionsCache.getKeys()) {
|
||||||
|
executingActionsCache.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
// Register the test executor, if needed
|
// Register the test executor, if needed
|
||||||
SleepActionExecuter.registerIfNeeded(ctx);
|
SleepActionExecuter.registerIfNeeded(ctx);
|
||||||
}
|
}
|
||||||
@@ -336,10 +340,203 @@ public class ActionTrackingServiceImplTest extends TestCase
|
|||||||
/** Ensure that the listing functions work */
|
/** Ensure that the listing functions work */
|
||||||
public void testListings() throws Exception
|
public void testListings() throws Exception
|
||||||
{
|
{
|
||||||
// TODO
|
// All listings start blank
|
||||||
|
assertEquals(
|
||||||
|
0, actionTrackingService.getAllExecutingActions().size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
0, actionTrackingService.getExecutingActions("test").size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
0, actionTrackingService.getExecutingActions(SleepActionExecuter.NAME).size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
0, actionTrackingService.getExecutingActions(createWorkingSleepAction(null)).size()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create some actions
|
||||||
|
Action sleepAction1 = createWorkingSleepAction("12345");
|
||||||
|
Action sleepAction2 = createWorkingSleepAction("54321");
|
||||||
|
Action moveAction = createFailingMoveAction();
|
||||||
|
|
||||||
|
// Start putting them in
|
||||||
|
actionTrackingService.recordActionExecuting(sleepAction1);
|
||||||
|
assertEquals(
|
||||||
|
1, actionTrackingService.getAllExecutingActions().size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
0, actionTrackingService.getExecutingActions("test").size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
1, actionTrackingService.getExecutingActions(SleepActionExecuter.NAME).size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
1, actionTrackingService.getExecutingActions(sleepAction1).size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
0, actionTrackingService.getExecutingActions(sleepAction2).size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
0, actionTrackingService.getExecutingActions(moveAction).size()
|
||||||
|
);
|
||||||
|
|
||||||
|
actionTrackingService.recordActionExecuting(moveAction);
|
||||||
|
assertEquals(
|
||||||
|
2, actionTrackingService.getAllExecutingActions().size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
0, actionTrackingService.getExecutingActions("test").size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
1, actionTrackingService.getExecutingActions(SleepActionExecuter.NAME).size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
1, actionTrackingService.getExecutingActions(sleepAction1).size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
0, actionTrackingService.getExecutingActions(sleepAction2).size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
1, actionTrackingService.getExecutingActions(moveAction).size()
|
||||||
|
);
|
||||||
|
|
||||||
|
actionTrackingService.recordActionExecuting(sleepAction2);
|
||||||
|
assertEquals(
|
||||||
|
3, actionTrackingService.getAllExecutingActions().size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
0, actionTrackingService.getExecutingActions("test").size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
2, actionTrackingService.getExecutingActions(SleepActionExecuter.NAME).size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
1, actionTrackingService.getExecutingActions(sleepAction1).size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
1, actionTrackingService.getExecutingActions(sleepAction2).size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
1, actionTrackingService.getExecutingActions(moveAction).size()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Now have some finish, should leave the cache
|
||||||
|
actionTrackingService.recordActionComplete(sleepAction2);
|
||||||
|
assertEquals(
|
||||||
|
2, actionTrackingService.getAllExecutingActions().size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
0, actionTrackingService.getExecutingActions("test").size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
1, actionTrackingService.getExecutingActions(SleepActionExecuter.NAME).size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
1, actionTrackingService.getExecutingActions(sleepAction1).size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
0, actionTrackingService.getExecutingActions(sleepAction2).size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
1, actionTrackingService.getExecutingActions(moveAction).size()
|
||||||
|
);
|
||||||
|
|
||||||
|
actionTrackingService.recordActionComplete(sleepAction1);
|
||||||
|
assertEquals(
|
||||||
|
1, actionTrackingService.getAllExecutingActions().size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
0, actionTrackingService.getExecutingActions("test").size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
0, actionTrackingService.getExecutingActions(SleepActionExecuter.NAME).size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
0, actionTrackingService.getExecutingActions(sleepAction1).size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
0, actionTrackingService.getExecutingActions(sleepAction2).size()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
1, actionTrackingService.getExecutingActions(moveAction).size()
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO Multiple actions of the same instance
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Cancel related
|
/** Cancel related */
|
||||||
|
public void testCancellation() throws Exception {
|
||||||
|
// Ensure we get the right answers checking
|
||||||
|
CancellableSleepAction sleepAction1 = (CancellableSleepAction)createWorkingSleepAction(null);
|
||||||
|
CancellableSleepAction sleepAction2 = (CancellableSleepAction)createWorkingSleepAction(null);
|
||||||
|
actionTrackingService.recordActionExecuting(sleepAction1);
|
||||||
|
actionTrackingService.recordActionExecuting(sleepAction2);
|
||||||
|
assertEquals(false, actionTrackingService.isCancellationRequested(sleepAction1));
|
||||||
|
assertEquals(false, actionTrackingService.isCancellationRequested(sleepAction2));
|
||||||
|
|
||||||
|
// Cancel with the action
|
||||||
|
actionTrackingService.requestActionCancellation(sleepAction1);
|
||||||
|
assertEquals(true, actionTrackingService.isCancellationRequested(sleepAction1));
|
||||||
|
assertEquals(false, actionTrackingService.isCancellationRequested(sleepAction2));
|
||||||
|
|
||||||
|
// Cancel with the summary
|
||||||
|
ExecutionSummary s2 = ActionTrackingServiceImpl.buildExecutionSummary(sleepAction2);
|
||||||
|
actionTrackingService.requestActionCancellation(s2);
|
||||||
|
assertEquals(true, actionTrackingService.isCancellationRequested(sleepAction1));
|
||||||
|
assertEquals(true, actionTrackingService.isCancellationRequested(sleepAction2));
|
||||||
|
|
||||||
|
|
||||||
|
// If the action had gone missing from the cache,
|
||||||
|
// then a check will put it back
|
||||||
|
CancellableSleepAction sleepAction3 = (CancellableSleepAction)createWorkingSleepAction(null);
|
||||||
|
String key3 = ActionTrackingServiceImpl.generateCacheKey(sleepAction3);
|
||||||
|
|
||||||
|
assertNull(executingActionsCache.get(key3));
|
||||||
|
assertEquals(false, actionTrackingService.isCancellationRequested(sleepAction3));
|
||||||
|
assertNotNull(executingActionsCache.get(key3));
|
||||||
|
|
||||||
|
executingActionsCache.remove(key3);
|
||||||
|
assertNull(executingActionsCache.get(key3));
|
||||||
|
assertEquals(false, actionTrackingService.isCancellationRequested(sleepAction3));
|
||||||
|
assertNotNull(executingActionsCache.get(key3));
|
||||||
|
|
||||||
|
actionTrackingService.requestActionCancellation(sleepAction3);
|
||||||
|
assertEquals(true, actionTrackingService.isCancellationRequested(sleepAction3));
|
||||||
|
assertNotNull(executingActionsCache.get(key3));
|
||||||
|
|
||||||
|
|
||||||
|
// Now have one execute and cancel it, ensure it does
|
||||||
|
final SleepActionExecuter sleepActionExec =
|
||||||
|
(SleepActionExecuter)ctx.getBean(SleepActionExecuter.NAME);
|
||||||
|
sleepActionExec.setSleepMs(10000);
|
||||||
|
|
||||||
|
UserTransaction txn = transactionService.getUserTransaction();
|
||||||
|
txn.begin();
|
||||||
|
|
||||||
|
executingActionsCache.remove(key3);
|
||||||
|
this.actionService.executeAction(sleepAction3, this.nodeRef, false, true);
|
||||||
|
|
||||||
|
// End the transaction. Should allow the async action
|
||||||
|
// to be started
|
||||||
|
txn.commit();
|
||||||
|
Thread.sleep(150);
|
||||||
|
|
||||||
|
assertEquals(false, actionTrackingService.isCancellationRequested(sleepAction3));
|
||||||
|
assertNotNull(executingActionsCache.get(key3));
|
||||||
|
|
||||||
|
actionTrackingService.requestActionCancellation(sleepAction3);
|
||||||
|
|
||||||
|
assertEquals(true, actionTrackingService.isCancellationRequested(sleepAction3));
|
||||||
|
assertNotNull(executingActionsCache.get(key3));
|
||||||
|
|
||||||
|
// Have it finish sleeping, will have been cancelled
|
||||||
|
sleepActionExec.getExecutingThread().interrupt();
|
||||||
|
Thread.sleep(100);
|
||||||
|
|
||||||
|
// TODO Proper cancelled exception and tracking
|
||||||
|
assertEquals(ActionStatus.Failed, sleepAction3.getExecutionStatus());
|
||||||
|
assertEquals("Cancelled!", sleepAction3.getExecutionFailureMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// =================================================================== //
|
// =================================================================== //
|
||||||
@@ -673,5 +870,4 @@ public class ActionTrackingServiceImplTest extends TestCase
|
|||||||
private Action createWorkingSleepAction(String id) throws Exception {
|
private Action createWorkingSleepAction(String id) throws Exception {
|
||||||
return ActionServiceImplTest.createWorkingSleepAction(id, actionService);
|
return ActionServiceImplTest.createWorkingSleepAction(id, actionService);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Reference in New Issue
Block a user