I have just been discussing this with Jonathan and the we are proposing the following approach to transaction timeout.
1. When the transport determines that the transaction is flowing to a different server, it should query TransactionTimeoutConfiguration to find out how long is left for the transaction by calling: getTimeLeftBeforeTransactionTimeout
2. It flows this value over to the remote side and calls SubordinationManager.getTransactionImporter().importTransaction(xid, timeout) with a timeout equal to this original value plus a value (for the purposes of this discussion we can call it a fudgefactor)
Why the need for the fudgefactor?
Basically we need to ensure that the subordinate transactions do not timeout before the parent transaction. If such a situation arises then the transaction when it tries to complete will get a heuristic. Why? Well basically after the subordinate transaction rollsback at time T (because of the timeout) then it will clean up after itself. Now when the parent tries to rollback the transaction (at time T+1) the subordinate will not know about the transaction. This will cascade a rollback but a heuristic one which is not great.
Ideally we would have the parent transaction manager responsible for monitoring the timeout and cascading this down, but if the root fails (or a link in the chain) then locks would be help indefinitely until that node resumed.
If we have a directly connected transport that can determine when a linked node fails then we could remove the fudgefactor and look at implementing an immediate rollback in the case of parent/child failure...