Add txs-by-id cache to WalletService to speed up trade history view

Add a third cache to WalletService, cleared upon wallet change events,
which maps txIds to txs. This allows the speedup of repeated calls to
'WalletService.getConfidenceForTxId', by avoiding the need to copy and
scan the entire set of wallet txs to find the one with matching id,
for each method invocation.

This is mainly to provide a further speedup to the closed-trades-view
load, by making it much faster to filter the list of BSQ swap trades by
tx confirmation status in 'ClosedTradesDataModel.applyList' and
'ClosedTradesManager.getNumPastTrades'.
This commit is contained in:
Steven Barclay 2023-02-01 23:02:25 +08:00
parent 42ea12f74c
commit 57b2b4b864
No known key found for this signature in database
GPG Key ID: 9FED6BF1176D500B

View File

@ -72,6 +72,7 @@ import org.bitcoinj.wallet.listeners.WalletReorganizeEventListener;
import javax.inject.Inject; import javax.inject.Inject;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultiset; import com.google.common.collect.ImmutableMultiset;
import com.google.common.collect.ImmutableSetMultimap; import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Multiset; import com.google.common.collect.Multiset;
@ -87,6 +88,7 @@ import org.bouncycastle.crypto.params.KeyParameter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.CopyOnWriteArraySet;
@ -122,6 +124,7 @@ public abstract class WalletService {
private final WalletChangeEventListener cacheInvalidationListener; private final WalletChangeEventListener cacheInvalidationListener;
private final AtomicReference<Multiset<Address>> txOutputAddressCache = new AtomicReference<>(); private final AtomicReference<Multiset<Address>> txOutputAddressCache = new AtomicReference<>();
private final AtomicReference<SetMultimap<Address, Transaction>> addressToMatchingTxSetCache = new AtomicReference<>(); private final AtomicReference<SetMultimap<Address, Transaction>> addressToMatchingTxSetCache = new AtomicReference<>();
private final AtomicReference<Map<Sha256Hash, Transaction>> txByIdCache = new AtomicReference<>();
@Getter @Getter
protected Wallet wallet; protected Wallet wallet;
@Getter @Getter
@ -147,6 +150,7 @@ public abstract class WalletService {
cacheInvalidationListener = wallet -> { cacheInvalidationListener = wallet -> {
txOutputAddressCache.set(null); txOutputAddressCache.set(null);
addressToMatchingTxSetCache.set(null); addressToMatchingTxSetCache.set(null);
txByIdCache.set(null);
}; };
} }
@ -463,17 +467,25 @@ public abstract class WalletService {
} }
@Nullable @Nullable
public TransactionConfidence getConfidenceForTxId(String txId) { public TransactionConfidence getConfidenceForTxId(@Nullable String txId) {
if (wallet != null) { if (wallet != null && txId != null) {
Set<Transaction> transactions = wallet.getTransactions(false); Transaction tx = getTxByIdMap().get(Sha256Hash.wrap(txId));
for (Transaction tx : transactions) { if (tx != null) {
if (tx.getTxId().toString().equals(txId))
return tx.getConfidence(); return tx.getConfidence();
} }
} }
return null; return null;
} }
private Map<Sha256Hash, Transaction> getTxByIdMap() {
return txByIdCache.updateAndGet(map -> map != null ? map : computeTxByIdMap());
}
private Map<Sha256Hash, Transaction> computeTxByIdMap() {
return wallet.getTransactions(false).stream()
.collect(ImmutableMap.toImmutableMap(Transaction::getTxId, tx -> tx));
}
@Nullable @Nullable
private TransactionConfidence getTransactionConfidence(Transaction tx, Address address) { private TransactionConfidence getTransactionConfidence(Transaction tx, Address address) {
List<TransactionConfidence> transactionConfidenceList = getOutputsWithConnectedOutputs(tx).stream() List<TransactionConfidence> transactionConfidenceList = getOutputsWithConnectedOutputs(tx).stream()
@ -761,7 +773,7 @@ public abstract class WalletService {
} }
@Nullable @Nullable
public Transaction getTransaction(String txId) { public Transaction getTransaction(@Nullable String txId) {
if (txId == null) { if (txId == null) {
return null; return null;
} }