forked from Qortal/qortal
Cache transaction list for 2 minutes, and synchronize, to prevent the balance and transactions APIs both requesting at once.
This ensures that only a single round of requests (per coin) is used for the wallettransactions and balance APIs. It also speeds up loading on subsequent requests. The 2 minute cache isn't much longer than the foreign block times, so shouldn't cause values to be too out of date.
This commit is contained in:
parent
892612c084
commit
9224ffbf73
@ -39,6 +39,7 @@ import org.qortal.utils.Amounts;
|
||||
import org.qortal.utils.BitTwiddling;
|
||||
|
||||
import com.google.common.hash.HashCode;
|
||||
import org.qortal.utils.NTP;
|
||||
|
||||
/** Bitcoin-like (Bitcoin, Litecoin, etc.) support */
|
||||
public abstract class Bitcoiny implements ForeignBlockchain {
|
||||
@ -53,6 +54,11 @@ public abstract class Bitcoiny implements ForeignBlockchain {
|
||||
|
||||
protected final NetworkParameters params;
|
||||
|
||||
/** Cache recent transactions to speed up subsequent lookups */
|
||||
protected List<SimpleTransaction> transactionsCache;
|
||||
protected Long transactionsCacheTimestamp;
|
||||
protected static long TRANSACTIONS_CACHE_TIMEOUT = 2 * 60 * 1000L; // 2 minutes
|
||||
|
||||
/** Keys that have been previously marked as fully spent,<br>
|
||||
* i.e. keys with transactions but with no unspent outputs. */
|
||||
protected final Set<ECKey> spentKeys = Collections.synchronizedSet(new HashSet<>());
|
||||
@ -353,6 +359,18 @@ public abstract class Bitcoiny implements ForeignBlockchain {
|
||||
}
|
||||
|
||||
public List<SimpleTransaction> getWalletTransactions(String key58) throws ForeignBlockchainException {
|
||||
synchronized (this) {
|
||||
// Serve from the cache if it's recent
|
||||
if (transactionsCache != null && transactionsCacheTimestamp != null) {
|
||||
Long now = NTP.getTime();
|
||||
boolean isCacheStale = (now != null && now - transactionsCacheTimestamp >= TRANSACTIONS_CACHE_TIMEOUT);
|
||||
if (!isCacheStale) {
|
||||
LOGGER.info("Serving transactions from cache");
|
||||
return transactionsCache;
|
||||
}
|
||||
}
|
||||
LOGGER.info("Fetching transactions from ElectrumX");
|
||||
|
||||
Context.propagate(bitcoinjContext);
|
||||
|
||||
Wallet wallet = walletFromDeterministicKey58(key58);
|
||||
@ -401,8 +419,7 @@ public abstract class Bitcoiny implements ForeignBlockchain {
|
||||
}
|
||||
// We haven't hit our search limit yet so increment the counter and keep looking
|
||||
unusedCounter++;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// Some keys in this batch were used, so reset the counter
|
||||
unusedCounter = 0;
|
||||
}
|
||||
@ -415,7 +432,14 @@ public abstract class Bitcoiny implements ForeignBlockchain {
|
||||
|
||||
Comparator<SimpleTransaction> newestTimestampFirstComparator = Comparator.comparingInt(SimpleTransaction::getTimestamp).reversed();
|
||||
|
||||
return walletTransactions.stream().map(t -> convertToSimpleTransaction(t, keySet)).sorted(newestTimestampFirstComparator).collect(Collectors.toList());
|
||||
// Update cache and return
|
||||
transactionsCacheTimestamp = NTP.getTime();
|
||||
transactionsCache = walletTransactions.stream()
|
||||
.map(t -> convertToSimpleTransaction(t, keySet))
|
||||
.sorted(newestTimestampFirstComparator).collect(Collectors.toList());
|
||||
|
||||
return transactionsCache;
|
||||
}
|
||||
}
|
||||
|
||||
protected SimpleTransaction convertToSimpleTransaction(BitcoinyTransaction t, Set<String> keySet) {
|
||||
|
Loading…
Reference in New Issue
Block a user