Skip to content

Allow multiple votes per transaction

Patrick Steinhardt requested to merge pks-subtransactions into master

Right now, we're using the pre-receive hook to call into transactions on the Gitaly nodes. This hook is well-understood to be executed once and only once per action, and as a result the current implementation of transactions allowed for a single vote via this pre-receive hook, only. The pre-receive hook was a stop-gap implementation of the real mechanism we wanted to eventually use, though, which is the reference-transaction hook that's going to be released as part of git-croe v2.28. While the input to both hooks is the same and thus no changes to the actual voting logic should be required, the most important difference is that the reference-transaction hook may be invoked arbitrarily many times for each Git command. E.g. a non-atomic push will execute the hook as many times as there are updated references.

This surfaces a current design limitation of the transaction mechanism as it is implemented in Gitaly: as a transaction only allows for a single vote per node, it's inherently incompatible with the semantics introduce by the reference-transaction hook. This is why we now extend the transaction mechanism to allow a sequence of votes instead by introducing subtransactions.

Subtransactions encapsulate all the voting logic that was previously part of the transaction, which is casting the vote and collecting the votes to establish whether quorum was reached. Transactions now start to be a wrapper of a set of transactions, which transparantly creates new subtransactions as required whenever a node casts a vote. Whenever a node casts a vote, one of three things may now happen:

1. A subtransaction exists where the node's status is "aborted". This
   means that any one of the subtransactions failed and thus the
   complete transaction needs to be labelled as "aborted" for the
   node. It will receive an error and is not allowed to cast any
   votes anymore.

2. A subtransaction exists where the node's state is "undecided". As
   this means that the node simply didn't cast a vote, it will cast
   its vote for the oldest undecided subtransaction and wait for
   quorum to be reached.

3. All existing subtransactions are in "committed" state for the
   given node. We'll thus create a new subtransaction, cast our vote
   for this new transaction and wait for quorum to be reached.

To evaluate the complete transaction's outcome, we need to establish whether for a given node, all created subtransactions are in state "committed". Only if that's the case will the transaction be treated as successful for the node.

With this logic, we're now able to transparently allow a voter to cast a sequence of votes.

Closes #2939 (closed)

Merge request reports

Loading