Doing a raise while Products.CMFCore.interfaces.IActionSucceededEvent is being executed is going to abort the ZODB transaction for the workflow?
Suppose I have mynamespace.myproduct:
<subscriber for="..interfaces.myinterface.IMyInterface
Products.CMFCore.interfaces.IActionSucceededEvent"
handler=".handlers.actionSucceeded"
/>
and mynamespace.myproduct2:
<subscriber for="..interfaces.myinterface.IMyInterface
Products.CMFCore.interfaces.IActionSucceededEvent"
handler=".handlers.actionSucceeded"
/>
(the handlers do different stuff, on each product, even if they have the same name on this example)
I have a custom type that has a custom workflow. I'm going to do a workflow transition from Python, using doActionFor
, and do a bunch of things when IActionSucceededEvent
is triggered.
My question is: if I raise an exception on any of .handlers.actionSucceeded
if an error occurs, will the doActionFor
call be reverted (even after IActionSucceededEvent
was run)? If not, if I use IActionWillBeInvokedEvent
, will I be able to accomplish my goals? Will I have a problem for having two different products, both using Products.CMF开发者_运维百科Core.interfaces.IActionSucceededEvent
for the same ..interfaces.myinterface.IMyInterface
interface?
- Yes, if you raise any exception in one of your handlers the entire transaction will fail and it will be reverted
- no, you wouldn't have problems using more than one subscriber for the same interfaces. They would be execute in order of registration.
- no, using IActionWillBeInvokedEvent will not help. It's fired before wf transition, but if you raise exceptions the transaction will fail anyway.
You can check this by turning Plone debug level to DEBUG (default is info) and put logging output to the event handlers. In DEBUG logging Plone prints transaction boundaries.
If your exception causes "505 Internal Server error" when the exception is raised it will also unroll any on-going transaction (unless transaction.commit() is called manually, but that should not be the case for the normal code).
As per @Giacomo's response, the transaction will be aborted for any exception that isn't caught. So your best bet is to find out what errors you want to tolerate and catch those exceptions in your subscriber, log the exception, and then move on so the transaction will still be committed:
import logging
logger = logging.getLogger('mynamespace.myproduct')
...
def actionSucceeded(obj, event):
...
try:
my_dangerous_stuff(...)
except (TolerableException, AnotherTolerableException, ...):
logger.exception('Encountered an error while handling foo event')
...
精彩评论