#BetaBlogs 18.4 - Global Exception Handler

betafollowup
18_4

#24

Hi @andrzej.kniola & Welcome back! :slight_smile: The goal was to introduce a global retry and error handling mechanism, especially for unexpected scenarios. This would improve the amount of error handling logic you’d need to add for each of the possible failing activities in a workflow, if a global handler would not exist. Starting from the challenges you described, how would you improve the current global handler implementation?


#25

When I said " Or in essence - what problem is this trying to solve?" maybe I wasn’t clear.
What I meant is “how does this make my life as a developer easier”.
Your answer boils down to “you can write less error handling now”. Ok, how?
To handle the exception, I still need to know why it happened, in what context it happened, what I need to do to “go back” to a system state where I can safely retry and how to run the part that previously failed with the now “fixed” state of the system.
Being able to write it in a separate workflow, that is devoid of any logical connection to the workflow it handles the exception for, doesn’t make it in my eyes any easier, it makes it harder. Doubley so since that workflow will fire for every single exception in the whole project, so as @octechnologist asked (that’s still unanswered) - are we expected to litter it with ton of conditionals?
If no, how could it decide how to handle that particular exception?
If yes, how does it make it better to write it in GEH instead of where the exception occurs (with one of the standard approaches - workflow handles its own errors, or the calling workflow handles it since it knows the context of the call).

To be able to retry a singular activity, it has to be completely atomic (like the GetAsset). Even then, depending on why it failed, there might be no point in retrying (missing asset won’t suddenly appear just because we tried 3 times).
Looking through the activities, I don’t see many for which I would see a point in retrying atomically.
All UI interactions have little chance in succeeding the second time (unless you use that instead of ensuring correct application state [i.e. WaitForReady, OnElementAppear etc.], which is just wrong design).
FileSystem operations in today’s age are robust to a point that there’s very little reason for them to fail in the first place (unless you have the file locked by previous operation, which is again wrong design).
Remote operations (web requests, but also operating on network drives) - maybe, depending on what they do exactly. I’d rather have a built-in retry for those though (same like with GetAsset), maybe via Proxy or Facade or similar patterns.
Office (Excel, Outlook etc.) operations use Interop or similar approaches. Don’t see that just retrying would help there.

The example posted (typing and saving notepad) is so basic that it makes it almost unrealistic and if that’s the case, I’d just stick with TryCatch as it gives the exact same effect and I can control better what’s happening.

There’s also a bigger issue I see when using a GEH approach - I don’t know how the code will execute by looking at it and that, in my book, is a firm “thanks, but no thanks”. Code being not clear enough is the (or at least one of) top time wasters in testing/debugging/changing.
As the saying goes “There’s code so simple, that there is obviously no errors, and then there is code so complicated that there are no obvious errors”. I’ll take some duplication over losing readibility any day.

So what does this help with and how?
How, precisely, does this make development (including testing) and maintenance easier?
Or to give the same one-liner that usually pops up in Ideas section - what’s the use case?

PS. To be clear - I don’t want to just bash the idea, even though I think it’s a mistake to introduce GEH (while simultaneously rejecting globals for configuration because “globals are bad”?).

  • Add an option in its configuration to ignore the same error bubbling up. I dont want to run the sequence/flowchart from the beginning because something inside failed, because the state of the system is not stable at that point, OR add configuration options to ignore certain activity types always (i.e. let it pass through/bubble up without interference from GEH) - i.e. Sequence, Loops, Flowchart, State, InvokeWorkflow (ESPECIALLY this one, since even on exception the double-reference hoop may have already altered the arguments values/state).
  • Add an option to always .Continue (i.e. omit the global handling, maybe outside of logging?) on certain exception types. I.e. I’d want to be able to specify that OOM, EngineFault, System.Exception, “asset doesn’t exist” (whichever that was) etc. do NOT trigger global handlers logic, without cluttering the handler itself.
  • Provide usage guidelines, not only how to add one. I.e. Should it be configured with whitelist or blacklist approach, when to add one and when to not add one (no pattern is universal, if you can’t say when it will be a bad idea you don’t understand it’s limitations [not you specifically, this is true for all patterns usage]) etc.
  • Provide clear explanation of what happens if an activity in the GEH throws an exception itself, or if a workflow invoked from GEH throws an exception (this is going down the rabbit hole, but with that “random popup” thing you’d probably not want handling directly in GEH, right? SingleResponsibility and all that)

The hardest part about “how would you make it better” leads me to suggestions that make it not Global anymore, as I don’t see how that helps :frowning: