在我们的 Symfony2 项目中,我们希望确保跨资源的修改是事务性的。例如,类似:
namespace ...;
use .../TransactionManager;
class MyService {
protected $tm;
public function __construct(TransactionManager $tm)
{
$this->tm = $tm;
}
/**
* @ManagedTransaction
*/
public function doSomethingAcrossResources()
{
...
// where tm is the transaction manager
// tm is exposing a Doctrine EntityManager adapter here
$this->tm->em->persist($entity);
...
// tm is exposing a redis adapter here
$this->tm->redis->set('foo', 'bar');
if ($somethingWentWrong) {
throw new Exception('Something went terribly wrong');
}
}
}
所以这里有几点需要注意:
- 每个资源都需要一个公开其 API 的适配器(例如 Doctrine 适配器、Redis 适配器、Memcache 适配器、文件适配器等)
- 如果出现问题(抛出异常),则不应将任何内容写入任何托管资源(即回滚所有内容)。
- 如果一切正常,所有资源都将按预期更新
- doSomethingAcrossResources 函数不必担心撤销它对非事务性资源(例如文件和 Memcache)所做的更改。这是关键,因为否则,这段代码可能会变得一团糟,只能在适当的时间写入 redis,等等。
- @ManagedTransacton 注释将处理其余部分(提交/回滚/启动所需的事务(基于适配器)等)
- 在最简单的实现中,tm 可以简单地管理一个队列并按顺序将所有项目出队。如果抛出异常,它根本不会使任何东西出队。所以适配器是事务管理器关于如何提交队列中每个项目的知识。
- 如果在出队期间发生异常,则事务管理器将查看它的适配器以了解如何回滚已经出队的项目(可能放置在回滚堆栈中)。对于像 EntityManager 这样需要在内部管理事务以便轻松回滚更改的资源来说,这可能会变得很棘手。但是,redis 适配器可能会在更新期间缓存以前的值,或者在 ADD 期间简单地在回滚期间发出 DELETE。
像这样的事务管理器是否已经存在?有没有更好的方法来实现这些目标?是否有我可能忽略的警告?
谢谢!