@Override
  public void sendResult(Object oneResult) {
    if (!function.hasResult()) {
      throw new IllegalStateException(
          String.format("Cannot %s result as the Function#hasResult() is false",
              "send"));
    }
    if (serverSender != null) {
      logger.debug(
          "PartitionedRegionFunctionResultSender sending result from local node to client {}",
          oneResult);
      clientSend(oneResult, dm.getDistributionManagerId());
    } else { // P2P
      if (msg != null) {
        try {
          logger.debug("PartitionedRegionFunctionResultSender sending result from remote node {}",
              oneResult);
          msg.sendReplyForOneResult(dm, pr, time, oneResult, false,
              enableOrderedResultStreming);
        } catch (ForceReattemptException e) {
          throw new FunctionException(e);
        } catch (InterruptedException e) {
          throw new FunctionException(e);
        }
      } else {
        logger.debug(
            "PartitionedRegionFunctionResultSender adding result to ResultCollector on local node {}",
            oneResult);
        rc.addResult(dm.getDistributionManagerId(), oneResult);
        functionStatsFunctionProvider.apply(function.getId(), dm.getSystem())
            .incResultsReceived();
      }
      // incrementing result sent stats.
      functionStatsFunctionProvider.apply(function.getId(), dm.getSystem())
          .incResultsReturned();
    }
  }
ResultSender needs ResultCollector in which to add results one by one. In case of localExecution
it just adds result to the resultCollector whereas for remote cases it takes help of
PRFunctionExecutionStreamer to send results to the calling node. The results will be received in
the ResultReceiver. ResultSender will be instantiated in executeOnDatastore and set in
FunctionContext.
geode-core/src/main/java/org/apache/geode/internal/cache/execute/PartitionedRegionFunctionResultSender.java