-
Notifications
You must be signed in to change notification settings - Fork 40
Error Handling
When some operation execution fails, engine saves error with a backtrace and sets operation to an error status. Operation failure set the whole process to the error status - this is default behavior which can be changed. If the process has some parent operation and belongs to some parent process this way - then parent operation and process are also moved to an error status.
A user can navigate to operation with an error status, check backtrace, and retry operation.
Processes index page also contains a list of unresolved errors in a right sidebar. This way user can track existing errors.
Rails workflow engine allows you to track errors happened during operations build or execution. You can gather all necessary information and retry error after fixing exception cause to continue process's normal flow.
Operation runner can be improved for custom errors handling behavior. For example, an engine can create admin user operations if specific exceptions were raised.
Here I am going to show basic errors handling. We will use 'bad' operation and 'bad' operation template, both raising exceptions:
class BadOperationTemplate < Workflow::OperationTemplate
def build_operation operation
raise 'BUILD_OPERATION'
end
def resolve_dependency operation
raise 'RESOLVE DEPENDENCY'
true
end
end
class BadOperation < Workflow::Operation
def on_complete
raise 'ON_COMPLETE EXCEPTION'
end
def execute
raise 'EXECUTE EXCEPTION'
true
end
end
We need to configure process using this bad operation and bad operation template.
Both operations use same operation class and operation template classes but I need two operations as the first one will be created and running right after process start and a second one will be created after the first operation is completed. This way I will use the second operation to show what happens if dependency resolution raising any exceptions.
The second operation is similar to the first one and the only difference is that it depends on first operation (with state 'Done').
Lets create a new process using this process template. The new process can be created from UI using 'Create Process button. You can see new process screenshot here:
As you can see on screenshot this process's status is 'Error', it has no operation as the first operation build is failed. You can see here raised exception information. Now if we comment out our raise command
class BadOperationTemplate < Workflow::OperationTemplate
def build_operation operation
# raise 'BUILD_OPERATION'
end
...
end
This build_operation method is used to customize operation building. As we have no other code here engine will create new operation using default behavior. Now when I click on error's ‘Retry’ button an engine will try to rebuild this operation. As we commented out exception raise from it – a new operation will be created and added to the process. When the engine will try to complete operation (running it's execute
method) – it will fail again as we have another exception there.
As you can see both operation and process has 'Error' status. This time exception raised in operation execution code so an error is added to the operation.
class BadOperation < Workflow::Operation
...
def execute
# raise 'EXECUTE EXCEPTION'
true
end
end
The operation has an execute
and on_complete
methods. on_complete
method useful for user operations so when user completes some operation – we can add here some custom code. Now if I retry operation error I will have next error:
Now I will comment out the exception from on_complete
method and will retry error. As you can see on next screenshot – the first operation is completed and has 'Done' status. Now process trying to resolve dependencies and create a second operation and fails as we raising exception in operation template's resolve_dependency method:
After commenting it out and retrying error we will see that process's both operation is done and the process is completed with 'Done' status.