If your first two transactions are successful, then secondTx would conflict. The middle transaction would have a commit version that comes after the commit version of firstTx (and consequently the read version of secondTx). Because secondTx depends on fencingTokenKey and that key changes between its read and potential commit versions, the transaction cannot succeed.
If the middle transaction runs simultaneously with secondTx, then it is possible for secondTx to succeed. This could happen if secondTx commits first (i.e. with a lower commit version) than the middle transaction. In that case, it’s as if the modification to fencingTokenKey doesn’t occur until after secondTx is done. However, if it is certain that the middle transaction commits first, then secondTx will fail.
I’m not certain which constraint was intended here (I’m guessing middle starts after secondTx), but I don’t think it matters when these two transactions start, only when they commit. This is because secondTx is being given an explicit read version regardless of when it starts, and the middle transaction has no reads and can’t be failed due to conflict.
The thing that matters is which of the two transactions commits first. If the middle transaction commits first, then we can’t commit secondTx because of the change to fencingTokenKey that occurred between secondTx’s read version and when it’s trying to commit. If secondTx commits first, then it can succeed and the middle transaction can commit afterward because it had no reads.
That’s correct, but I think the reason will eventually change once the 5-second window has passed. At first it will repeatedly fail with a conflict (i.e. not_committed), but after the read version becomes more than 5 seconds old, it will start to fail with transaction_too_old.