use of org.alfresco.service.cmr.thumbnail.FailedThumbnailInfo in project alfresco-repository by Alfresco.
the class ThumbnailServiceImpl method getFailedThumbnails.
@Override
public Map<String, FailedThumbnailInfo> getFailedThumbnails(NodeRef sourceNode) {
Map<String, FailedThumbnailInfo> result = Collections.emptyMap();
if (nodeService.hasAspect(sourceNode, ContentModel.ASPECT_FAILED_THUMBNAIL_SOURCE)) {
List<ChildAssociationRef> failedThumbnailChildren = nodeService.getChildAssocs(sourceNode, ContentModel.ASSOC_FAILED_THUMBNAIL, RegexQNamePattern.MATCH_ALL);
result = new HashMap<String, FailedThumbnailInfo>();
for (ChildAssociationRef chAssRef : failedThumbnailChildren) {
final QName failedThumbnailName = chAssRef.getQName();
NodeRef failedThumbnailNode = chAssRef.getChildRef();
Map<QName, Serializable> props = nodeService.getProperties(failedThumbnailNode);
Date failureDateTime = (Date) props.get(ContentModel.PROP_FAILED_THUMBNAIL_TIME);
int failureCount = (Integer) props.get(ContentModel.PROP_FAILURE_COUNT);
final FailedThumbnailInfo failedThumbnailInfo = new FailedThumbnailInfo(failedThumbnailName.getLocalName(), failureDateTime, failureCount, failedThumbnailNode);
result.put(failedThumbnailName.getLocalName(), failedThumbnailInfo);
}
} else {
logger.debug(sourceNode + " does not have " + ContentModel.ASPECT_FAILED_THUMBNAIL_SOURCE + " aspect");
}
return result;
}
use of org.alfresco.service.cmr.thumbnail.FailedThumbnailInfo in project alfresco-repository by Alfresco.
the class ThumbnailServiceImpl method onCreateNode.
public void onCreateNode(ChildAssociationRef childAssoc) {
NodeRef thumbnailNodeRef = childAssoc.getChildRef();
NodeRef sourceNodeRef = childAssoc.getParentRef();
Map<QName, Serializable> props = nodeService.getProperties(thumbnailNodeRef);
if (logger.isDebugEnabled()) {
logger.debug("Thumbnail " + thumbnailNodeRef + " props " + props);
}
String thumbnailName = (String) nodeService.getProperty(thumbnailNodeRef, ContentModel.PROP_NAME);
if (logger.isDebugEnabled()) {
logger.debug("Thumbnail created " + childAssoc + " for sourceNodeRef " + sourceNodeRef + ", thumbnail " + thumbnailName + ", thumbnailNodeRef " + thumbnailNodeRef);
}
// in order to mark the update after the transactions that creates the thumbnail commits.
if (nodeService.exists(thumbnailNodeRef)) {
if (logger.isDebugEnabled()) {
logger.debug("Caching " + childAssoc + " in transaction resources, thumbnail " + thumbnailName);
}
TransactionalResourceHelper.getSet(THUMBNAIL_PARENT_NODES).add(childAssoc);
TransactionSupportUtil.bindListener(this.transactionListener, 0);
// For new version/content the child association contains a temporary thumbnail node, that gets removed later.
// We need to add the original thumbnail node to the TransactionalResourceHelper instead.
QName thumbnailQname = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, thumbnailName);
if (!childAssoc.getQName().equals(thumbnailQname)) {
List<ChildAssociationRef> allAssocList = nodeService.getChildAssocs(childAssoc.getParentRef(), RegexQNamePattern.MATCH_ALL, thumbnailQname);
for (ChildAssociationRef aChildAssoc : allAssocList) {
if (logger.isDebugEnabled()) {
logger.debug("Caching original thumbnail " + aChildAssoc + " in transaction resources, thumbnail " + thumbnailName);
}
TransactionalResourceHelper.getSet(THUMBNAIL_PARENT_NODES).add(aChildAssoc);
}
}
} else {
if (logger.isDebugEnabled()) {
logger.debug("Thumbnail " + thumbnailNodeRef + " does not exist, thumbnail " + thumbnailName);
}
}
// When a thumbnail succeeds, we must delete any existing thumbnail failure nodes
// In fact there should only be zero or one such failedThumbnails
Map<String, FailedThumbnailInfo> failures = getFailedThumbnails(sourceNodeRef);
if (logger.isDebugEnabled()) {
logger.debug("Thumbnail failures " + failures + " for sourceNodeRef " + sourceNodeRef + ", thumbnail " + thumbnailName);
}
FailedThumbnailInfo existingFailedThumbnail = failures.get(thumbnailName);
if (logger.isDebugEnabled()) {
logger.debug("Existing failed thumbnail " + existingFailedThumbnail + ", thumbnail " + thumbnailName);
}
if (existingFailedThumbnail != null) {
if (logger.isDebugEnabled()) {
StringBuilder msg = new StringBuilder();
msg.append("Deleting failedThumbnail node ").append(existingFailedThumbnail.getFailedThumbnailNode());
logger.debug(msg.toString());
}
nodeService.deleteNode(existingFailedThumbnail.getFailedThumbnailNode());
}
}
use of org.alfresco.service.cmr.thumbnail.FailedThumbnailInfo in project alfresco-repository by Alfresco.
the class ThumbnailServiceImplTest method testCreateFailingThumbnail.
/**
* @since 3.5.0
*/
@Test
public void testCreateFailingThumbnail() throws Exception {
// see REPO-1528
if (shouldTestBeSkippedForCurrentDB()) {
return;
}
logger.debug("Starting testCreateFailingThumbnail");
final NodeRef corruptNode = this.createCorruptedContent(folder);
logger.debug("Running failing thumbnail on " + corruptNode);
// Make sure the source node is correctly set up before we start
// It should not be renditioned and should not be marked as having any failed thumbnails.
assertFalse(secureNodeService.hasAspect(corruptNode, RenditionModel.ASPECT_RENDITIONED));
assertFalse(secureNodeService.hasAspect(corruptNode, ContentModel.ASPECT_FAILED_THUMBNAIL_SOURCE));
TestTransaction.flagForCommit();
TestTransaction.end();
// Attempt to perform a thumbnail that we know will fail.
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>() {
public Void execute() throws Throwable {
ThumbnailDefinition thumbnailDef = thumbnailService.getThumbnailRegistry().getThumbnailDefinition("doclib");
Action createThumbnailAction = ThumbnailHelper.createCreateThumbnailAction(thumbnailDef, services);
actionService.executeAction(createThumbnailAction, corruptNode, true, true);
return null;
}
});
// The thumbnail attempt has now failed. But a compensating action should have been scheduled that will mark the
// source node with a failure aspect. As that is an asynchronous action, we need to wait for that to complete.
// This should be long enough for the compensating action to run.
Thread.sleep(3000);
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>() {
public Void execute() throws Throwable {
assertFalse("corrupt node should not have renditioned aspect", secureNodeService.hasAspect(corruptNode, RenditionModel.ASPECT_RENDITIONED));
assertTrue("corrupt node should have failed thumbnails aspect", secureNodeService.hasAspect(corruptNode, ContentModel.ASPECT_FAILED_THUMBNAIL_SOURCE));
Map<String, FailedThumbnailInfo> failedThumbnails = thumbnailService.getFailedThumbnails(corruptNode);
assertEquals("Wrong number of failed thumbnails", 1, failedThumbnails.size());
assertTrue("Missing QName for failed thumbnail", failedThumbnails.containsKey("doclib"));
final FailedThumbnailInfo doclibFailureInfo = failedThumbnails.get("doclib");
assertNotNull("Failure info was null", doclibFailureInfo);
assertEquals("Failure count was wrong.", 1, doclibFailureInfo.getFailureCount());
assertEquals("thumbnail name was wrong.", "doclib", doclibFailureInfo.getThumbnailDefinitionName());
return null;
}
});
// If you uncomment this line and set the timeout to a value greater than ${system.thumbnail.minimum.retry.period} * 1000.
// Then the retry period will have passed, the below re-thumbnail attempt will be made and the test will fail with a
// failureCount == 2.
//
// Thread.sleep(150 * 1000);
// Run the thumbnail again. It should not run because the action condition should prevent it.
// We can check that it does not run by ensuring the failureCount does not change.
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>() {
public Void execute() throws Throwable {
ThumbnailDefinition thumbnailDef = thumbnailService.getThumbnailRegistry().getThumbnailDefinition("doclib");
Action createThumbnailAction = ThumbnailHelper.createCreateThumbnailAction(thumbnailDef, services);
actionService.executeAction(createThumbnailAction, corruptNode, true, true);
return null;
}
});
// Pause to let the async action be considered for running (but not run).
Thread.sleep(3000);
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>() {
public Void execute() throws Throwable {
Map<String, FailedThumbnailInfo> failedThumbnails = thumbnailService.getFailedThumbnails(corruptNode);
assertEquals("Wrong number of failed thumbnails", 1, failedThumbnails.size());
assertTrue("Missing QName for failed thumbnail", failedThumbnails.containsKey("doclib"));
final FailedThumbnailInfo doclibFailureInfo = failedThumbnails.get("doclib");
assertNotNull("Failure info was null", doclibFailureInfo);
assertEquals("Failure count was wrong.", 1, doclibFailureInfo.getFailureCount());
assertEquals("thumbnail name was wrong.", "doclib", doclibFailureInfo.getThumbnailDefinitionName());
return null;
}
});
}
use of org.alfresco.service.cmr.thumbnail.FailedThumbnailInfo in project alfresco-repository by Alfresco.
the class NodeEligibleForRethumbnailingEvaluator method evaluateImpl.
/**
* @see ActionConditionEvaluatorAbstractBase#evaluateImpl(ActionCondition, NodeRef)
*/
public boolean evaluateImpl(ActionCondition actionCondition, NodeRef actionedUponNodeRef) {
if (!this.nodeService.exists(actionedUponNodeRef)) {
return false;
}
Serializable paramThumbnailDefnName = actionCondition.getParameterValue(PARAM_THUMBNAIL_DEFINITION_NAME);
Serializable paramRetryPeriod = actionCondition.getParameterValue(PARAM_RETRY_PERIOD);
Serializable paramRetryCount = actionCondition.getParameterValue(PARAM_RETRY_COUNT);
Serializable paramQuietPeriod = actionCondition.getParameterValue(PARAM_QUIET_PERIOD);
final Serializable parameterValue = actionCondition.getParameterValue(PARAM_QUIET_PERIOD_RETRIES_ENABLED);
Serializable paramQuietPeriodRetriesEnabled = parameterValue != null ? parameterValue : FailureHandlingOptions.DEFAULT_QUIET_PERIOD_RETRIES_ENABLED;
final QName thumbnailDefnQName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, (String) paramThumbnailDefnName);
// If there are no previous failed thumbnail attempts for this thumbnail definition,
// then the node is always eligible for a first try.
Map<String, FailedThumbnailInfo> failures = thumbnailService.getFailedThumbnails(actionedUponNodeRef);
if (failures.isEmpty() || !failures.containsKey(thumbnailDefnQName.getLocalName())) {
if (logger.isDebugEnabled()) {
StringBuilder msg = new StringBuilder();
msg.append("Node ").append(actionedUponNodeRef).append(" has no matching ").append(ContentModel.ASSOC_FAILED_THUMBNAIL).append(" child.");
logger.debug(msg.toString());
}
return true;
}
final FailedThumbnailInfo failedThumbnailInfo = failures.get(thumbnailDefnQName.getLocalName());
// thumbnail definition at some point.
if (failedThumbnailInfo.getMostRecentFailure() == null) {
// The property should never be null like this, but just in case.
return true;
}
// So how long ago did the given thumbnail definition fail?
long nowMs = new Date().getTime();
long failureTimeMs = failedThumbnailInfo.getMostRecentFailure().getTime();
final long timeSinceLastFailureMs = nowMs - failureTimeMs;
// And how many failures have there been?
final int failureCount = failedThumbnailInfo.getFailureCount();
if (logger.isDebugEnabled()) {
StringBuilder msg = new StringBuilder();
msg.append("Comparing failure time of ").append(failedThumbnailInfo.getMostRecentFailure()).append(" to now. Difference is ").append(timeSinceLastFailureMs).append(" ms. ").append(failureCount).append(" existing failures.");
logger.debug(msg.toString());
}
if (failureCount >= (Integer) paramRetryCount) {
boolean quietPeriodRetriesEnabled = (Boolean) paramQuietPeriodRetriesEnabled;
return quietPeriodRetriesEnabled && timeSinceFailureExceedsLimit(paramQuietPeriod, timeSinceLastFailureMs);
} else {
return timeSinceFailureExceedsLimit(paramRetryPeriod, timeSinceLastFailureMs);
}
}
use of org.alfresco.service.cmr.thumbnail.FailedThumbnailInfo in project alfresco-repository by Alfresco.
the class FailedThumbnailSourceAspect method deleteFailedThumbnailChildren.
/**
* Delete all cm:failedThumbnail children as they represent a failure to thumbnail
* the old content. By deleting all cm:failedThumbnail children, the cm:failedThumbnailSource
* aspect will be automatically removed by a policy/behaviour in the ThumbnailService.
*
* This is necessary so that if a new version of a 'broken' document is uploaded, then
* it will be thumbnailed in the normal way.
*/
private void deleteFailedThumbnailChildren(NodeRef nodeRef) {
Map<String, FailedThumbnailInfo> failedThumbnails = thumbnailService.getFailedThumbnails(nodeRef);
behaviourFilter.disableBehaviour(nodeRef, ContentModel.ASPECT_AUDITABLE);
try {
if (log.isDebugEnabled()) {
log.debug("Deleting " + failedThumbnails.size() + " " + ContentModel.TYPE_FAILED_THUMBNAIL + " nodes");
}
for (Entry<String, FailedThumbnailInfo> entry : failedThumbnails.entrySet()) {
FailedThumbnailInfo info = entry.getValue();
nodeService.deleteNode(info.getFailedThumbnailNode());
}
} finally {
behaviourFilter.enableBehaviour(nodeRef, ContentModel.ASPECT_AUDITABLE);
}
}
Aggregations