[NC-1558] Retry tasks a max number of times before failing (#74)

mbaxter 6 years ago committed by GitHub
parent 97b341b0c9
commit 05b8f1fab1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      ethereum/eth/src/main/java/tech/pegasys/pantheon/ethereum/eth/manager/AbstractRetryingPeerTask.java
  2. 3
      ethereum/eth/src/main/java/tech/pegasys/pantheon/ethereum/eth/manager/exceptions/EthTaskException.java
  3. 8
      ethereum/eth/src/main/java/tech/pegasys/pantheon/ethereum/eth/manager/exceptions/MaxRetriesReachedException.java
  4. 16
      ethereum/eth/src/main/java/tech/pegasys/pantheon/ethereum/eth/sync/tasks/CompleteBlocksTask.java
  5. 24
      ethereum/eth/src/main/java/tech/pegasys/pantheon/ethereum/eth/sync/tasks/DownloadHeaderSequenceTask.java
  6. 4
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/ethtaskutils/AbstractMessageTaskTest.java
  7. 118
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/ethtaskutils/RetryingMessageTaskTest.java
  8. 14
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/manager/ethtaskutils/RetryingMessageTaskWithResultsTest.java
  9. 7
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/tasks/CompleteBlocksTaskTest.java
  10. 12
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/tasks/DownloadHeaderSequenceTaskTest.java
  11. 4
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/sync/tasks/PipelinedImportChainSegmentTaskTest.java

@ -1,5 +1,6 @@
package tech.pegasys.pantheon.ethereum.eth.manager; package tech.pegasys.pantheon.ethereum.eth.manager;
import tech.pegasys.pantheon.ethereum.eth.manager.exceptions.MaxRetriesReachedException;
import tech.pegasys.pantheon.ethereum.eth.manager.exceptions.NoAvailablePeersException; import tech.pegasys.pantheon.ethereum.eth.manager.exceptions.NoAvailablePeersException;
import tech.pegasys.pantheon.ethereum.eth.sync.tasks.WaitForPeerTask; import tech.pegasys.pantheon.ethereum.eth.sync.tasks.WaitForPeerTask;
import tech.pegasys.pantheon.util.ExceptionUtils; import tech.pegasys.pantheon.util.ExceptionUtils;
@ -14,9 +15,12 @@ public abstract class AbstractRetryingPeerTask<T> extends AbstractEthTask<T> {
private static final Logger LOG = LogManager.getLogger(); private static final Logger LOG = LogManager.getLogger();
private final EthContext ethContext; private final EthContext ethContext;
private final int maxRetries;
private int requestCount = 0;
public AbstractRetryingPeerTask(final EthContext ethContext) { public AbstractRetryingPeerTask(final EthContext ethContext, final int maxRetries) {
this.ethContext = ethContext; this.ethContext = ethContext;
this.maxRetries = maxRetries;
} }
@Override @Override
@ -25,7 +29,12 @@ public abstract class AbstractRetryingPeerTask<T> extends AbstractEthTask<T> {
// Return if task is done // Return if task is done
return; return;
} }
if (requestCount > maxRetries) {
result.get().completeExceptionally(new MaxRetriesReachedException());
return;
}
requestCount += 1;
executePeerTask() executePeerTask()
.whenComplete( .whenComplete(
(peerResult, error) -> { (peerResult, error) -> {

@ -17,6 +17,7 @@ public class EthTaskException extends RuntimeException {
PEER_DISCONNECTED, PEER_DISCONNECTED,
NO_AVAILABLE_PEERS, NO_AVAILABLE_PEERS,
PEER_BREACHED_PROTOCOL, PEER_BREACHED_PROTOCOL,
INCOMPLETE_RESULTS INCOMPLETE_RESULTS,
MAX_RETRIES_REACHED
} }
} }

@ -0,0 +1,8 @@
package tech.pegasys.pantheon.ethereum.eth.manager.exceptions;
public class MaxRetriesReachedException extends EthTaskException {
public MaxRetriesReachedException() {
super(FailureReason.MAX_RETRIES_REACHED);
}
}

@ -32,6 +32,7 @@ import org.apache.logging.log4j.Logger;
*/ */
public class CompleteBlocksTask<C> extends AbstractRetryingPeerTask<List<Block>> { public class CompleteBlocksTask<C> extends AbstractRetryingPeerTask<List<Block>> {
private static final Logger LOG = LogManager.getLogger(); private static final Logger LOG = LogManager.getLogger();
private static final int DEFAULT_RETRIES = 3;
private final EthContext ethContext; private final EthContext ethContext;
private final ProtocolSchedule<C> protocolSchedule; private final ProtocolSchedule<C> protocolSchedule;
@ -43,8 +44,9 @@ public class CompleteBlocksTask<C> extends AbstractRetryingPeerTask<List<Block>>
private CompleteBlocksTask( private CompleteBlocksTask(
final ProtocolSchedule<C> protocolSchedule, final ProtocolSchedule<C> protocolSchedule,
final EthContext ethContext, final EthContext ethContext,
final List<BlockHeader> headers) { final List<BlockHeader> headers,
super(ethContext); final int maxRetries) {
super(ethContext, maxRetries);
checkArgument(headers.size() > 0, "Must supply a non-empty headers list"); checkArgument(headers.size() > 0, "Must supply a non-empty headers list");
this.protocolSchedule = protocolSchedule; this.protocolSchedule = protocolSchedule;
this.ethContext = ethContext; this.ethContext = ethContext;
@ -53,11 +55,19 @@ public class CompleteBlocksTask<C> extends AbstractRetryingPeerTask<List<Block>>
this.blocks = new HashMap<>(); this.blocks = new HashMap<>();
} }
public static <C> CompleteBlocksTask<C> forHeaders(
final ProtocolSchedule<C> protocolSchedule,
final EthContext ethContext,
final List<BlockHeader> headers,
final int maxRetries) {
return new CompleteBlocksTask<>(protocolSchedule, ethContext, headers, maxRetries);
}
public static <C> CompleteBlocksTask<C> forHeaders( public static <C> CompleteBlocksTask<C> forHeaders(
final ProtocolSchedule<C> protocolSchedule, final ProtocolSchedule<C> protocolSchedule,
final EthContext ethContext, final EthContext ethContext,
final List<BlockHeader> headers) { final List<BlockHeader> headers) {
return new CompleteBlocksTask<>(protocolSchedule, ethContext, headers); return new CompleteBlocksTask<>(protocolSchedule, ethContext, headers, DEFAULT_RETRIES);
} }
@Override @Override

@ -35,6 +35,7 @@ import org.apache.logging.log4j.Logger;
*/ */
public class DownloadHeaderSequenceTask<C> extends AbstractRetryingPeerTask<List<BlockHeader>> { public class DownloadHeaderSequenceTask<C> extends AbstractRetryingPeerTask<List<BlockHeader>> {
private static final Logger LOG = LogManager.getLogger(); private static final Logger LOG = LogManager.getLogger();
private static final int DEFAULT_RETRIES = 3;
private final EthContext ethContext; private final EthContext ethContext;
private final ProtocolContext<C> protocolContext; private final ProtocolContext<C> protocolContext;
@ -52,8 +53,9 @@ public class DownloadHeaderSequenceTask<C> extends AbstractRetryingPeerTask<List
final ProtocolContext<C> protocolContext, final ProtocolContext<C> protocolContext,
final EthContext ethContext, final EthContext ethContext,
final BlockHeader referenceHeader, final BlockHeader referenceHeader,
final int segmentLength) { final int segmentLength,
super(ethContext); final int maxRetries) {
super(ethContext, maxRetries);
this.protocolSchedule = protocolSchedule; this.protocolSchedule = protocolSchedule;
this.protocolContext = protocolContext; this.protocolContext = protocolContext;
this.ethContext = ethContext; this.ethContext = ethContext;
@ -65,6 +67,17 @@ public class DownloadHeaderSequenceTask<C> extends AbstractRetryingPeerTask<List
lastFilledHeaderIndex = segmentLength; lastFilledHeaderIndex = segmentLength;
} }
public static <C> DownloadHeaderSequenceTask<C> endingAtHeader(
final ProtocolSchedule<C> protocolSchedule,
final ProtocolContext<C> protocolContext,
final EthContext ethContext,
final BlockHeader referenceHeader,
final int segmentLength,
final int maxRetries) {
return new DownloadHeaderSequenceTask<>(
protocolSchedule, protocolContext, ethContext, referenceHeader, segmentLength, maxRetries);
}
public static <C> DownloadHeaderSequenceTask<C> endingAtHeader( public static <C> DownloadHeaderSequenceTask<C> endingAtHeader(
final ProtocolSchedule<C> protocolSchedule, final ProtocolSchedule<C> protocolSchedule,
final ProtocolContext<C> protocolContext, final ProtocolContext<C> protocolContext,
@ -72,7 +85,12 @@ public class DownloadHeaderSequenceTask<C> extends AbstractRetryingPeerTask<List
final BlockHeader referenceHeader, final BlockHeader referenceHeader,
final int segmentLength) { final int segmentLength) {
return new DownloadHeaderSequenceTask<>( return new DownloadHeaderSequenceTask<>(
protocolSchedule, protocolContext, ethContext, referenceHeader, segmentLength); protocolSchedule,
protocolContext,
ethContext,
referenceHeader,
segmentLength,
DEFAULT_RETRIES);
} }
@Override @Override

@ -23,6 +23,10 @@ import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
/**
* @param <T> The type of data being requested from the network
* @param <R> The type of data returned from the network
*/
public abstract class AbstractMessageTaskTest<T, R> { public abstract class AbstractMessageTaskTest<T, R> {
protected static Blockchain blockchain; protected static Blockchain blockchain;
protected static ProtocolSchedule<Void> protocolSchedule; protected static ProtocolSchedule<Void> protocolSchedule;

@ -1,17 +1,18 @@
package tech.pegasys.pantheon.ethereum.eth.manager.ethtaskutils; package tech.pegasys.pantheon.ethereum.eth.manager.ethtaskutils;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import tech.pegasys.pantheon.ethereum.eth.manager.EthPeer;
import tech.pegasys.pantheon.ethereum.eth.manager.EthProtocolManagerTestUtil; import tech.pegasys.pantheon.ethereum.eth.manager.EthProtocolManagerTestUtil;
import tech.pegasys.pantheon.ethereum.eth.manager.EthTask; import tech.pegasys.pantheon.ethereum.eth.manager.EthTask;
import tech.pegasys.pantheon.ethereum.eth.manager.RespondingEthPeer; import tech.pegasys.pantheon.ethereum.eth.manager.RespondingEthPeer;
import tech.pegasys.pantheon.ethereum.eth.manager.RespondingEthPeer.Responder; import tech.pegasys.pantheon.ethereum.eth.manager.RespondingEthPeer.Responder;
import tech.pegasys.pantheon.ethereum.eth.manager.exceptions.MaxRetriesReachedException;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.Test; import org.junit.Test;
@ -20,10 +21,22 @@ import org.junit.Test;
* *
* @param <T> * @param <T>
*/ */
public abstract class RetryingMessageTaskTest<T, R> extends AbstractMessageTaskTest<T, R> { public abstract class RetryingMessageTaskTest<T> extends AbstractMessageTaskTest<T, T> {
protected final int maxRetries;
public RetryingMessageTaskTest() {
this.maxRetries = 3;
}
@Override
protected void assertResultMatchesExpectation(
final T requestedData, final T response, final EthPeer respondingPeer) {
assertThat(response).isEqualTo(requestedData);
}
@Test @Test
public void doesNotCompleteWhenPeerReturnsPartialResult() public void failsWhenPeerRepeatedlyReturnsPartialResult()
throws ExecutionException, InterruptedException { throws ExecutionException, InterruptedException {
// Setup data to be requested and expected response // Setup data to be requested and expected response
@ -33,17 +46,19 @@ public abstract class RetryingMessageTaskTest<T, R> extends AbstractMessageTaskT
EthProtocolManagerTestUtil.createPeer(ethProtocolManager); EthProtocolManagerTestUtil.createPeer(ethProtocolManager);
// Execute task and wait for response // Execute task and wait for response
final AtomicBoolean done = new AtomicBoolean(false);
final T requestedData = generateDataToBeRequested(); final T requestedData = generateDataToBeRequested();
final EthTask<R> task = createTask(requestedData); final EthTask<T> task = createTask(requestedData);
final CompletableFuture<R> future = task.run(); final CompletableFuture<T> future = task.run();
respondingPeer.respondTimes(responder, 20);
future.whenComplete( // Respond max times
(result, error) -> { respondingPeer.respondTimes(responder, maxRetries);
done.compareAndSet(false, true); assertThat(future.isDone()).isFalse();
});
// Next retry should fail
assertThat(done).isFalse(); respondingPeer.respond(responder);
assertThat(future.isDone()).isTrue();
assertThat(future.isCompletedExceptionally()).isTrue();
assertThatThrownBy(future::get).hasCauseInstanceOf(MaxRetriesReachedException.class);
} }
@Test @Test
@ -52,16 +67,10 @@ public abstract class RetryingMessageTaskTest<T, R> extends AbstractMessageTaskT
// Setup data to be requested // Setup data to be requested
final T requestedData = generateDataToBeRequested(); final T requestedData = generateDataToBeRequested();
// Execute task and wait for response final EthTask<T> task = createTask(requestedData);
final AtomicBoolean done = new AtomicBoolean(false); final CompletableFuture<T> future = task.run();
final EthTask<R> task = createTask(requestedData);
final CompletableFuture<R> future = task.run(); assertThat(future.isDone()).isFalse();
future.whenComplete(
(result, error) -> {
done.compareAndSet(false, true);
});
assertThat(done).isFalse();
} }
@Test @Test
@ -71,17 +80,10 @@ public abstract class RetryingMessageTaskTest<T, R> extends AbstractMessageTaskT
final T requestedData = generateDataToBeRequested(); final T requestedData = generateDataToBeRequested();
// Execute task and wait for response // Execute task and wait for response
final AtomicBoolean done = new AtomicBoolean(false); final EthTask<T> task = createTask(requestedData);
final AtomicReference<R> actualResult = new AtomicReference<>(); final CompletableFuture<T> future = task.run();
final EthTask<R> task = createTask(requestedData);
final CompletableFuture<R> future = task.run(); assertThat(future.isDone()).isFalse();
future.whenComplete(
(result, error) -> {
actualResult.set(result);
done.compareAndSet(false, true);
});
assertThat(done).isFalse();
// Setup a peer // Setup a peer
final Responder responder = RespondingEthPeer.blockchainResponder(blockchain); final Responder responder = RespondingEthPeer.blockchainResponder(blockchain);
@ -89,7 +91,7 @@ public abstract class RetryingMessageTaskTest<T, R> extends AbstractMessageTaskT
EthProtocolManagerTestUtil.createPeer(ethProtocolManager); EthProtocolManagerTestUtil.createPeer(ethProtocolManager);
respondingPeer.respondWhile(responder, () -> !future.isDone()); respondingPeer.respondWhile(responder, () -> !future.isDone());
assertResultMatchesExpectation(requestedData, actualResult.get(), respondingPeer.getEthPeer()); assertResultMatchesExpectation(requestedData, future.get(), respondingPeer.getEthPeer());
} }
@Test @Test
@ -101,26 +103,17 @@ public abstract class RetryingMessageTaskTest<T, R> extends AbstractMessageTaskT
EthProtocolManagerTestUtil.createPeer(ethProtocolManager); EthProtocolManagerTestUtil.createPeer(ethProtocolManager);
final T requestedData = generateDataToBeRequested(); final T requestedData = generateDataToBeRequested();
// Execute task and wait for response final EthTask<T> task = createTask(requestedData);
final AtomicBoolean done = new AtomicBoolean(false); final CompletableFuture<T> future = task.run();
final AtomicReference<R> actualResult = new AtomicReference<>();
final EthTask<R> task = createTask(requestedData); assertThat(future.isDone()).isFalse();
final CompletableFuture<R> future = task.run();
future.whenComplete(
(result, error) -> {
actualResult.set(result);
done.compareAndSet(false, true);
});
assertThat(done).isFalse();
respondingPeer.respondWhile(responder, () -> !future.isDone()); respondingPeer.respondWhile(responder, () -> !future.isDone());
assertResultMatchesExpectation(requestedData, actualResult.get(), respondingPeer.getEthPeer()); assertResultMatchesExpectation(requestedData, future.get(), respondingPeer.getEthPeer());
} }
@Test @Test
public void doesNotCompleteWhenPeersSendEmptyResponses() public void failsWhenPeersSendEmptyResponses() throws ExecutionException, InterruptedException {
throws ExecutionException, InterruptedException {
// Setup a unresponsive peer // Setup a unresponsive peer
final Responder responder = RespondingEthPeer.emptyResponder(); final Responder responder = RespondingEthPeer.emptyResponder();
final RespondingEthPeer respondingPeer = final RespondingEthPeer respondingPeer =
@ -129,15 +122,20 @@ public abstract class RetryingMessageTaskTest<T, R> extends AbstractMessageTaskT
// Setup data to be requested // Setup data to be requested
final T requestedData = generateDataToBeRequested(); final T requestedData = generateDataToBeRequested();
// Execute task and wait for response // Setup and run task
final AtomicBoolean done = new AtomicBoolean(false); final EthTask<T> task = createTask(requestedData);
final EthTask<R> task = createTask(requestedData); final CompletableFuture<T> future = task.run();
final CompletableFuture<R> future = task.run();
respondingPeer.respondTimes(responder, 20);
future.whenComplete(
(response, error) -> {
done.compareAndSet(false, true);
});
assertThat(future.isDone()).isFalse(); assertThat(future.isDone()).isFalse();
// Respond max times
respondingPeer.respondTimes(responder, maxRetries);
assertThat(future.isDone()).isFalse();
// Next retry should fail
respondingPeer.respond(responder);
assertThat(future.isDone()).isTrue();
assertThat(future.isCompletedExceptionally()).isTrue();
assertThatThrownBy(future::get).hasCauseInstanceOf(MaxRetriesReachedException.class);
} }
} }

@ -1,14 +0,0 @@
package tech.pegasys.pantheon.ethereum.eth.manager.ethtaskutils;
import static org.assertj.core.api.Assertions.assertThat;
import tech.pegasys.pantheon.ethereum.eth.manager.EthPeer;
public abstract class RetryingMessageTaskWithResultsTest<T> extends RetryingMessageTaskTest<T, T> {
@Override
protected void assertResultMatchesExpectation(
final T requestedData, final T response, final EthPeer respondingPeer) {
assertThat(response).isEqualTo(requestedData);
}
}

@ -4,13 +4,13 @@ import tech.pegasys.pantheon.ethereum.core.Block;
import tech.pegasys.pantheon.ethereum.core.BlockBody; import tech.pegasys.pantheon.ethereum.core.BlockBody;
import tech.pegasys.pantheon.ethereum.core.BlockHeader; import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.eth.manager.EthTask; import tech.pegasys.pantheon.ethereum.eth.manager.EthTask;
import tech.pegasys.pantheon.ethereum.eth.manager.ethtaskutils.RetryingMessageTaskWithResultsTest; import tech.pegasys.pantheon.ethereum.eth.manager.ethtaskutils.RetryingMessageTaskTest;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class CompleteBlocksTaskTest extends RetryingMessageTaskWithResultsTest<List<Block>> { public class CompleteBlocksTaskTest extends RetryingMessageTaskTest<List<Block>> {
@Override @Override
protected List<Block> generateDataToBeRequested() { protected List<Block> generateDataToBeRequested() {
@ -28,6 +28,7 @@ public class CompleteBlocksTaskTest extends RetryingMessageTaskWithResultsTest<L
protected EthTask<List<Block>> createTask(final List<Block> requestedData) { protected EthTask<List<Block>> createTask(final List<Block> requestedData) {
final List<BlockHeader> headersToComplete = final List<BlockHeader> headersToComplete =
requestedData.stream().map(Block::getHeader).collect(Collectors.toList()); requestedData.stream().map(Block::getHeader).collect(Collectors.toList());
return CompleteBlocksTask.forHeaders(protocolSchedule, ethContext, headersToComplete); return CompleteBlocksTask.forHeaders(
protocolSchedule, ethContext, headersToComplete, maxRetries);
} }
} }

@ -2,13 +2,12 @@ package tech.pegasys.pantheon.ethereum.eth.sync.tasks;
import tech.pegasys.pantheon.ethereum.core.BlockHeader; import tech.pegasys.pantheon.ethereum.core.BlockHeader;
import tech.pegasys.pantheon.ethereum.eth.manager.EthTask; import tech.pegasys.pantheon.ethereum.eth.manager.EthTask;
import tech.pegasys.pantheon.ethereum.eth.manager.ethtaskutils.RetryingMessageTaskWithResultsTest; import tech.pegasys.pantheon.ethereum.eth.manager.ethtaskutils.RetryingMessageTaskTest;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class DownloadHeaderSequenceTaskTest public class DownloadHeaderSequenceTaskTest extends RetryingMessageTaskTest<List<BlockHeader>> {
extends RetryingMessageTaskWithResultsTest<List<BlockHeader>> {
@Override @Override
protected List<BlockHeader> generateDataToBeRequested() { protected List<BlockHeader> generateDataToBeRequested() {
@ -26,6 +25,11 @@ public class DownloadHeaderSequenceTaskTest
final BlockHeader lastHeader = requestedData.get(requestedData.size() - 1); final BlockHeader lastHeader = requestedData.get(requestedData.size() - 1);
final BlockHeader referenceHeader = blockchain.getBlockHeader(lastHeader.getNumber() + 1).get(); final BlockHeader referenceHeader = blockchain.getBlockHeader(lastHeader.getNumber() + 1).get();
return DownloadHeaderSequenceTask.endingAtHeader( return DownloadHeaderSequenceTask.endingAtHeader(
protocolSchedule, protocolContext, ethContext, referenceHeader, requestedData.size()); protocolSchedule,
protocolContext,
ethContext,
referenceHeader,
requestedData.size(),
maxRetries);
} }
} }

@ -14,7 +14,7 @@ import tech.pegasys.pantheon.ethereum.eth.manager.EthProtocolManagerTestUtil;
import tech.pegasys.pantheon.ethereum.eth.manager.EthTask; import tech.pegasys.pantheon.ethereum.eth.manager.EthTask;
import tech.pegasys.pantheon.ethereum.eth.manager.RespondingEthPeer; import tech.pegasys.pantheon.ethereum.eth.manager.RespondingEthPeer;
import tech.pegasys.pantheon.ethereum.eth.manager.RespondingEthPeer.Responder; import tech.pegasys.pantheon.ethereum.eth.manager.RespondingEthPeer.Responder;
import tech.pegasys.pantheon.ethereum.eth.manager.ethtaskutils.RetryingMessageTaskTest; import tech.pegasys.pantheon.ethereum.eth.manager.ethtaskutils.AbstractMessageTaskTest;
import tech.pegasys.pantheon.ethereum.eth.messages.EthPV62; import tech.pegasys.pantheon.ethereum.eth.messages.EthPV62;
import tech.pegasys.pantheon.ethereum.eth.messages.EthPV63; import tech.pegasys.pantheon.ethereum.eth.messages.EthPV63;
import tech.pegasys.pantheon.ethereum.eth.sync.tasks.exceptions.InvalidBlockException; import tech.pegasys.pantheon.ethereum.eth.sync.tasks.exceptions.InvalidBlockException;
@ -38,7 +38,7 @@ import java.util.stream.LongStream;
import org.junit.Test; import org.junit.Test;
public class PipelinedImportChainSegmentTaskTest public class PipelinedImportChainSegmentTaskTest
extends RetryingMessageTaskTest<List<Block>, List<Block>> { extends AbstractMessageTaskTest<List<Block>, List<Block>> {
@Override @Override
protected List<Block> generateDataToBeRequested() { protected List<Block> generateDataToBeRequested() {

Loading…
Cancel
Save