cancel
Showing results for 
Search instead for 
Did you mean: 

Update node property during action

schipmolder
Champ on-the-rise
Champ on-the-rise
Hi,

I think this is a transaction thing, but when I update a property of a node during the execution of a long (asynchronous) action the property isn't actually updated until the action has completed. Is there a way to get it to update the property straight away and continue with the rest of the action?

In this case it's a property that contains an integer for a progress counter (0 to 100%). The action can easily take 10 to 15 minutes and the client application periodically calls a web script to retrieve the progress of the action until it's at 100%.
As the property currently isn't actually updated until at the end of the action the progress bar for the user now jumps straight from 0% to 100% when the action completes which is not ideal.

Thanks!
5 REPLIES 5

afaust
Legendary Innovator
Legendary Innovator
Hello,

unfortunately, there is no real support for incremental progress tracking in Repository tier actions - actions are supposed to be (relatively) quick in execution. Also, the transaction tracking of Lucene previously had some inherent issues with long running transactions and would not index them - I don't know how SOLR handles this. But for 10 - 15 minutes you should be fine - as far as I remember, the issue was with transactions that went on for more than an hour.

In order to update a node property immediately, you'd have to use a retrying transaction helper to execute the "setting of progress property" in a nested (requiresNew = true) transaction. But if that property is located on a node you will be updating as part of the action, you'll run into concurrency issues when the action completes. E.g. Alfresco will report a conflict between the changes made in the nested transaction and your overall action transaction. This very likely will mean the action transaction rolls back and is tried again from the start.

If you must set some progress data, I would advise to use the AttributeService instead of a node property to manage the progress data. That way you won't run into update conflicts when using nested transactions. You also reduce pressure on indexing since you don't frequently change a property.

Another option would be to try to split the action apart into logical fragments (multiple actions) and trigger the next fragment as an asynchronous action when the current one completes and commits (including the progress property). Of course this depends on the nature of your action and you might have already considered this - it's just what my initial instinct would be when encountering a long running action…

Regards
Axel

schipmolder
Champ on-the-rise
Champ on-the-rise
Thanks as always Axel!

I'm now trying to set the progress using the retrying transaction helper but for some reason this keeps failing as soon as the property is set and then the transaction is retrying later on.
Do you understand why this code fails?

(ns and actionedUponNodeRef both exist)
<java>
NodeService ns = this.nodeService;
Boolean result = this.transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Boolean>(){
   public Boolean execute() throws Throwable {
      logger.debug("execute");
      QName progressQName = QName.createQName(MyModel.NAMESPACE_MYMODEL_CONTENT_MODEL, "progress");
      logger.debug("setting");
      ns.setProperty(actionedUponNodeRef, progressQName, 10);
      logger.debug("set");
      return true;
   }  
}, false, true);
</java>

This results in:

   [defaultAsyncAction4] execute
   [defaultAsyncAction4] setting


When I comment out the setProperty call the transaction does succeed though and the action continues.

mrogers
Star Contributor
Star Contributor
Yes there will likely be concurrency issues between the transaction that your action is running in and your new transaction.   They are both trying to access the same node.     You may well have a transaction deadlock.

As axel suggests above use the attribute service instead.   I'd use the attribute service myself if the status needs persisting for a long time.

Another option that I'd consider is a non transactional cache item.  That is add a new cache continuing the status of your running actions.

schipmolder
Champ on-the-rise
Champ on-the-rise
Ok, the misunderstanding was that I thought there would only be a conflict if the action actually makes changes to the node which in this case doesn't happen, it only reads data, but I followed your advise and after a bit of rewriting I think the attribute service works fine indeed.

The only thing now is to find out how to make it available in javascript.
I believe i saw an article about how to make services available in js a while ago but can't find it yet.
If you know could you please post a link?

Thanks!

schipmolder
Champ on-the-rise
Champ on-the-rise
Hmm, looks like I spoke too soon as I still have to wait for the action that sets the attributes to complete before another webscript gets the updated value, so the progress still jumps straight from 0 to 100%.
Not sure why it's doing this, maybe because the action is asynchronous or something else, but I'll troubleshoot in more detail tomorrow.