void retry(boolean fromClusterEvent, @Nullable final Throwable failure) {
      if (!fromClusterEvent) {
        // make it threaded operation so we fork on the discovery listener thread
        request.beforeLocalFork();
        request.operationThreaded(true);
        clusterService.add(
            request.timeout(),
            new TimeoutClusterStateListener() {
              @Override
              public void postAdded() {
                if (start(true)) {
                  // if we managed to start and perform the operation on the primary, we can remove
                  // this listener
                  clusterService.remove(this);
                }
              }

              @Override
              public void onClose() {
                clusterService.remove(this);
                listener.onFailure(new NodeClosedException(nodes.localNode()));
              }

              @Override
              public void clusterChanged(ClusterChangedEvent event) {
                if (start(true)) {
                  // if we managed to start and perform the operation on the primary, we can remove
                  // this listener
                  clusterService.remove(this);
                }
              }

              @Override
              public void onTimeout(TimeValue timeValue) {
                // just to be on the safe side, see if we can start it now?
                if (start(true)) {
                  clusterService.remove(this);
                  return;
                }
                clusterService.remove(this);
                Throwable listenerFailure = failure;
                if (listenerFailure == null) {
                  if (shardIt == null) {
                    listenerFailure =
                        new UnavailableShardsException(
                            null,
                            "no available shards: Timeout waiting for ["
                                + timeValue
                                + "], request: "
                                + request.toString());
                  } else {
                    listenerFailure =
                        new UnavailableShardsException(
                            shardIt.shardId(),
                            "["
                                + shardIt.size()
                                + "] shardIt, ["
                                + shardIt.sizeActive()
                                + "] active : Timeout waiting for ["
                                + timeValue
                                + "], request: "
                                + request.toString());
                  }
                }
                listener.onFailure(listenerFailure);
              }
            });
      }
    }