- public TransactionChainProxy(ActorContext actorContext) {
- this.actorContext = actorContext;
- transactionChainId = actorContext.getCurrentMemberName() + "-txn-chain-" + counter.incrementAndGet();
- }
-
- public String getTransactionChainId() {
- return transactionChainId;
+ /**
+ * This map holds Promise instances for each read-only tx. It is used to maintain ordering of tx creates
+ * wrt to read-only tx's between this class and a LocalTransactionChain since they're bridged by
+ * asynchronous futures. Otherwise, in the following scenario, eg:
+ * <p/>
+ * 1) Create write tx1 on chain
+ * 2) do write and submit
+ * 3) Create read-only tx2 on chain and issue read
+ * 4) Create write tx3 on chain, do write but do not submit
+ * <p/>
+ * if the sequence/timing is right, tx3 may create its local tx on the LocalTransactionChain before tx2,
+ * which results in tx2 failing b/c tx3 isn't ready yet. So maintaining ordering prevents this issue
+ * (see Bug 4774).
+ * <p/>
+ * A Promise is added via newReadOnlyTransaction. When the parent class completes the primary shard
+ * lookup and creates the TransactionContext (either success or failure), onTransactionContextCreated is
+ * called which completes the Promise. A write tx that is created prior to completion will wait on the
+ * Promise's Future via findPrimaryShard.
+ */
+ private final ConcurrentMap<TransactionIdentifier, Promise<Object>> priorReadOnlyTxPromises =
+ new ConcurrentHashMap<>();
+
+ TransactionChainProxy(final TransactionContextFactory parent, final LocalHistoryIdentifier historyId) {
+ super(parent.getActorUtils(), historyId);
+ this.parent = parent;