@Override
  protected void doExecute(
      final MultiPercolateRequest request, final ActionListener<MultiPercolateResponse> listener) {
    final ClusterState clusterState = clusterService.state();
    clusterState.blocks().globalBlockedRaiseException(ClusterBlockLevel.READ);

    final List<Object> percolateRequests = new ArrayList<>(request.requests().size());
    // Can have a mixture of percolate requests. (normal percolate requests & percolate existing
    // doc),
    // so we need to keep track for what percolate request we had a get request
    final IntArrayList getRequestSlots = new IntArrayList();
    List<GetRequest> existingDocsRequests = new ArrayList<>();
    for (int slot = 0; slot < request.requests().size(); slot++) {
      PercolateRequest percolateRequest = request.requests().get(slot);
      percolateRequest.startTime = System.currentTimeMillis();
      percolateRequests.add(percolateRequest);
      if (percolateRequest.getRequest() != null) {
        existingDocsRequests.add(percolateRequest.getRequest());
        getRequestSlots.add(slot);
      }
    }

    if (!existingDocsRequests.isEmpty()) {
      final MultiGetRequest multiGetRequest = new MultiGetRequest(request);
      for (GetRequest getRequest : existingDocsRequests) {
        multiGetRequest.add(
            new MultiGetRequest.Item(getRequest.index(), getRequest.type(), getRequest.id())
                .routing(getRequest.routing()));
      }

      multiGetAction.execute(
          multiGetRequest,
          new ActionListener<MultiGetResponse>() {

            @Override
            public void onResponse(MultiGetResponse multiGetItemResponses) {
              for (int i = 0; i < multiGetItemResponses.getResponses().length; i++) {
                MultiGetItemResponse itemResponse = multiGetItemResponses.getResponses()[i];
                int slot = getRequestSlots.get(i);
                if (!itemResponse.isFailed()) {
                  GetResponse getResponse = itemResponse.getResponse();
                  if (getResponse.isExists()) {
                    PercolateRequest originalRequest =
                        (PercolateRequest) percolateRequests.get(slot);
                    percolateRequests.set(
                        slot,
                        new PercolateRequest(originalRequest, getResponse.getSourceAsBytesRef()));
                  } else {
                    logger.trace("mpercolate existing doc, item[{}] doesn't exist", slot);
                    percolateRequests.set(
                        slot,
                        new DocumentMissingException(
                            null, getResponse.getType(), getResponse.getId()));
                  }
                } else {
                  logger.trace(
                      "mpercolate existing doc, item[{}] failure {}",
                      slot,
                      itemResponse.getFailure());
                  percolateRequests.set(slot, itemResponse.getFailure());
                }
              }
              new ASyncAction(request, percolateRequests, listener, clusterState).run();
            }

            @Override
            public void onFailure(Throwable e) {
              listener.onFailure(e);
            }
          });
    } else {
      new ASyncAction(request, percolateRequests, listener, clusterState).run();
    }
  }