Transaction hooks for 2PC
Problem to solve
When a success signal is sent via the Git protocol or an RPC for a write operation from a HA Gitaly cluster, we want the success signal to communicate that the write has succeeded in multiple locations so that a single node failure does not result in data loss.
We need a way to hook into the Git write life cycle to perform a transactional write across multiple nodes. A proof of concept is being implemented using a pre-receive
hook, but we want coverage of all write operations, not just git-receive-pack
Proposal
Implement new hooks in Git designed to help us capture all write operations. As all reference updates use Git's reference transaction mechanism, this would be the natural place to implement this set of hooks. Currently, these transactions have the following states:
- open: a transaction was created, reference updates can be added to it
- prepared: reference updates were queued and locks are taken for the references that are to be updated
- aborted: the locks were rolled back and no changes were done to the repository
- committed: the reference updates were committed
Three hooks should be implemented for the "prepared", "aborted" and "committed" states that allow to directly hook into Git's reference transaction in order to allow for much more fine-grained control over reference updates. As input, the hooks should get all references with their old and new states via stdin with the same format as the pre-receive-hook ("update ").
While the "ref-tx-aborted" and "ref-tx-committed" hooks may only be of informing nature as the transaction is finished already, the "ref-tx-prepared" hook should be able to abort the transaction by returning an error code.