class Eth2PeerManager implements PeerLookup, PeerHandler {

  @Override
  public void onConnect(final Peer peer) {
    Eth2Peer eth2Peer = eth2PeerFactory.create(peer, rpcMethods);
    final boolean wasAdded = connectedPeerMap.putIfAbsent(peer.getId(), eth2Peer) == null;
    if (!wasAdded) {
      LOG.debug("Duplicate peer connection detected for peer {}. Ignoring peer.", peer.getId());
      return;
    }

    peer.setDisconnectRequestHandler(reason -> eth2Peer.sendGoodbye(reason.getReasonCode()));
    if (peer.connectionInitiatedLocally()) {
      eth2Peer
          .sendStatus()
          .finish(
              () -> LOG.trace("Sent status to {}", peer.getId()),
              RootCauseExceptionHandler.builder()
                  .addCatch(
                      RpcException.class,
                      err -> {
                        LOG.trace("Status message rejected by {}: {}", peer.getId(), err);
                        eth2Peer.disconnectImmediately(
                            Optional.of(DisconnectReason.REMOTE_FAULT), true);
                      })
                  .defaultCatch(
                      err -> {
                        LOG.debug("Failed to send status to {}: {}", peer.getId(), err);
                        eth2Peer.disconnectImmediately(Optional.empty(), true);
                      }));
    } else {
      ensureStatusReceived(eth2Peer);
    }

    eth2Peer.subscribeInitialStatus(
        (status) -> {
          connectSubscribers.forEach(c -> c.onConnected(eth2Peer));
          setUpPeriodicTasksForPeer(eth2Peer);
        });
  }

    Eth2PeerManager(
      final AsyncRunner asyncRunner,
      final CombinedChainDataClient combinedChainDataClient,
      final RecentChainData storageClient,
      final MetricsSystem metricsSystem,
      final Eth2PeerFactory eth2PeerFactory,
      final StatusMessageFactory statusMessageFactory,
      final MetadataMessagesFactory metadataMessagesFactory,
      final RpcEncoding rpcEncoding,
      final Duration eth2RpcPingInterval,
      final int eth2RpcOutstandingPingThreshold,
      final Duration eth2StatusUpdateInterval);

}