private void processFinishedGroups(List<RemoteReplicaGroup> remoteReplicaGroups,
      Set<Integer> groupsAddedToExchangeMetadatResponse) {

    /*for each data node we are caching the first metadata responses received for remote replica groups.
     this will be used in tests only.
     */
    remoteReplicaGroups.stream()
        .filter(g -> !groupsAddedToExchangeMetadatResponse.contains(g.id) && g.isDone()
            && g.getExchangeMetadataResponseList() != null)
        .forEach(g -> {
          exchangeMetadataResponsesInEachCycle.computeIfAbsent(g.getRemoteDataNode(), k -> new ArrayList<>())
              .addAll(g.getExchangeMetadataResponseList());
          groupsAddedToExchangeMetadatResponse.add(g.id);
        });

    // print logs for groups which have error
    remoteReplicaGroups.stream()
        .filter(g -> g.isDone() && g.getException() != null)
        .forEach(g -> logger.error("Remote node: {} Thread name: {} RemoteReplicaGroup {} has exception {}",
            g.getRemoteDataNode(), threadName, g.getRemoteReplicaInfos(), g.getException()));
  }
Computes the exchangeMetaDataResponse for each cycle
Prints logs for remote replica groups which have errors

@param remoteReplicaGroups remoteReplica groups
@param groupsAddedToExchangeMetadatResponse set of group ids for which exchange metadata is added to {@link #exchangeMetadataResponsesInEachCycle}
ambry-replication/src/main/java/com/github/ambry/replication/ReplicaThread.java