Error handling

Dec 29, 2010 at 5:28 PM

How does one handles errors ?

I need to know what failed in my workflow. I need to be able to return an object describing the error, possibly and exception also without breaking everything.

I want to have a list of errors after the workflow completes.

 

Is that possible ?

Coordinator
Dec 30, 2010 at 7:15 PM

The framework doesn't collate exceptions for you.  The current behaviour is that the workflow engine sets the SuccessResult property to False for objects that inherit from the generic BasicOperation class.  There is no equivalent for lamda functions.

 

Therefore, unfortunately, the answer is that you will have to provide your own mechanism.  One way would be to include an Exception list in the data type of the workflow and each Operation class or lamda function should catch it's exceptions and add them to this list. You could then examine this collection in subsequent operations or at the end of the workflow.

 

I have recently begun thinking about how best to allow developers to work with exceptions but have deferred this until I have a solid requirement.  Any suggestions you have would be appreciated.

Coordinator
Mar 9, 2011 at 8:55 PM
Edited Mar 9, 2011 at 8:56 PM

The latest beta allows the client to specify whether to rethrow exceptions.  This is done when creating the workflow configuration obejct.  For example,

Workflow.Definiton(Exception.Rethrow).Do(//do somthing);

This will rethrow exceptions.  
These can be caught in your operations and aggregated or you can put an exception block around the start method.
Editor
Mar 9, 2011 at 8:59 PM

I like that, I saw in the code where it was swallowing exceptions, only setting an internal flag indicating an error occurred. Rethrow is a fair solution to the problem and will certainly do for now. 

Coordinator
Mar 9, 2011 at 10:33 PM
Edited Mar 9, 2011 at 10:39 PM

One thing to bear in mind is that if you configure the workflow to rethrow exceptions you can then only use retry to retry failed operations rather than exceptions.  So, you would need to catch all exceptions and set the operation success flag if it can recovered from by a Retry.

Retry is a policy for exceptions and failures.  Therefore, setting it to rethrow can be seen as overriding any policy on the operation.

I am considering a different syntax for the future;

Do<Operation>().On.Failure.Retry();

Do<Operation>().On.Exception.Retry();

Do<Operation>().On.FailureOrException.Retry();

and then either;

Do<Operation>().Ignore.Exceptions;

or

Do<Operation>().On.Exceptions.Continue;

This allows the policy for exceptions to be set for each operation rather than the workflow.

Mar 9, 2011 at 10:45 PM

I think this should be perfect. :)

Is it possible to do

Do<Operation>().On.FailureOrException.Do<AnotherOperation>() ?

Editor
Mar 9, 2011 at 10:49 PM

Yes. Adding an exception handler operation is a great idea. Also ban the idea of simply doing

Do<Operation>().On.Exception.Retry();

This would almost certainly lead to infinite loops. One option might be allow it to retry x number of times:

Do<Operation>().On.Exception.Retry(3);

Coordinator
Mar 10, 2011 at 12:15 AM

Retry() without specifying attempts defaults to once.  The syntax is below;

Retry(); // defaults to once

Retry().Once;

Retry().Twice;

Retry().Attempts(int);

Coordinator
Mar 10, 2011 at 12:17 AM
Edited Mar 10, 2011 at 12:18 AM

Do<Operation>().On.FailureOrException.Do<AnotherOperation>() seems worth thinking about.

Editor
Mar 10, 2011 at 12:19 AM

Oh, if it defaults to once, I suppose my point is moot

Editor
Mar 14, 2011 at 4:13 PM

This is another feature that I can't wait on, so I'm implementing it immediately. I'm creating an IFaultHandler interface and a default implementation that captures errors in Dispatcher and can be retrieved from an IWorkflow instance. This isn't immediately fluent, but can easily be wrapped into a fluent interface.

Mar 14, 2011 at 4:23 PM

Regarding IfaultHandler,

 

When I see IFaultHandler, it makes me thinking WCF faults.

I would name it IErrorHandler or better IWorklowErrorHandler

Editor
Mar 14, 2011 at 7:12 PM

@rolek - I agree, the word "fault" give you that same spine shiver that you get when dealing with SOAP & WCF.

I didn't see your message until now, so I just checked in some code using IFaultHandler. I'm checking it again soon with IErrorHandler. I don't think I have write access to Subversion, so this is going to Github (https://github.com/tkellogg/objectflow)

Coordinator
Apr 8, 2011 at 1:34 PM
Edited Apr 8, 2011 at 1:35 PM

Workflows should handle exceptions through policies.  

For example, the only workflow exception handling policy I have included is a Retry policy.  The only other pattern I intended to implement is a delegate as in the example;

workflow.Do<operation>().On.Exception(delegate);

This would allow exceptions to be collated.

I have also added an abstract class that could be extended to handle exceptions.

I think anything else would be over complicating the solution.

If there is a specific requirement for something more complicated I would be interested in looking at the requirement rather than the solution.

Coordinator
Sep 5, 2012 at 8:55 PM
Edited Sep 5, 2012 at 10:28 PM

I've added exception handling into the latest release (1.4.x).  This allows you to specify exception handling policies as below;

var workflow = new Workflow(); 
workflow.Configure() 
	.On<NotImplementedException>(()=> MyNotImpExceptionHandler) 
	.On<Exception>(()=>MyExceptionHandler) 
	.When().Do(...)

The When<T>() method closes the definition of exception handlers and you can then define the workflow as usual.  The T in the when clause should match the type of workflow defined.  In this case, string.

 

 

Mar 5, 2013 at 1:03 AM
Hi, is there a more complete example of the last post, of what the MyExceptionHandler actually is?
Coordinator
Mar 5, 2013 at 3:51 PM
I have discussed the exception handling in a blog post;

www.garfieldmoore.co.uk

There is also a demo in the project. The exception handler is an action so can be defined as a method or lamda.

So the following workflow definition calls the private void method when an Exception is thrown;
 public class CoffeeCustomerService : AsAWorkflow<CustomerState>
    {
        public override IWorkflow<CustomerState> Configure()
        {
            return Workflow<CustomerState>.Definition()
                .Configure()
                .On<Exception>(ExceptionHandlerCode)
                .When<CustomerState>()
                .Do<PlaceOrder>()
                .Do<PayForCoffee>()
                .Do<PickUp>();
        }

        private void ExceptionHandlerCode()
        {
            throw new NotImplementedException();
        }
    }
Coordinator
Mar 6, 2013 at 9:44 AM
I've added to the documentation here; http://objectflow.codeplex.com/wikipage?title=Exceptions
Mar 25, 2013 at 2:34 PM
Edited Mar 25, 2013 at 3:58 PM
Some ideas I really miss at that time:
  • Exception handling should pass the exception to the handler and the context.
  • On<Exception> would catch any Exception and derived exception. (like a catch would behave)
Coordinator
Apr 16, 2013 at 8:34 PM
I have been thinking about including a way to catch any exceptions. This will probably make it into the next release.

Thanks for the feedback.