-
Notifications
You must be signed in to change notification settings - Fork 813
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
7311: add peertask foundation code #7628
base: main
Are you sure you want to change the base?
7311: add peertask foundation code #7628
Conversation
Signed-off-by: Matilda Clerke <[email protected]>
Signed-off-by: Matilda Clerke <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left some comments
import org.slf4j.LoggerFactory; | ||
|
||
/** "Manages" the EthPeers for the PeerTaskExecutor */ | ||
public class PeerManager { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the code a bit I think that PeerManager could just be an interface with one method: getPeer()
Different implementations could give us the behaviour that we are looking for, like how many retries, retry the same peer/other peers.
This would also allow us to pick peers when they are needed, e.g. to make sure that these peers don't have too many open requests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An interface to allow easy swapping of different implementations is a fine, but I'm not sure how we'd implement retries in the peer manager... the peer manager is completely separated from the PeerTasks and has no idea what tasks are being executed and whether they succeed or fail.
|
||
public <T> PeerTaskExecutorResult<T> execute(final PeerTask<T> peerTask) { | ||
PeerTaskExecutorResult<T> executorResult; | ||
int triesRemaining = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this could be handled by the peer manager
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand how that would work. The peer manager doesn't have any connection to the tasks being run
} | ||
} while (--triesRemaining > 0 | ||
&& executorResult.getResponseCode() != PeerTaskExecutorResponseCode.SUCCESS | ||
&& executorResult.getResponseCode() != PeerTaskExecutorResponseCode.PEER_DISCONNECTED |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you don't care about which peer is used you would try with another peer ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is in the executeAgainstPeer()
method, so at this point in the code we do care which peer is used. If the calling code doesn't care which peer a task is run against, it can call the execute()
method instead, which contains the logic for peer switching.
} while (--triesRemaining > 0 | ||
&& executorResult.getResponseCode() != PeerTaskExecutorResponseCode.SUCCESS | ||
&& executorResult.getResponseCode() != PeerTaskExecutorResponseCode.PEER_DISCONNECTED | ||
&& sleepBetweenRetries(WAIT_TIME_BEFORE_RETRY[triesRemaining])); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could be handled by the peer manager
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how exactly. The peer manager doesn't (and shouldn't) know anything about whether a peer is requested for a retry or for a first attempt.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to sleep between retries?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't strictly need to sleep between retries, but if a peer is unable to respond before timing out, it's likely just busy or we're experiencing network issues, so waiting a moment before retrying can allow things a chance to improve.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding was this is a refactor so I think we should match the existing behaviour. Not sure how the retry timing worked before, possibly it is 1 second? https://github.com/hyperledger/besu/blob/main/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/AbstractRetryingPeerTask.java#L154
If we can later improve the peering performance with different timeouts that would be a good experiment to test out once the refactor is stable.
Instead of Thread.sleep, is there a reason not to use ethScheduler.scheduleFutureTask as before? I think we will lose the ethScheduler metrics if we just use vanilla CompleteableFutures
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of Thread.sleep, is there a reason not to use ethScheduler.scheduleFutureTask as before?
Mainly because this particular method shouldn't be concerned with scheduling tasks. Its singular concern is to implement task execution with optional retries.
In addition, methods in the EthSchedule class seem to operate on either Runnables or EthTasks, which really doesn't combine well with the entirely different paradigm at play with PeerTasks and the PeerTaskExecutor. A better solution would be to ensure we have similar metrics set up in the PeerTaskExecutor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mainly because this particular method shouldn't be concerned with scheduling tasks.
If we use it, EthScheduler would be the one concerned with scheduling tasks IMO. Anyway isn't this an implementation detail: implementing the retries with a wait time in the PeerTaskExecutor is equivalent to scheduling a future task with a wait time isn't it?
I think we need to maintain the metrics as they are, that's quite a big loss in functionality otherwise. Would much rather we use EthScheduler since a number of maintainers are trying to centralise thread execution here so we can reuse the metrics and testing support in a consistent way across Besu.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, I'll see if I can do a bit of rework to utilise EthScheduler to capture some metrics.
} | ||
} | ||
|
||
private static boolean isPeerUnused( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be handled by the peer manager
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These methods are here because they are used in the predicate specifically to request peers for the peer task executor. They may not be applicable to all calls to peerManager.getPeer
.
They certainly could be moved to PeerManager, but that more tightly couples the peer manager to this one specific use case. Maintaining separation is what gives and maintains the simplicity of this code, as compared with the old system.
return !usedEthPeers.contains(ethPeer); | ||
} | ||
|
||
private static boolean isPeerHeightHighEnough(final EthPeer ethPeer, final long requiredHeight) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be handled by the peer manager
return ethPeer.chainState().getEstimatedHeight() >= requiredHeight; | ||
} | ||
|
||
private static boolean isPeerProtocolSuitable(final EthPeer ethPeer, final String protocol) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be handled by the peer manager
.../src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerTaskRequestSender.java
Outdated
Show resolved
Hide resolved
(boolean streamClosed, MessageData message, EthPeer peer) -> { | ||
responseMessageDataFuture.complete(message); | ||
}); | ||
return responseMessageDataFuture.get(timeoutMs, TimeUnit.MILLISECONDS); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like that!
Signed-off-by: Matilda Clerke <[email protected]>
Signed-off-by: Matilda Clerke <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ended up making quite a few comments as I went through.
TL;DR: No major objections. The way peers are selected needs some more consideration IMO as it seems a bit spread out across the classes.
/** "Manages" the EthPeers for the PeerTaskExecutor */ | ||
public interface PeerManager { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I liked @jframe's suggestion of PeerSelector since it makes its role clearer IMO.
"Manager" hides a potential multitude of responsibilities (and may tempt people to expand on them in the future).
This might be a stretch, but I think it also dovetails nicely with the concept of "transaction selection" where we choose transactions to execute from a pool.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, I agree. PeerSelector more accurately describes the classes responsibility.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the descriptive comments!
public interface PeerManager { | ||
|
||
/** | ||
* Gets the highest reputation peer matching the supplies filter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels like an implementation detail of the DefaultPeerManager...if the interface requires it to be highest reputation should we rename the method to getHighestReputationPeer
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...or move the comment to DefaultPeerManager
...or merge PeerManager with DefaultPeerManager :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's fair. Originally, there was no interface, so the javadoc described the implementation. I'll reword it
|
||
// use a synchronized map to ensure the map is never modified by multiple threads at once | ||
private final Map<PeerId, EthPeer> ethPeersByPeerId = | ||
Collections.synchronizedMap(new HashMap<>()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ConcurrentHashMap is a more modern and performant equivalent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, never use that one before.
|
||
@Override | ||
public EthPeer getPeer(final Predicate<EthPeer> filter) throws NoAvailablePeerException { | ||
LOG.trace("Getting peer from pool of {} peers", ethPeersByPeerId.size()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LOG.trace("Getting peer from pool of {} peers", ethPeersByPeerId.size()); | |
LOG.trace("Finding peer from pool of {} peers", ethPeersByPeerId.size()); |
|
||
/** Manages the execution of PeerTasks, respecting their PeerTaskBehavior */ | ||
public class PeerTaskExecutor { | ||
private static final long[] WAIT_TIME_BEFORE_RETRY = {0, 20000, 5000}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the thinking behind these retry timings? Warrants a comment I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea was to have a progressive back-off timer on retries. As discussed elsewhere, it would be better to stay consistent with the existing implemention (appears to be a 1 second delay), and make this sort of change later, so I'll change that shortly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
progressive back-off timer on retries
0 -> 20 seconds -> 5 seconds? Should it {0, 5000, 20000};
instead?
but yeh, think we should avoid changing any functionality as much as possible (or do it in both old and new if it's a known improvement)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, it was using the retry countdown to select it. First retry, the countdown would be 2, so WAIT_TIME_BEFORE_RETRY[triesRemaining]
would be 5000
} while (--triesRemaining > 0 | ||
&& executorResult.getResponseCode() != PeerTaskExecutorResponseCode.SUCCESS | ||
&& executorResult.getResponseCode() != PeerTaskExecutorResponseCode.PEER_DISCONNECTED | ||
&& sleepBetweenRetries(WAIT_TIME_BEFORE_RETRY[triesRemaining])); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to sleep between retries?
throw new RuntimeException(e); | ||
} | ||
}); | ||
Thread.sleep(500); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need this in the test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because of the nature of RequestSender, the actual test has to be performed on another thread than the test thread. The code below this line must be execute after RequestSender has submitted it's callback method to responseStream.then. Since it doesn't make sense to expose a signal just for testing, we can just add a small delay to ensure the code is executed in the required sequence. Obviously, for production code, this is a dirty hack and proper inter-thread signalling should be used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice coverage!
} | ||
|
||
@Test | ||
public void testGetPeer() throws NoAvailablePeerException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would be nice to test the exceptional case too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call, I'll add another test
Signed-off-by: Matilda Clerke <[email protected]>
Signed-off-by: Matilda Clerke <[email protected]>
Signed-off-by: Matilda Clerke <[email protected]>
Signed-off-by: Matilda Clerke <[email protected]>
Signed-off-by: Matilda Clerke <[email protected]>
…ch old implementation Signed-off-by: Matilda Clerke <[email protected]>
Signed-off-by: Matilda Clerke <[email protected]>
Signed-off-by: Matilda Clerke <[email protected]>
Signed-off-by: Matilda Clerke <[email protected]>
* | ||
* @return the SubProtocol used for this PeerTask | ||
*/ | ||
String getSubProtocol(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can the stronger SubProtocol
type be used here? Not sure how much of hassle it is practice though
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Iirc I looked at using the SubProtocol type and decided against it. I can't remember why, so I'll take another look.
* | ||
* @return the Collection of behaviors this task is expected to exhibit in the PeetTaskExecutor | ||
*/ | ||
Collection<PeerTaskBehavior> getPeerTaskBehaviors(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Think a set would make more sense, don't think it makes sense to have duplicate behaviours
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep true
|
||
public enum PeerTaskBehavior { | ||
RETRY_WITH_SAME_PEER, | ||
RETRY_WITH_OTHER_PEERS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this also include the non-retry single try behaviour if the intent is to include all the current peer behaviours? Otherwise, like @siladu mentioned, this should be the PeerTaskRetryBehavior
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Non-retry behaviour is just the absence of retry behaviours.
I wanted to leave this as PeerTaskBehavior to allow for other behaviors to be added later. They aren't strictly just for describing desired retry behavior, but there aren't currently any other behaviors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think if the goal is for the code to be more readable, I would go with more specific/descriptive naming and let whoever may (or may not) add more behaviours in later worry about the appropriate name then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, that makes sense
public <T> PeerTaskExecutorResult<T> execute(final PeerTask<T> peerTask) { | ||
PeerTaskExecutorResult<T> executorResult; | ||
int triesRemaining = | ||
peerTask.getPeerTaskBehaviors().contains(PeerTaskBehavior.RETRY_WITH_OTHER_PEERS) ? 3 : 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can a constant be created for the number of retries. Also may want to make the number of retries configurable as I think we use a different number of retries in various places.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added constants for now. I think I'll hold off on making them configurable until I get a better idea of how/when/why different values are used.
(candidatePeer) -> | ||
isPeerUnused(candidatePeer, usedEthPeers) | ||
&& (protocolSpecSupplier.get().isPoS() | ||
|| isPeerHeightHighEnough( | ||
candidatePeer, peerTask.getRequiredBlockNumber())) | ||
&& isPeerProtocolSuitable(candidatePeer, peerTask.getSubProtocol())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree with @siladu here; the peer selection would more cleanly belong in the PeerSelector
MessageData requestMessageData = peerTask.getRequestMessage(); | ||
PeerTaskExecutorResult<T> executorResult; | ||
int triesRemaining = | ||
peerTask.getPeerTaskBehaviors().contains(PeerTaskBehavior.RETRY_WITH_SAME_PEER) ? 3 : 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bit unsure about this behaviour. If you specify RETRY_WITH_SAME_PEER and RETRY_WITH_OTHER_PEERS what would happen? It would select a peer and try with that peer up to 3 times and if that fails repeat the process up to 3 times. So it could potentially be trying the request up to 9 times?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's correct
return !usedEthPeers.contains(ethPeer); | ||
} | ||
|
||
private static boolean isPeerHeightHighEnough(final EthPeer ethPeer, final long requiredHeight) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method doesn't need to be static
return ethPeer.chainState().getEstimatedHeight() >= requiredHeight; | ||
} | ||
|
||
private static boolean isPeerProtocolSuitable(final EthPeer ethPeer, final String protocol) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method doesn't need to be static
} | ||
} | ||
|
||
private static boolean isPeerUnused( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method doesn't need to be static
|
||
import java.util.Optional; | ||
|
||
public class PeerTaskExecutorResult<T> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be simpler as a record
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It means losing the nice Optional wrapping to guarantee the optional result is always set, but yeah in general it should be a record.
Signed-off-by: Matilda Clerke <[email protected]>
Signed-off-by: Matilda Clerke <[email protected]>
Signed-off-by: Matilda Clerke <[email protected]>
Signed-off-by: Matilda Clerke <[email protected]>
Signed-off-by: Matilda Clerke <[email protected]>
Signed-off-by: Matilda Clerke <[email protected]>
Signed-off-by: Matilda Clerke <[email protected]>
public EthPeer getPeer(final Predicate<EthPeer> filter) { | ||
return streamBestPeers().filter(filter).findFirst().orElseThrow(NoAvailablePeersException::new); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than add a duplicate implementation, could we just use the existing bestPeerMatchingCriteria or refactor to suit both needs?
My preference would be Optional<EthPeer>
instead of an exception for normal control flow, and reusing the existing impl would mean we less risk/testing for the existing clients of that method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I'll update
...m/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerTaskExecutor.java
Outdated
Show resolved
Hide resolved
|
||
public static final int RETRIES_WITH_SAME_PEER = 3; | ||
public static final int RETRIES_WITH_OTHER_PEER = 3; | ||
public static final int NO_RETRIES = 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I think the benefit is succinctness/readability/encapsulation. If I want to understand what PeerTaskRetryBehavior.RETRIES_WITH_SAME_PEER actually does then I need to understand this extra mapping within PeerTaskExecutor, whereas if the enum contains a numberOfRetries field, this should be more obvious IMO.
Signed-off-by: Matilda Clerke <[email protected]>
…isting peer selection behavior in EthPeers Signed-off-by: Matilda Clerke <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After discussion and further review, it sounds like this code is bypassing some existing functionality in EthPeers. That might be fine if done intentionally, but I'd like to understand why it is fine to skip it.
For example, I think it is missing an equivalent to EthPeer.hasAvailableRequestCapacity
.
Also EthPeer.executePeerRequest
has some logic around actualMinBlockNumber and maintains a synchronized Collection<PendingPeerRequest> pendingRequests
which also has associated metrics - is there an equivalent to these in the new system? Maybe they are superfluous?
Without a good understanding of the old system, in particular EthPeers, it is hard to understand from the new system what is being bypassed, and whether it is intentional or something that was missed. I will have to defer to you @Matilda-Clerke to point these kind of changes out, or maybe for @pinges to spot them.
Signed-off-by: Matilda Clerke <[email protected]>
We definitely need as many eyes on these changes as we can get. I think all that's really missing at the moment is the in-flight requests metric mentioned above. |
ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthPeers.java
Outdated
Show resolved
Hide resolved
...m/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerTaskExecutor.java
Outdated
Show resolved
Hide resolved
private boolean sleepBetweenRetries() { | ||
try { | ||
// sleep for 1 second to match implemented wait between retries in AbstractRetryingPeerTask | ||
Thread.sleep(1000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we just use ethContext.getScheduler().scheduleFutureTask
so we don't have to block entire thread for a retry
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's possible. In practice, this is only called on a worker thread anyway
...m/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerTaskExecutor.java
Show resolved
Hide resolved
peerTask.getPeerRequirementFilter().test(candidatePeer) | ||
&& !usedEthPeers.contains(candidatePeer)); | ||
if (peer.isEmpty()) { | ||
executorResult = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the previous code, we would have an additional wait of 5 seconds if there were no peers. Is this still needed? @pinges what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I noticed that. Seems very weird to me that we'd just sit and wait for a peer, but only for 5 seconds. Imo, we should just let the task/pipeline fail so it can be retried later.
&& !usedEthPeers.contains(candidatePeer)); | ||
if (peer.isEmpty()) { | ||
executorResult = | ||
new PeerTaskExecutorResult<>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't handle disconnecting the failed peers like the AbstractRetryingSwitchingPeerTask.refreshPeers
does in this case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, disconnecting failed peers shouldn't be done here (or in AbstractRetryingSwitchingPeerTask). It's just not one of the responsibilities of a class which is managing the sending of a request message and parsing of the response.
Optional<EthPeer> peer = | ||
peerSelector.getPeer( | ||
(candidatePeer) -> | ||
peerTask.getPeerRequirementFilter().test(candidatePeer) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How will the isSuitablePeer
check intended to be handled? Will this happen through the getPeerRequirementFilter
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, all of a tasks requirements should be included in the getPeerRequirementFilter Predicate, and any additional requirements should be added here by the PeerTaskExecutor
...m/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerTaskExecutor.java
Outdated
Show resolved
Hide resolved
Signed-off-by: Matilda Clerke <[email protected]>
…class name Signed-off-by: Matilda Clerke <[email protected]>
…or enums Signed-off-by: Matilda Clerke <[email protected]>
Signed-off-by: Matilda Clerke <[email protected]>
Signed-off-by: Matilda Clerke <[email protected]>
Signed-off-by: Matilda Clerke <[email protected]>
Is an equivalent of this logic needed too? besu/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthPeers.java Lines 268 to 275 in aac7c63
|
…xecutor Signed-off-by: Matilda Clerke <[email protected]>
@siladu As that's a requirement of the individual task, I've handled in the EthPeer filter of each PeerTask. You can see an example in https://github.com/hyperledger/besu/pull/7638/files#diff-65888fb86ed73e694cc6171b8f99c9150241acb7edc94a575a0ea83b4b91849dR111-R115 |
PR description
This PR adds the foundational code for the new peer task system. For details about how this is used, please see the spike PR proving the concept is workable.