RE Framework MaxRetryNumber and Orchestrator Queue Max # Rertry, again

Hi,

I’m trying to get a clarification of these 2 numbers. My understanding from reading the documentations and crawling on the forum is that:

  • Orchestrator Queue Max # Retry is totally independent of the REFramework config, so regardless of the MaxRetryNumber, if an Orchestrator Queue is being used, the item will be retried to the the Max # Retry of the Queue
  • MaxRetryNumber configuration will only apply to non Orchestrator queue

Reading through the logic of retry in REF, I’m more confident with the above understanding.

But, the topic I quoted below seemed to suggest that BOTH will be considered

https://forum.uipath.com/t/retry-mechanism-in-re-framework/131373/2

i.e. MaxRetryNumber configured the number of local retry, while Max # Retry of the Queue defined the retry internally of Orchestrator Queue. So the total number of retries will be the multiplication of 2 numbers, i.e. if MaxRetryNumber = 3 and Max # Retry of the processing queue = 2, total retry will be 3 * 2 = 6

I don’t think that is correct, but I could be wrong.

From my reading of the Retry flow of REF, in case QueueRetry is true, io_RetryNumber is not increased, io_TransactionNumber is always increased though.

Anyone can clarify this? Thanks so much!

Cheers,

@mrducnguyen Welcome to our UiPath Community. In Config it is clearly mentioned that
MaxRetryNumber => Must be 0 if working with Orchestrator queues. If > 0, the robot will retry the same transaction which failed with a system exception. Must be an integer value.

If you are using Queue then logic will just simply ignore value of Retry Number but if it will go into infinite loop for that item(If transaction will throw System Exception every time)

image
Please have a look on attached 2 workflows for more deeper knowledge. and let me know if you need more info on that
RetryCurrentTransaction.xaml (20.4 KB) SetTransactionStatus.xaml (40.3 KB)

Thanks @Arpit_Kesharwani for your reply. But I don’t think we’ll reach to infinite loop even if we use Orchestrator Queue and configure MaxRetryNumber > 0, since Orchestrator will take care of the Retry.

Reason I asked this question because it’s a question in the Practice test for the Developer Certification :slight_smile:

If using Orchestrator Queue, and MaxRetryNumber > 0, the flow will always flow through the ‘Yes’ branch at decision point “Robot retry?”, and

  1. io_RetryNumber will have been set to the current in_TransactionItem.RetryNo in previous step
  2. It will end up in io_TransactionNumber being increased by 1 in all cases, since:
    • If MaxRetryNumber is reached, it will check for QueueRetry which is true in this case, it will end up with io_TransactionNumber increment by 1
    • if MaxRetryNumber is not reached, it will just reset io_RetryNumber = 0 and increase io_TransactionNumber by 1

The above flow becomes exactly the same behaviour as the ‘No’ branch in which MaxRetryNumber <= 0

In this case the retry would just happen in Orchestrator I believe. (And I’m curious why io_TransactionNumber is increased regardless, but it’s not important for now :slight_smile: )

I think if Orchestrator Queue Retry always takes precedence of MaxRetryNumber on local configuration, the flow can be rearranged a bit so that it highlights the decision point?! Like below

Hi @ClaytonM, can you provide some thoughts? Thanks in advance!

Hi.

Hopefully, I can clarify some things for you, and this still gets me confused sometimes too.

I am working from an optimized REF where both localized retries and queue retries can be used simultaneously to perform a more efficient result. - in that case, yes, the total retries would be (retryNumber + transactionItem.RetryNo) as you pointed out.

However, if I remember right, the REF’s original retry mechanism was intended to use one or the other. So if you want localized retry, set your Queue to use no retries and set MaxRetry > 0. (You can still use the Queue for that reason). Now, keep in mind, that when you use the localized retry, this will attempt to retry on the same machine which it is currently running, therefore, if there is an issue with that machine, it will continue to fail… whereas, the queue retry will (potentially) choose a different machine to perform the transaction — i hope they improve it in the future where it prioritizes a different machine when the transaction fails.

The reason I wanted to use both localized retries and queue retries is just for that reason. I could efficiently make 5 retries, for example, on the same transaction on the same machine. However, if it still fails, I could have that transaction be attempted again on hopefully a different machine. I typically do 5 localized and 3 queue retries.

But, like I said, the REF is supposed to have you manually tell it if it is using the queue retry or not as it can’t tell automatically (from my understanding). Sure, you can look at the transactionItem.RetryNo, but RetryNo will be 0 on the first attempt and you can’t really tell it to use the localized retry when you have the queue use zero retries, etc.

So, essentially, it should use this logic:

  • if MaxRetryNumber = 0, then increment transactionNumber, and use transactionItem.RetryNo in logging if desired
  • Else, if retryNumber > MaxRetryNumber, then reset retryNumber and increment transactionNumber, else increment retryNumber

So, retryNumber is really only incremented when MaxRetryNumber is used, otherwise, it uses the queue’s RetryNo. However, as I mentioned, it will ignore the retryNumber if the queue is used. Bear in mind, that the retry transition in the state machine should also be ignored when the queue retry is used.

TransactionNumber represents the transaction for the job run on each particular machine. The reason this gets incremented when using the queue’s retry is because each queue retry is a different transaction since it can be performed on different robots/machines. Localized retries will not increment this because the transaction is still being performed on the same machine with the same job run. - hopefully, that makes sense.


If you choose to use both localized and queue retries, then you can make some adjustments where you log two different numbers: retryNumber and transactionItem.RetryNo, one being for localized retry and one for queue retry.

image

The logic is mostly similar to the REF’s but some slight changes. Although, I chose to use a Switch to go between “Successful”, “No Retries”, “RetryAttempt”, “MaxRetries”.


Let me know if you would like to clarify further on anything, cause I put a lot of words on this reply :upside_down_face:

2 Likes

Thanks @ClaytonM, I like the flexibility to modify REF logic to fit our needs!

I have dug a bit further, this is the condition to determine whether QueueRetry is true or false of REF as of 16 July 2020, found in the System Error sequence of the SetTransactionStatus flow

in_TransactionItem isNot Nothing AndAlso (in_TransactionItem.GetType is GetType(Uipath.Core.QueueItem))

It’s just simply set QueueRetry to true if the type of TransactionItem is UiPath.Core.QueueItem, in this case, the default behaviour when Orchestrator Queue is leveraged will always be: MaxRetryCount won’t be taken into account regardless of its value, and Max # Retry always takes precedence even if it is 0

Of course, anyone who uses REF can change the Retry Behaviour to suite one’s needs!

Here is a little of what I did with it:

stored the IsQueue condition to a variable to be used in multiple places:
image

stored the queue retry number into a variable to be added to the front of the log message:
image

Then, I have a sequence for No Retries, Retry Attempt, and Max Retries.
image

If MaxRetryNumber is 0, it will go to No Retries. So, basically, you can use this with both Queue and in-code retries simultaneously. Although, there are varying opinions on this.

The IsQueue variable is just used to do the “Set Transaction Status” activity, since that can only be done with queue items.

Regards.

Thanks @ClaytonM for sharing your tweaks!

I assumed you would need to remove the check for QueueRetry in the Retry flow also, did you?

The idea of using both Queue Retry and Localised retry is great!

That is correct. The queue retry is handled by Orchestrator, and the only thing that the code does is formulate the Log message with its queue retry number using ‘IsQueue’ and the RetryNo>0