Implement reference transaction service
As part of the two-phase commit for Gitaly, we need a central service which handles transactions for us. With the service, the flow will basically look like following:
1. When getting a repository-scoped mutating request, Praefect will
allocate a new transaction with the service and forward the
transaction identifier to all nodes taking part in the
transaction.
2. Upon doing any kind of reference update, the nodes will connect
to the transaction service and present the transaction
identifier.
3. As soon as all nodes have voted on the transaction, the
transaction service will return each of the client's RPC with a
"commit" message.
4. The clients perform the reference update.
In order to count and evaluate votes, the transaction service needs to know about all the participants that may cast a vote. As such, the transaction registration will pass along the set of all Gitaly nodes that take part in the process. As we will always have exactly one voter at first, which is the primary Gitaly node, we currently enforce this limit to keep the initial service implementation simple.
To establish whether all voters agree on a given transaction, they need to announce the reference updates they intend to perform. In order to decrease the size of such an announcement in case there are several thousand reference updates at once, each node will only send a hash of planned reference updates.
This is only the first part, I didn't yet wire it up with anything. That's going to be the next step, though, where I let the primary reach out to this new transaction service in case a feature flag is set for two-phase commits.