+ // Global lock used for transactions spanning multiple shards - synchronizes sending of the ready messages
+ // for atomicity to avoid potential deadlock with concurrent transactions spanning the same shards as outlined
+ // in the following scenario:
+ //
+ // - Tx1 sends ready message to shard A
+ // - Tx2 sends ready message to shard A
+ // - Tx2 sends ready message to shard B
+ // - Tx1 sends ready message to shard B
+ //
+ // This scenario results in deadlock: after Tx1 canCommits to shard A, it can't proceed with shard B until Tx2
+ // completes as Tx2 was readied first on shard B. However Tx2 cannot make progress because it's waiting to canCommit
+ // on shard A which is blocked by Tx1.
+ //
+ // The global lock avoids this as it forces the ready messages to be sent in a predictable order:
+ //
+ // - Tx1 sends ready message to shard A
+ // - Tx1 sends ready message to shard B
+ // - Tx2 sends ready message to shard A
+ // - Tx2 sends ready message to shard B
+ //
+ private static final Object GLOBAL_TX_READY_LOCK = new Object();
+
+ private final Map<String, TransactionContextWrapper> txContextWrappers = new TreeMap<>();