You are viewing limited content. For full access, please sign in.

Question

Question

How resource intensive is the Try Catch activity?

asked on April 4, 2022 Show version history

Hello,
We have an open support ticket with Laserfiche for a SQL error we have been having for a few months now. As a fix to the problem we have been placing query, custom query, insert and update activities within the Try Catch activity. 

Many times adding in a token that gets modified by each branch of the Try Catch easily fixes the problem. Other scenarios where there is a For Each Row tied to the query can lead to a much more complex fix. 

The concern came up that Try Catch might add overhead to the workflow server. That begged the question of how resource intensive is the Try Catch activity? I am starting to believe it is best practice to prevent data query connection/communication errors from terminating workflows.

Can anyone add to that idea? Thoughts?

 

Thank You

0 0

Answer

SELECTED ANSWER
replied on April 5, 2022

In that case it would depend on what happens within the For Each Row activity, and the consequences of a failure.

If the For Each Row is just doing repository stuff, the initial query is the only db activity, and a retry wouldn't break anything then I would wrap the whole thing in one big try-catch.

If the For Each Row performs another database activity, then it would depend on whether that is an insert or an update since a retry has different implications.

For inserts, I would put the try-catch inside of the loop iteration so it catches the insert error but doesn't break the entire loop.

For updates, running the same update twice usually won't hurt anything so I would just keep one big try-catch.

However, it also depends on how you want to handle any errors.

If you want it to keep going to the next row, then you'd need a try-catch inside the loop so one error on insert/update doesn't break the loop.

Also, it depends on how critical it is that these activities complete successfully, and how they're being triggered.

For example, if they're triggered by Forms, Forms is set to wait for the workflow, and the workflow terminates, then that would suspend the Forms instance so retrying would run the workflow again.

If there's no easy way to retrigger the workflow and you want the best chance of success, I usually create a boolean token like "Update Complete" set to false by default.

Then, I put the db activity inside of a repeat loop and set the token to true right after the db activity.

That way, if it completes successfully the token is updated and the loop ends, but if it triggers the try-catch and never reaches the token update, it will trigger the repeat and try again automatically (in this case I usually put at least a 1-min delay in the catch branch).

If you have the try-catch inside of the for each row on a loop, then make sure you're resetting the "complete" token to false at the beginning of the row loop so the success of the previous iteration doesn't affect the next one.

I usually do something like this, but again it really depends on the context.

1 0

Replies

replied on April 4, 2022

I use try-catch activities quite frequently and I can't imagine they would add any overhead since really the error gets caught either way and the try-catch just tells workflow not to terminate the instance.

Personally, I almost never use db activities in a workflow without a try-catch since a lot of unexpected things can happen when interacting with an external database, like deadlocks, timeouts, etc.

2 0
replied on April 5, 2022

Thanks Jason. Just curious how you handle when you have to use the For Each Row activity AND the Try Catch together. I have been able to just have duplicate branches, but sometimes that doesn't make sense to do it that way.  

0 0
SELECTED ANSWER
replied on April 5, 2022

In that case it would depend on what happens within the For Each Row activity, and the consequences of a failure.

If the For Each Row is just doing repository stuff, the initial query is the only db activity, and a retry wouldn't break anything then I would wrap the whole thing in one big try-catch.

If the For Each Row performs another database activity, then it would depend on whether that is an insert or an update since a retry has different implications.

For inserts, I would put the try-catch inside of the loop iteration so it catches the insert error but doesn't break the entire loop.

For updates, running the same update twice usually won't hurt anything so I would just keep one big try-catch.

However, it also depends on how you want to handle any errors.

If you want it to keep going to the next row, then you'd need a try-catch inside the loop so one error on insert/update doesn't break the loop.

Also, it depends on how critical it is that these activities complete successfully, and how they're being triggered.

For example, if they're triggered by Forms, Forms is set to wait for the workflow, and the workflow terminates, then that would suspend the Forms instance so retrying would run the workflow again.

If there's no easy way to retrigger the workflow and you want the best chance of success, I usually create a boolean token like "Update Complete" set to false by default.

Then, I put the db activity inside of a repeat loop and set the token to true right after the db activity.

That way, if it completes successfully the token is updated and the loop ends, but if it triggers the try-catch and never reaches the token update, it will trigger the repeat and try again automatically (in this case I usually put at least a 1-min delay in the catch branch).

If you have the try-catch inside of the for each row on a loop, then make sure you're resetting the "complete" token to false at the beginning of the row loop so the success of the previous iteration doesn't affect the next one.

I usually do something like this, but again it really depends on the context.

1 0
replied on April 5, 2022

This is super helpful thank you so much. If there are ever in person Empower conferences again, I owe you an adult beverage :)

one more question I have been mulling around. Ever think about using a token calculator to set a token to "20 seconds into the future" and then use that token in the delay activity so rather than waiting one minute, it just references the token?



Not sure if that activity can even handle seconds, but am close to testing it. 

0 0
replied on April 5, 2022 Show version history

I've tested it before, and unfortunately it won't work that way.

Under the hood, Workflow relies on Microsoft's task scheduler and similar OS services, and those only really work with minute intervals.

Microsoft's OS timing mechanisms tend to work off whole minute markers too rather than precise time differences (i.e., 12:01-12:02 not 12:01:30-12:02:30).

One indicator of this is that when you look at the activity history of workflows, even a 1-min delay is almost never exactly 1 minute.

It's an interesting topic. Back in the Windows Phone days there was a lot of difficultly around building a precise timer app because of similar behavior.

0 0
replied on April 5, 2022

Ah rats. Thanks for saving me the time with testing that theory out!

0 0
replied on April 5, 2022

This has long annoyed me, given that timing circuits going back the 70s have very high precision and accuracy. You'd think MS could expose something a little better by this point.

0 0
replied on April 5, 2022

Yea, it's really odd. Task scheduler does have an option for a delay that currently includes 30 seconds as an option.

However, it says "Delay task for up to (random delay)" so a 30-second delay could be anywhere between 1 and 30 seconds, and that's after the trigger.

 

But, realistically, it's not often that I find myself in a position where a "seconds" timer is really all that important, or can't be alleviated with a different approach.

In the case of a try-catch delay on a db activity, if something goes wrong, I usually want to give it at least a full minute before I try again anyway because those kinds of errors usually come from outages, too much activity, etc., and hitting it repeatedly can just make things worse.

1 0
replied on April 5, 2022

True. My main need for super fast timers when testing but in production, a minute or few isn't really an issue.

1 0
replied on April 8, 2022 Show version history

So we started using your technique in hardening our data activities, @████████.

 

I just came across a scenario that surprised me but also makes sense. Looks like the Repeat activity won't allow for the For Each Row like this:

 

If I pull that query out of there it is happy again. I tried re-selecting it as sometimes workflow looses a connection here or there. That didn't do the trick. 

 

I had several of these that were similar when I was implementing the try/catch method. I would have to clone all the activities down both the try and the catch branches. Thinking that may be the way to go with these. Any thoughts?

Thanks so much.

EDIT: after looking at this with a fresh set of eyes, I don't believe the activities need to be cloned. Rather they just get put in the Try branch. If there are additional data query activities, nest the repeat configuration within that Try branch. Sound about right?

 

The idea that the activities could keep repeating does give me some pause and wonder if this is truly the best way. There could be some unwanted behavior if it repeats the same item multiple times. Such as (in the example above) the Update Word Doc, Create Entry or Attach Electronic Doc. 

EDIT2:

I actually am NOT liking the idea of nesting the repeats. For these where a For Each Row feeds off of a query, our best idea is to keep the query in the repeat and put an invoke in with it. send the value per row through the parameters of the invoke. 

0 0
replied on April 11, 2022

Yes that's right. Some tokens become unavailable to other activities when they are inside of a repeat loop because of how they are tracked.

With most you can just assign them to another token, but for things like a database lookup that return multiple rows, you need to put everything inside of the repeat so your for each row can access the data.

1 0
You are not allowed to follow up in this post.

Sign in to reply to this post.