RM Performance Improvements

* general file plan browse rendering in around half the previously recorded times for around 500 records (need to scale up)
 * unessesary bottle neck removed from record detail page rendering (see RM-1461)
 * other general improvements
 * TODO .. hasFrozenChildren, getNextDisposition, TransferNodeIndicator, HeldBy .. all traverse up or down record/record folder hierarchy in ways that don't scale
 * fix to disposition lifecycle job that failed all when one failed .. this explains why the job appeared not to work on occasion



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@74458 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Roy Wetherall
2014-06-23 07:21:51 +00:00
parent 15a00fa939
commit 3e7aa934f7
10 changed files with 79 additions and 72 deletions

View File

@@ -7,8 +7,8 @@
<bean id="capabilityCondition.base" <bean id="capabilityCondition.base"
abstract="true"> abstract="true">
<property name="permissionService" ref="PermissionService" /> <property name="permissionService" ref="permissionService" /> <!-- use lower case service to enhance performance -->
<property name="nodeService" ref="NodeService" /> <property name="nodeService" ref="nodeService" /> <!-- use lower case service to enhance performance -->
<property name="freezeService" ref="FreezeService" /> <property name="freezeService" ref="FreezeService" />
<property name="recordService" ref="RecordService" /> <property name="recordService" ref="RecordService" />
<property name="filePlanService" ref="FilePlanService" /> <property name="filePlanService" ref="FilePlanService" />

View File

@@ -1214,7 +1214,7 @@ public class RecordsManagementAdminServiceImpl implements RecordsManagementAdmin
*/ */
public List<AssociationRef> getCustomReferencesTo(NodeRef node) public List<AssociationRef> getCustomReferencesTo(NodeRef node)
{ {
return nodeService.getSourceAssocs(node, RegexQNamePattern.MATCH_ALL); return nodeService.getSourceAssocs(node, null);
} }
/** /**

View File

@@ -213,10 +213,6 @@ public class RMSecurityCommon implements ApplicationContextAware
return result; return result;
} }
// Get the file plan for the node
NodeRef filePlan = getFilePlanService().getFilePlan(nodeRef);
if (permissionService.hasPermission(nodeRef, RMPermissionModel.READ_RECORDS) == AccessStatus.DENIED) if (permissionService.hasPermission(nodeRef, RMPermissionModel.READ_RECORDS) == AccessStatus.DENIED)
{ {
// log message // log message
@@ -229,7 +225,9 @@ public class RMSecurityCommon implements ApplicationContextAware
return setTransactionCache("checkRmRead", nodeRef, AccessDecisionVoter.ACCESS_DENIED); return setTransactionCache("checkRmRead", nodeRef, AccessDecisionVoter.ACCESS_DENIED);
} }
// Get the file plan for the node
NodeRef filePlan = getFilePlanService().getFilePlan(nodeRef);
if (permissionService.hasPermission(filePlan, RMPermissionModel.VIEW_RECORDS) == AccessStatus.DENIED) if (permissionService.hasPermission(filePlan, RMPermissionModel.VIEW_RECORDS) == AccessStatus.DENIED)
{ {
// log capability details // log capability details

View File

@@ -745,7 +745,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
private NodeRef getNextDispositionActionNodeRef(NodeRef nodeRef) private NodeRef getNextDispositionActionNodeRef(NodeRef nodeRef)
{ {
NodeRef result = null; NodeRef result = null;
List<ChildAssociationRef> assocs = nodeService.getChildAssocs(nodeRef, ASSOC_NEXT_DISPOSITION_ACTION, RegexQNamePattern.MATCH_ALL); List<ChildAssociationRef> assocs = nodeService.getChildAssocs(nodeRef, ASSOC_NEXT_DISPOSITION_ACTION, ASSOC_NEXT_DISPOSITION_ACTION, 1, true);
if (assocs.size() != 0) if (assocs.size() != 0)
{ {
result = assocs.get(0).getChildRef(); result = assocs.get(0).getChildRef();
@@ -838,7 +838,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
NodeRef currentDispositionAction = null; NodeRef currentDispositionAction = null;
if (nodeService.hasAspect(nodeRef, ASPECT_DISPOSITION_LIFECYCLE)) if (nodeService.hasAspect(nodeRef, ASPECT_DISPOSITION_LIFECYCLE))
{ {
List<ChildAssociationRef> assocs = nodeService.getChildAssocs(nodeRef, ASSOC_NEXT_DISPOSITION_ACTION, RegexQNamePattern.MATCH_ALL); List<ChildAssociationRef> assocs = nodeService.getChildAssocs(nodeRef, ASSOC_NEXT_DISPOSITION_ACTION, ASSOC_NEXT_DISPOSITION_ACTION);
if (assocs.size() > 0) if (assocs.size() > 0)
{ {
currentDispositionAction = assocs.get(0).getChildRef(); currentDispositionAction = assocs.get(0).getChildRef();

View File

@@ -186,12 +186,22 @@ public class DispositionLifecycleJobExecuter extends RecordsManagementJobExecute
Map<String, Serializable> props = new HashMap<String, Serializable>(1); Map<String, Serializable> props = new HashMap<String, Serializable>(1);
props.put(RMDispositionActionExecuterAbstractBase.PARAM_NO_ERROR_CHECK, Boolean.FALSE); props.put(RMDispositionActionExecuterAbstractBase.PARAM_NO_ERROR_CHECK, Boolean.FALSE);
// execute disposition action try
recordsManagementActionService.executeRecordsManagementAction(parent.getParentRef(), dispAction, props);
if (logger.isDebugEnabled())
{ {
logger.debug("Processed action: " + dispAction + "on" + parent); // execute disposition action
recordsManagementActionService.executeRecordsManagementAction(parent.getParentRef(), dispAction, props);
if (logger.isDebugEnabled())
{
logger.debug("Processed action: " + dispAction + "on" + parent);
}
}
catch (AlfrescoRuntimeException exception)
{
if (logger.isDebugEnabled())
{
logger.debug(exception);
}
} }
} }
} }

View File

@@ -710,17 +710,6 @@ public class RecordServiceImpl extends BaseBehaviourBean
return result; return result;
} }
/**
* @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#isDeclared(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public boolean isDeclared(NodeRef record)
{
ParameterCheck.mandatory("record", record);
return nodeService.hasAspect(record, ASPECT_DECLARED_RECORD);
}
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#createRecord(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef) * @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#createRecord(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef)
*/ */

View File

@@ -86,7 +86,7 @@ public abstract class ExtendedSecurityBaseDynamicAuthority implements DynamicAut
{ {
if (nodeService == null) if (nodeService == null)
{ {
nodeService = (NodeService)applicationContext.getBean("nodeService"); nodeService = (NodeService)applicationContext.getBean("dbNodeService");
} }
return nodeService; return nodeService;
} }

View File

@@ -52,6 +52,9 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
/** Application context */ /** Application context */
protected ApplicationContext applicationContext; protected ApplicationContext applicationContext;
/** internal node service */
private NodeService internalNodeService;
/** /**
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext) * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
@@ -77,6 +80,21 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
{ {
this.dictionaryService = dictionaryService; this.dictionaryService = dictionaryService;
} }
/**
* Helper to get internal node service.
* <p>
* Used for performance reasons.
*/
private NodeService getInternalNodeService()
{
if (internalNodeService == null)
{
internalNodeService = (NodeService)applicationContext.getBean("dbNodeService");
}
return internalNodeService;
}
/** /**
* Gets the file plan component kind from the given node reference * Gets the file plan component kind from the given node reference
@@ -196,12 +214,8 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
public boolean isFilePlanComponent(NodeRef nodeRef) public boolean isFilePlanComponent(NodeRef nodeRef)
{ {
boolean result = false; boolean result = false;
if (getInternalNodeService().exists(nodeRef) &&
// use the internal node service to prevent redirection of security checking. getInternalNodeService().hasAspect(nodeRef, ASPECT_FILE_PLAN_COMPONENT))
NodeService myNodeService = (NodeService)applicationContext.getBean("nodeService");
if (myNodeService.exists(nodeRef) &&
myNodeService.hasAspect(nodeRef, ASPECT_FILE_PLAN_COMPONENT))
{ {
result = true; result = true;
} }
@@ -264,7 +278,7 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
{ {
ParameterCheck.mandatory("nodeRef", nodeRef); ParameterCheck.mandatory("nodeRef", nodeRef);
return nodeService.hasAspect(nodeRef, ASPECT_RECORD); return getInternalNodeService().hasAspect(nodeRef, ASPECT_RECORD);
} }
/** /**
@@ -280,7 +294,8 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
ParameterCheck.mandatory("nodeRef", nodeRef); ParameterCheck.mandatory("nodeRef", nodeRef);
boolean isHold = false; boolean isHold = false;
if (nodeService.exists(nodeRef) && instanceOf(nodeRef, TYPE_HOLD)) if (getInternalNodeService().exists(nodeRef) &&
instanceOf(nodeRef, TYPE_HOLD))
{ {
isHold = true; isHold = true;
} }
@@ -298,6 +313,18 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
return instanceOf(nodeRef, TYPE_TRANSFER); return instanceOf(nodeRef, TYPE_TRANSFER);
} }
/**
* Indicates whether a record is complete or not.
*
* @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#isDeclared(org.alfresco.service.cmr.repository.NodeRef)
*/
public boolean isDeclared(NodeRef record)
{
ParameterCheck.mandatory("record", record);
return getInternalNodeService().hasAspect(record, ASPECT_DECLARED_RECORD);
}
/** /**
* Gets the file plan that a given file plan component resides within. * Gets the file plan that a given file plan component resides within.
@@ -309,35 +336,23 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
{ {
NodeRef result = null; NodeRef result = null;
if (nodeRef != null) if (nodeRef != null)
{ {
RunAsWork<NodeRef> runAsWork = new RunAsWork<NodeRef>() result = (NodeRef)getInternalNodeService().getProperty(nodeRef, PROP_ROOT_NODEREF);
if (result == null)
{ {
@Override if (instanceOf(nodeRef, TYPE_FILE_PLAN))
public NodeRef doWork()
{ {
NodeRef result = (NodeRef)nodeService.getProperty(nodeRef, PROP_ROOT_NODEREF); result = nodeRef;
if (result == null)
{
if (instanceOf(nodeRef, TYPE_FILE_PLAN))
{
result = nodeRef;
}
else
{
ChildAssociationRef parentAssocRef = nodeService.getPrimaryParent(nodeRef);
if (parentAssocRef != null)
{
result = getFilePlan(parentAssocRef.getParentRef());
}
}
}
return result;
} }
else
}; {
ChildAssociationRef parentAssocRef = getInternalNodeService().getPrimaryParent(nodeRef);
result = AuthenticationUtil.runAsSystem(runAsWork); if (parentAssocRef != null)
{
result = getFilePlan(parentAssocRef.getParentRef());
}
}
}
} }
return result; return result;
@@ -352,15 +367,9 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
protected boolean instanceOf(NodeRef nodeRef, QName ofClassName) protected boolean instanceOf(NodeRef nodeRef, QName ofClassName)
{ {
ParameterCheck.mandatory("nodeRef", nodeRef); ParameterCheck.mandatory("nodeRef", nodeRef);
ParameterCheck.mandatory("ofClassName", ofClassName); ParameterCheck.mandatory("ofClassName", ofClassName);
boolean result = false; QName className = getInternalNodeService().getType(nodeRef);
if (nodeService.exists(nodeRef) && return instanceOf(className, ofClassName);
(ofClassName.equals(nodeService.getType(nodeRef)) ||
dictionaryService.isSubClass(nodeService.getType(nodeRef), ofClassName)))
{
result = true;
}
return result;
} }
/** /**

View File

@@ -275,7 +275,8 @@ public class HoldServiceImplUnitTest extends BaseUnitTest
@Test (expected=AlfrescoRuntimeException.class) @Test (expected=AlfrescoRuntimeException.class)
public void addToHoldNotARecordFolderOrRecord() public void addToHoldNotARecordFolderOrRecord()
{ {
holdService.addToHold(hold, filePlanComponent); NodeRef anotherThing = generateNodeRef(TYPE_RECORD_CATEGORY);
holdService.addToHold(hold, anotherThing);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

@@ -121,7 +121,7 @@ public class BaseUnitTest implements RecordsManagementModel
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
// setup application context // setup application context
doReturn(mockedNodeService).when(mockedApplicationContext).getBean("nodeService"); doReturn(mockedNodeService).when(mockedApplicationContext).getBean("dbNodeService");
// setup retrying transaction helper // setup retrying transaction helper
Answer<Object> doInTransactionAnswer = new Answer<Object>() Answer<Object> doInTransactionAnswer = new Answer<Object>()