Multi-Content Revisions/Transaction Management

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:

(Code experiment: https://gerrit.wikimedia.org/r/#/c/299521/)

A  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: