Skip to content
This repository has been archived by the owner on Aug 23, 2020. It is now read-only.

Commit

Permalink
Add solidification queue to transaction solidifier
Browse files Browse the repository at this point in the history
  • Loading branch information
DyrellC committed Mar 30, 2020
1 parent ff0ef35 commit 8ed7600
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,6 @@ public class MilestoneSolidifierImpl implements MilestoneSolidifier {
*/
private static final int SOLIDIFICATION_INTERVAL = 100;

/**
* <p>
* Defines the maximum amount of transactions that are allowed to get processed while trying to solidify a
* milestone.
* </p>
* <p>
* Note: We want to find the next previous milestone and not get stuck somewhere at the end of the tangle with a
* long running {@link TransactionSolidifier#checkSolidity(Hash)} call.
* </p>
*/
private static final int SOLIDIFICATION_TRANSACTIONS_LIMIT = 50000;

/**
* Logger for this class allowing us to dump debug and status messages.
*/
Expand Down Expand Up @@ -341,7 +329,7 @@ private boolean isSolid(Map.Entry<Hash, Integer> currentEntry) {
}

try {
return transactionSolidifier.checkSolidity(currentEntry.getKey(), SOLIDIFICATION_TRANSACTIONS_LIMIT);
return transactionSolidifier.addMilestoneToSolidificationQueue(currentEntry.getKey());
} catch (Exception e) {
log.error("Error while solidifying milestone #" + currentEntry.getValue(), e);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,22 @@ public interface TransactionSolidifier {
*/
void shutdown();

/**
* Add a hash to the solidification queue, and runs an initial {@link #checkSolidity} call.
*
* @param hash Hash of the transaction to solidify
*/
void addToSolidificationQueue(Hash hash);

/**
* Checks if milestone transaction is solid. Returns true if it is, and if it is not, it adds the hash to the
* solidification queue and returns false.
*
* @param hash Hash of the transaction to solidify
* @return True if solid, false if not
*/
boolean addMilestoneToSolidificationQueue(Hash hash);

/**
* Fetch the next transaction in the transactionsToBroadcast set.
* @return A {@link TransactionViewModel} object to be broadcast.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,29 @@ public class TransactionSolidifierImpl implements TransactionSolidifier {

private static final IntervalLogger log = new IntervalLogger(TransactionSolidifier.class);

/**
* Defines the maximum amount of transactions that are allowed to get processed while trying to solidify a
* milestone.
*
* NOte: we want to find the next previous milestone and not get stuck somewhere at the end of the tangle with a
* long running {@link #checkSolidity(Hash)} call.
*/
private static final int SOLIDIFICATION_TRANSACTIONS_LIMIT = 50000;


/**
* Executor service for running the {@link #processTransactionsToSolidify()}.
*/
private SilentScheduledExecutorService executorService = new DedicatedScheduledExecutorService(
"Transaction Solidifier", log.delegate());

/**
* A queue for processing transactions with the {@link #checkSolidity(Hash)} call. Once a transaction has been
* marked solid it will be placed into the {@link #transactionsToBroadcast} queue.
*/
private BlockingQueue<Hash> transactionsToSolidify = new LinkedBlockingQueue<>(MAX_SIZE);


/**
* A set of transactions that will be called by the {@link TransactionProcessingPipeline} to be broadcast to
* neighboring nodes.
Expand Down Expand Up @@ -87,6 +104,43 @@ public void shutdown() {
executorService.shutdownNow();
}

/**
*{@inheritDoc}
*/
@Override
public void addToSolidificationQueue(Hash hash){
try{
if(!transactionsToSolidify.contains(hash)) {
if (transactionsToSolidify.size() >= MAX_SIZE - 1) {
transactionsToSolidify.remove();
}

transactionsToSolidify.put(hash);
}
} catch(Exception e){
log.error("Error placing transaction into solidification queue",e);
}
}

/**
* {@inheritDoc}
*/
@Override
public boolean addMilestoneToSolidificationQueue(Hash hash){
try{
TransactionViewModel tx = fromHash(tangle, hash);
if(tx.isSolid()){
transactionPropagator.addToPropagationQueue(hash);
return true;
}
addToSolidificationQueue(hash);
return false;
}catch(Exception e){
log.error("Error adding milestone to solidification queue", e);
return false;
}
}

/**
*{@inheritDoc}
*/
Expand All @@ -105,9 +159,19 @@ public void clearFromBroadcastQueue(TransactionViewModel transaction){


/**
* Process any solid transactions present in the {@link TransactionPropagator}.
* Iterate through the {@link #transactionsToSolidify} queue and call {@link #checkSolidity(Hash)} on each hash.
* Solid transactions are then processed into the {@link #transactionsToBroadcast} queue. After that, process any
* solid transactions present in the {@link TransactionPropagator}.
*/
private void processTransactionsToSolidify(){
Hash hash;
if((hash = transactionsToSolidify.poll()) != null) {
try {
checkSolidity(hash);
} catch (Exception e) {
log.info(e.getMessage());
}
}
transactionPropagator.propagateSolidTransactions();
}

Expand All @@ -116,7 +180,7 @@ private void processTransactionsToSolidify(){
*/
@Override
public boolean checkSolidity(Hash hash) throws Exception {
return checkSolidity(hash, 50000);
return checkSolidity(hash, SOLIDIFICATION_TRANSACTIONS_LIMIT);
}

/**
Expand Down Expand Up @@ -218,6 +282,12 @@ private void addToBroadcastQueue(TransactionViewModel tvm) {
}
}

@VisibleForTesting
Set<Hash> getSolidificationQueue(){
return new LinkedHashSet<>(transactionsToSolidify);
}


@Override
public void updateStatus(TransactionViewModel transactionViewModel) throws Exception {
transactionRequester.clearTransactionRequest(transactionViewModel.getHash());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,22 @@ public void verifyTxIsNotSolid() throws Exception {
assertFalse("Expected transaction to fail solidity check", txSolidifier.checkSolidity(tx.getHash()));
}

@Test
public void getSolidificationQueue() throws Exception {
TransactionViewModel mainTx = getTxWithBranchAndTrunk();
for(int i = 0; i < 10; i++) {
TransactionViewModel tx = getTxWithBranchAndTrunk();
txSolidifier.addToSolidificationQueue(tx.getHash());
}
txSolidifier.addToSolidificationQueue(mainTx.getHash());
assertTrue("Expected transaction to be present in the solidification queue",
txSolidifier.getSolidificationQueue().contains(mainTx.getHash()));
}

@Test
public void verifyTransactionIsProcessedFully() throws Exception {
TransactionViewModel tx = getTxWithBranchAndTrunk();
txSolidifier.checkSolidity(tx.getHash());
txSolidifier.addToSolidificationQueue(tx.getHash());

//Time to process through the steps
Thread.sleep(1000);
Expand All @@ -121,7 +132,7 @@ public void verifyTransactionIsProcessedFully() throws Exception {
@Test
public void verifyInconsistentTransactionIsNotProcessedFully() throws Exception {
TransactionViewModel tx = getTxWithoutBranchAndTrunk();
txSolidifier.checkSolidity(tx.getHash());
txSolidifier.addToSolidificationQueue(tx.getHash());

//Time to process through the steps
Thread.sleep(1000);
Expand Down

0 comments on commit 8ed7600

Please sign in to comment.