Multi-Content Revisions/Transaction Management
This page is obsolete. It is being retained for archival purposes. It may document extensions or features that are obsolete and/or no longer supported. Do not rely on the information here being up-to-date. |
To provide atomic storage operations, we need a way to maintain a transaction context across multiple stages of saving, and across different storage backends. One options would be a lightweight pair of interfaces:
interface Transaction {
public function begin();
public function commit();
public function abort();
}
interface TransactionBuilder {
/**
* @param callable $callback the action to perform on prepare.
*/
public function onPrepareDo( $callback );
/**
* @param callable $callback the action to perform on commit.
*/
public function onCommitDo( $callback );
/**
* @param callable $callback the action to perform on abort.
*/
public function onAbortDo( $callback );
}
(Code experiment: https://gerrit.wikimedia.org/r/#/c/299521/)
A TransactionManager
class that implements the two interfaces would then just call all abort callbacks on abort(), and all prepare and later all commit callbacks on commit().
Services that need transactional context (such as BlobStore) would take a TransactionBuilder as a parameter to the relevant methods. Controllers can take a TransactionBuilder in the constructor, if the respective factory methods that creates the controller takes one as a parameter.
An SQL based storage service would use the TransactionBuilder as follows:
$dbw = $this->dbLoadBalancer->getConnection( DB_MASTER );
$dbw->startAtomic( __METHOD__ );
$dbw-insert( ... );
$method = __METHOD__;
$trx->onCommitDo( function() use ( $dbw, $method ) {
$dbw->endAtomic( $method );
// XXX: call $this->dbLoadBalancer->reuseConnection( $dbw ) here?
}, __METHOD__ );
$trx->onAbortDo( function() use ( $dbw ) {
$dbw->rollback();
}, __METHOD__ );
// XXX: ...or call $this->dbLoadBalancer->reuseConnection( $dbw ) here?