On Thu, Mar 31, 2011 at 04:11:24PM +0200, Simone Carletti wrote: > > I'm currently working to implement an error handling feature in a workflow. > I experimented with the :on_error statement and it seems to do its job > pretty well. > http://ruote.rubyforge.org/common_attributes.html#on_error
Hello Simone, > My workflow can crash essentially for three reasons: > > 1. a pre/post-condition is missing (I'll probably open a new thread about > this. let's ignore this case for now). :filter could help here http://ruote.rubyforge.org/common_attributes.html#filter > 2. the person in charge of a workitem is not available (we currently compute > the assignee list internally of a participant) I'd suggest leaving the task in the worklist of the person until he becomes available (he's probably gone for a coffee). > 3. anything else, including (but not limited to) Ruby syntax error, business > errors, etc. > > Case 2 and 3 should have a different handling logic. For instance, in case > of a missing assignee the system should notify the HR team while in case of > a technical error the system should notify the Dev team. Also, the actions > required to solve the issue can vary. > > After reading the documentation I came up with a possible solution but I > haven't been able to make it working. I'd like to know if it is the right > way or is there a better way to accomplish the task. > > Basically, the difference between the case 2 and case 3 is the type of > exception. In case of PositionNotFound error, we're dealing with a case 2. > Otherwise, it's a case 3. Obviously. > My idea was to create two different participant classes and register both > rescuers as "rescue". > > class Case2ErrorRescuer < LocalParticipant > def consume(workitem) > end > def accept?(workitem) > puts "refusing #{workitem.sid}" > workitem.error["class"] == "StandardError" > end > end > class Case3ErrorRescuer < LocalParticipant > def consume(workitem) > end > def accept?(workitem) > puts "refusing #{workitem.sid}" > workitem.error["class"] != "StandardError" > end > end > > $engine.register do > ... > participant /rescuer/, Case2ErrorRescuer > participant /rescuer/, Case3ErrorRescuer > end > $engine.on_error = "rescuer" > > As you can see, I'm using the accept? participant method to refuse a > workitem if the workitem doesn't satisfy the rescuer requirements. > > The first part seems to work correctly. The Case3ErrorRescuer catches the > error, refuses it but then Ruote can't find the second participant. > > Here's a piece of the Ruote log > > 3 20 er * 20110331-yabizage 53c12 0_0_1 > 20110331-yabizage StandardError > 20110331-yabizage kaboom > 20110331-yabizage on_reply.rb:43:in `consume' > (...) OK, IIRC the 'on_error' handling code is different from the regular 'dispatch to participant' code. I will investigate that. https://github.com/jmettraux/ruote/issues/25 > I believe one alternative would be to create a subprocess with a sequence > and append several :if conditions in the subprocess definition to filter > according to the value of the __error__ field, but this solution is quite > complex and not very flexible because limited by the workflow DSL. I'd say "limited to the workflow DSL" and not "limited by the workflow DSL", but it's true. What about a single participant that does all the error handling ? > Is there a better way to accomplish this task? Something similar to the > Rails rescue_from feature. > > http://api.rubyonrails.org/classes/ActiveSupport/Rescuable/ClassMethods.html Matches nicely the "single participant that does all the error handling". OK, I will look at the on_error issue. Many thanks, -- John Mettraux - http://jmettraux.wordpress.com -- you received this message because you are subscribed to the "ruote users" group. to post : send email to [email protected] to unsubscribe : send email to [email protected] more options : http://groups.google.com/group/openwferu-users?hl=en
