2

假设我有mynamespace.myproduct

 <subscriber for="..interfaces.myinterface.IMyInterface
                  Products.CMFCore.interfaces.IActionSucceededEvent" 
            handler=".handlers.actionSucceeded" 
    /> 

mynamespace.myproduct2

 <subscriber for="..interfaces.myinterface.IMyInterface
                  Products.CMFCore.interfaces.IActionSucceededEvent" 
            handler=".handlers.actionSucceeded" 
    /> 

(处理程序在每个产品上做不同的事情,即使他们在这个例子中有相同的名字)

我有一个具有自定义工作流程的自定义类型。我将使用 Python 进行工作流转换,并在触发doActionFor时做很多事情。IActionSucceededEvent

我的问题是:如果我在任何.handlers.actionSucceeded错误发生时引发异常,doActionFor调用是否会被恢复(即使在IActionSucceededEvent运行之后)?如果没有,如果我使用IActionWillBeInvokedEvent,我能实现我的目标吗?如果我有两种不同的产品,都使用Products.CMFCore.interfaces.IActionSucceededEvent相同的..interfaces.myinterface.IMyInterface界面,我会有问题吗?

4

3 回答 3

4
  1. 是的,如果您在其中一个处理程序中引发任何异常,则整个事务将失败并且将被还原
  2. 不,对于相同的接口使用多个订阅者不会有问题。它们将按注册顺序执行。
  3. 不,使用 IActionWillBeInvokedEvent 将无济于事。它在 wf 转换之前触发,但如果您引发异常,事务无论如何都会失败。
于 2011-09-05T22:10:59.633 回答
3

您可以通过将 Plone 调试级别设置为 DEBUG(默认为 info)并将日志记录输出到事件处理程序来检查这一点。在 DEBUG 日志记录中,Plone 打印事务边界。

如果您的异常在引发异常时导致“505 内部服务器错误”,它还将展开任何正在进行的事务(除非手动调用 transaction.commit(),但正常代码不应如此)。

于 2011-09-05T22:03:14.273 回答
3

根据@Giacomo 的响应,事务将因任何未捕获的异常而中止。所以你最好的办法是找出你想要容忍的错误,并在你的订阅者中捕获这些异常,记录异常,然后继续,这样事务仍然会被提交:

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')
    ...
于 2011-09-06T04:44:02.960 回答