class TrailingPeerLimiter implements BlockAddedObserver {

  public void enforceTrailingPeerLimit() {
    final TrailingPeerRequirements requirements = trailingPeerRequirementsCalculator.get();
    if (requirements.getMaxTrailingPeers() == Long.MAX_VALUE) {
      return;
    }
    final long minimumHeightToBeUpToDate = requirements.getMinimumHeightToBeUpToDate();
    final long maxTrailingPeers = requirements.getMaxTrailingPeers();
    final List<EthPeer> trailingPeers =
        ethPeers
            .streamAvailablePeers()
            .filter(peer -> peer.chainState().hasEstimatedHeight())
            .filter(peer -> peer.chainState().getEstimatedHeight() < minimumHeightToBeUpToDate)
            .sorted(BY_CHAIN_HEIGHT)
            .collect(Collectors.toList());

    while (!trailingPeers.isEmpty() && trailingPeers.size() > maxTrailingPeers) {
      final EthPeer peerToDisconnect = trailingPeers.remove(0);
      LOG.debug("Enforcing trailing peers limit by disconnecting {}", peerToDisconnect);
      peerToDisconnect.disconnect(DisconnectReason.TOO_MANY_PEERS);
    }
  }

  public  TrailingPeerLimiter(
      final EthPeers ethPeers,
      final Supplier<TrailingPeerRequirements> trailingPeerRequirementsCalculator);

}