org.elasticsearch.action.ActionListener Java Examples

The following examples show how to use org.elasticsearch.action.ActionListener. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: TransportBulkCreateIndicesAction.java    From Elasticsearch with Apache License 2.0 6 votes vote down vote up
@Override
protected void masterOperation(final BulkCreateIndicesRequest request,
                               final ClusterState state,
                               final ActionListener<BulkCreateIndicesResponse> listener) throws ElasticsearchException {

    if (request.indices().isEmpty()) {
        listener.onResponse(new BulkCreateIndicesResponse(true));
        return;
    }

    final ActionListener<ClusterStateUpdateResponse> stateUpdateListener = new ActionListener<ClusterStateUpdateResponse>() {
        @Override
        public void onResponse(ClusterStateUpdateResponse clusterStateUpdateResponse) {
                listener.onResponse(new BulkCreateIndicesResponse(true));
        }

        @Override
        public void onFailure(Throwable e) {
            listener.onFailure(e);
        }
    };
    createIndices(request, stateUpdateListener);
}
 
Example #2
Source File: TransportDeleteAction.java    From Elasticsearch with Apache License 2.0 6 votes vote down vote up
@Override
protected void doExecute(final Task task, final DeleteRequest request, final ActionListener<DeleteResponse> listener) {
    ClusterState state = clusterService.state();
    if (autoCreateIndex.shouldAutoCreate(request.index(), state)) {
        createIndexAction.execute(task, new CreateIndexRequest(request).index(request.index()).cause("auto(delete api)")
            .masterNodeTimeout(request.timeout()), new ActionListener<CreateIndexResponse>() {
            @Override
            public void onResponse(CreateIndexResponse result) {
                innerExecute(task, request, listener);
            }

            @Override
            public void onFailure(Throwable e) {
                if (ExceptionsHelper.unwrapCause(e) instanceof IndexAlreadyExistsException) {
                    // we have the index, do it
                    innerExecute(task, request, listener);
                } else {
                    listener.onFailure(e);
                }
            }
        });
    } else {
        innerExecute(task, request, listener);
    }
}
 
Example #3
Source File: TransportCreateUserAction.java    From crate with Apache License 2.0 6 votes vote down vote up
@Override
protected void masterOperation(CreateUserRequest request, ClusterState state, ActionListener<WriteUserResponse> listener) throws Exception {
    clusterService.submitStateUpdateTask("create_user [" + request.userName() + "]",
        new AckedClusterStateUpdateTask<WriteUserResponse>(Priority.URGENT, request, listener) {

            private boolean alreadyExists = false;

            @Override
            public ClusterState execute(ClusterState currentState) throws Exception {
                MetaData currentMetaData = currentState.metaData();
                MetaData.Builder mdBuilder = MetaData.builder(currentMetaData);
                alreadyExists = putUser(mdBuilder, request.userName(), request.secureHash());
                return ClusterState.builder(currentState).metaData(mdBuilder).build();
            }

            @Override
            protected WriteUserResponse newResponse(boolean acknowledged) {
                return new WriteUserResponse(acknowledged, alreadyExists);
            }
        });
}
 
Example #4
Source File: ModelManager.java    From anomaly-detection with Apache License 2.0 6 votes vote down vote up
private void processThresholdCheckpoint(
    Optional<String> thresholdCheckpoint,
    String modelId,
    String detectorId,
    double score,
    ActionListener<ThresholdingResult> listener
) {

    Optional<ModelState<ThresholdingModel>> model = thresholdCheckpoint
        .map(
            checkpoint -> AccessController
                .doPrivileged((PrivilegedAction<ThresholdingModel>) () -> gson.fromJson(checkpoint, thresholdingModelClass))
        )
        .map(threshold -> new ModelState<>(threshold, modelId, detectorId, ModelType.THRESHOLD.getName(), clock.instant()));
    if (model.isPresent()) {
        thresholds.put(modelId, model.get());
        getThresholdingResult(model.get(), score, listener);
    } else {
        throw new ResourceNotFoundException(detectorId, CommonErrorMessages.NO_CHECKPOINT_ERR_MSG + modelId);
    }
}
 
Example #5
Source File: ModelManager.java    From anomaly-detection with Apache License 2.0 6 votes vote down vote up
private void clearModelForIterator(String detectorId, Map<String, ?> models, Iterator<String> idIter, ActionListener<Void> listener) {
    if (idIter.hasNext()) {
        String modelId = idIter.next();
        if (getDetectorIdForModelId(modelId).equals(detectorId)) {
            models.remove(modelId);
            checkpointDao
                .deleteModelCheckpoint(
                    modelId,
                    ActionListener.wrap(r -> clearModelForIterator(detectorId, models, idIter, listener), listener::onFailure)
                );
        } else {
            clearModelForIterator(detectorId, models, idIter, listener);
        }
    } else {
        listener.onResponse(null);
    }
}
 
Example #6
Source File: AnomalyDetectorActionHandler.java    From anomaly-detection with Apache License 2.0 6 votes vote down vote up
/**
 * Get detector job for update/delete AD job.
 * If AD job exist, will return error message; otherwise, execute function.
 *
 * @param clusterService ES cluster service
 * @param client ES node client
 * @param detectorId detector identifier
 * @param channel ES rest channel
 * @param function AD function
 */
public void getDetectorJob(
    ClusterService clusterService,
    NodeClient client,
    String detectorId,
    RestChannel channel,
    AnomalyDetectorFunction function
) {
    if (clusterService.state().metadata().indices().containsKey(ANOMALY_DETECTOR_JOB_INDEX)) {
        GetRequest request = new GetRequest(ANOMALY_DETECTOR_JOB_INDEX).id(detectorId);
        client.get(request, ActionListener.wrap(response -> onGetAdJobResponseForWrite(response, channel, function), exception -> {
            logger.error("Fail to get anomaly detector job: " + detectorId, exception);
            try {
                channel.sendResponse(new BytesRestResponse(channel, exception));
            } catch (IOException e) {
                logger.error("Fail to send exception" + detectorId, e);
            }
        }));
    } else {
        function.execute();
    }
}
 
Example #7
Source File: AnomalyDetectorProfileRunnerTests.java    From anomaly-detection with Apache License 2.0 6 votes vote down vote up
public void testInitOrRunningStateTemplate(InittedEverResultStatus status, DetectorState expectedState) throws IOException,
    InterruptedException {
    setUpClientGet(true, JobStatus.ENABLED);
    setUpClientSearch(status, ErrorResultStatus.NO_ERROR);
    DetectorProfile expectedProfile = new DetectorProfile();
    expectedProfile.setState(expectedState);
    final CountDownLatch inProgressLatch = new CountDownLatch(1);

    runner.profile(detector.getDetectorId(), ActionListener.wrap(response -> {
        assertEquals(expectedProfile, response);
        inProgressLatch.countDown();
    }, exception -> {
        assertTrue("Should not reach here ", false);
        inProgressLatch.countDown();
    }), stateOnly);
    assertTrue(inProgressLatch.await(100, TimeUnit.SECONDS));
}
 
Example #8
Source File: IndexAnomalyDetectorActionHandler.java    From anomaly-detection with Apache License 2.0 6 votes vote down vote up
private void checkADNameExists(String detectorId) throws IOException {
    BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
    // src/main/resources/mappings/anomaly-detectors.json#L14
    boolQueryBuilder.must(QueryBuilders.termQuery("name.keyword", anomalyDetector.getName()));
    if (StringUtils.isNotBlank(detectorId)) {
        boolQueryBuilder.mustNot(QueryBuilders.termQuery(RestHandlerUtils._ID, detectorId));
    }
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(boolQueryBuilder).timeout(requestTimeout);
    SearchRequest searchRequest = new SearchRequest(ANOMALY_DETECTORS_INDEX).source(searchSourceBuilder);

    client
        .search(
            searchRequest,
            ActionListener
                .wrap(
                    searchResponse -> onSearchADNameResponse(searchResponse, detectorId, anomalyDetector.getName()),
                    exception -> onFailure(exception)
                )
        );
}
 
Example #9
Source File: MockInternalClusterInfoService.java    From crate with Apache License 2.0 6 votes vote down vote up
@Override
protected CountDownLatch updateNodeStats(ActionListener<NodesStatsResponse> listener) {
    return super.updateNodeStats(new ActionListener<>() {
        @Override
        public void onResponse(NodesStatsResponse nodesStatsResponse) {
            ImmutableOpenMap.Builder<String, DiskUsage> leastAvailableUsagesBuilder = ImmutableOpenMap.builder();
            ImmutableOpenMap.Builder<String, DiskUsage> mostAvailableUsagesBuilder = ImmutableOpenMap.builder();
            fillDiskUsagePerNode(
                LOGGER,
                adjustNodesStats(nodesStatsResponse.getNodes()),
                leastAvailableUsagesBuilder,
                mostAvailableUsagesBuilder
            );
            leastAvailableSpaceUsages = leastAvailableUsagesBuilder.build();
            mostAvailableSpaceUsages = mostAvailableUsagesBuilder.build();
        }

        @Override
        public void onFailure(Exception e) {
        }
    });
}
 
Example #10
Source File: NodeStatsTest.java    From crate with Apache License 2.0 6 votes vote down vote up
@Test
public void testRequestsIfRequired() throws Exception {
    List<Symbol> toCollect = new ArrayList<>();
    toCollect.add(idRef);
    toCollect.add(hostnameRef);

    when(collectPhase.toCollect()).thenReturn(toCollect);

    BatchIterator iterator = NodeStats.newInstance(
        transportNodeStatsAction,
        collectPhase,
        nodes,
        txnCtx,
        new InputFactory(getFunctions())
    );
    iterator.loadNextBatch();

    // Hostnames needs to be collected so requests need to be performed
    verify(transportNodeStatsAction).execute(eq("nodeOne"), any(NodeStatsRequest.class), any(ActionListener.class),
        eq(TimeValue.timeValueMillis(3000L)));
    verify(transportNodeStatsAction).execute(eq("nodeTwo"), any(NodeStatsRequest.class), any(ActionListener.class),
        eq(TimeValue.timeValueMillis(3000L)));
    verifyNoMoreInteractions(transportNodeStatsAction);
}
 
Example #11
Source File: ReloadRestAction.java    From elasticsearch-auth with Apache License 2.0 6 votes vote down vote up
@Override
protected void handleRequest(final RestRequest request,
        final RestChannel channel, final Client client) {

    authService.reload(new ActionListener<Void>() {
        @Override
        public void onResponse(final Void response) {
            ResponseUtil.send(request, channel, RestStatus.OK);
        }

        @Override
        public void onFailure(final Throwable e) {
            ResponseUtil.send(request, channel,
                    RestStatus.INTERNAL_SERVER_ERROR, "message",
                    "Failed to reload AuthService.");
        }
    });
}
 
Example #12
Source File: TransportCoordinateSearchAction.java    From siren-join with GNU Affero General Public License v3.0 5 votes vote down vote up
@Override
protected void doExecute(final SearchRequest request, final ActionListener<SearchResponse> listener) {
  logger.debug("{}: Execute coordinated search action", Thread.currentThread().getName());

  // A reference to the listener that will be used - can be overwritten to reference a CoordinateSearchListener
  ActionListener<SearchResponse> actionListener = listener;

  // Retrieve the singleton instance of the filterjoin cache
  FilterJoinCache cache = cacheService.getCacheInstance();

  // Parse query source
  Tuple<XContentType, Map<String, Object>> parsedSource = this.parseSource(request.source());
  if (parsedSource != null) { // can be null if this is a uri search (query parameter in extraSource)
    Map<String, Object> map = parsedSource.v2();

    // Unwrap "wrapper" queries
    WrapperQueryVisitor wrapperVisitor = new WrapperQueryVisitor(map);
    wrapperVisitor.traverse();

    // Query planning and execution of filter joins
    SourceMapVisitor mapVisitor = new SourceMapVisitor(map);
    mapVisitor.traverse();
    FilterJoinVisitor joinVisitor = new FilterJoinVisitor(client, mapVisitor.getFilterJoinTree(), cache, request);
    joinVisitor.traverse();

    // Wraps the listener with our own to inject metadata information in the response
    CoordinateSearchListener coordinateSearchListener = new CoordinateSearchListener(listener);
    coordinateSearchListener.setMetadata(joinVisitor.getMetadata());
    actionListener = coordinateSearchListener;

    // Filter joins have been replaced by a binary terms filter
    // Rebuild the query source, and delegate the execution of the search action
    request.source(this.buildSource(parsedSource.v1().xContent(), map));
  }

  // Delegate the execution of the request to the original search action
  this.searchAction.execute(request, actionListener);

  logger.debug("{}: Coordinated search action completed", Thread.currentThread().getName());
}
 
Example #13
Source File: TransportConnection.java    From heroic with Apache License 2.0 5 votes vote down vote up
@Override
public void execute(
    @NotNull IndexRequest request,
    @NotNull ActionListener<IndexResponse> listener
) {
    client.index(request, listener);
}
 
Example #14
Source File: ActionListeners.java    From crate with Apache License 2.0 5 votes vote down vote up
public static <T extends AcknowledgedResponse> ActionListener<T> waitForShards(ActionListener<T> delegate,
                                                                               ActiveShardsObserver observer,
                                                                               TimeValue timeout,
                                                                               Runnable onShardsNotAcknowledged,
                                                                               Supplier<String[]> indices) {

    return ActionListener.wrap(
        resp -> {
            if (resp.isAcknowledged()) {
                observer.waitForActiveShards(
                    indices.get(),
                    ActiveShardCount.DEFAULT,
                    timeout,
                    shardsAcknowledged -> {
                        if (!shardsAcknowledged) {
                            onShardsNotAcknowledged.run();
                        }
                        delegate.onResponse(resp);
                    },
                    delegate::onFailure
                );
            } else {
                delegate.onResponse(resp);
            }
        },
        delegate::onFailure
    );
}
 
Example #15
Source File: TransportDeleteIndexTemplateAction.java    From crate with Apache License 2.0 5 votes vote down vote up
@Override
protected void masterOperation(final DeleteIndexTemplateRequest request, final ClusterState state, final ActionListener<AcknowledgedResponse> listener) {
    indexTemplateService.removeTemplates(new MetaDataIndexTemplateService.RemoveRequest(request.name()).masterTimeout(request.masterNodeTimeout()), new MetaDataIndexTemplateService.RemoveListener() {
        @Override
        public void onResponse(MetaDataIndexTemplateService.RemoveResponse response) {
            listener.onResponse(new AcknowledgedResponse(response.acknowledged()));
        }

        @Override
        public void onFailure(Exception e) {
            logger.debug(() -> new ParameterizedMessage("failed to delete templates [{}]", request.name()), e);
            listener.onFailure(e);
        }
    });
}
 
Example #16
Source File: AnomalyDetectorProfileRunnerTests.java    From anomaly-detection with Apache License 2.0 5 votes vote down vote up
public void testDisabledJobIndexTemplate(JobStatus status) throws IOException, InterruptedException {
    setUpClientGet(true, status);
    DetectorProfile expectedProfile = new DetectorProfile();
    expectedProfile.setState(DetectorState.DISABLED);
    final CountDownLatch inProgressLatch = new CountDownLatch(1);

    runner.profile(detector.getDetectorId(), ActionListener.wrap(response -> {
        assertEquals(expectedProfile, response);
        inProgressLatch.countDown();
    }, exception -> {
        assertTrue("Should not reach here ", false);
        inProgressLatch.countDown();
    }), stateOnly);
    assertTrue(inProgressLatch.await(100, TimeUnit.SECONDS));
}
 
Example #17
Source File: SearchActionFilter.java    From elasticsearch-dynarank with Apache License 2.0 5 votes vote down vote up
@Override
public <Request extends ActionRequest, Response extends ActionResponse> void apply(final Task task, final String action,
        final Request request, final ActionListener<Response> listener, final ActionFilterChain<Request, Response> chain) {
    if (!SearchAction.INSTANCE.name().equals(action)) {
        chain.proceed(task, action, request, listener);
        return;
    }

    final SearchRequest searchRequest = (SearchRequest) request;
    final ActionListener<Response> wrappedListener = DynamicRanker.getInstance().wrapActionListener(action, searchRequest, listener);
    chain.proceed(task, action, request, wrappedListener == null ? listener : wrappedListener);
}
 
Example #18
Source File: TransportShowTenantsAction.java    From Elasticsearch with Apache License 2.0 5 votes vote down vote up
@Override
protected void masterOperation(final ShowTenantsRequest request, ClusterState state, final ActionListener<ShowTenantsResponse> listener) {

    ShowTenantsResponse response = new ShowTenantsResponse();
    List<TenantProperty> tenantProperties = new ArrayList<TenantProperty>();
    ImmutableMap<Long, TenantProperty> allTenants = state.metaData().getTenantMetadata().tenantProperties();
    for (Long tenantId : allTenants.keySet()) {
        tenantProperties.add(allTenants.get(tenantId));
    }
    response.setTenantProperty(tenantProperties);
    listener.onResponse(response);
}
 
Example #19
Source File: PeerRecoveryTargetService.java    From crate with Apache License 2.0 5 votes vote down vote up
@Override
public void messageReceived(RecoveryFinalizeRecoveryRequest request, TransportChannel channel, Task task) throws Exception {
    try (RecoveryRef recoveryRef = onGoingRecoveries.getRecoverySafe(request.recoveryId(), request.shardId())) {
        final ActionListener<TransportResponse> listener =
            new HandledTransportAction.ChannelActionListener<>(channel, Actions.FINALIZE, request);
        recoveryRef.target().finalizeRecovery(
            request.globalCheckpoint(),
            ActionListener.wrap(
                nullVal -> listener.onResponse(TransportResponse.Empty.INSTANCE),
                listener::onFailure
            )
        );
    }
}
 
Example #20
Source File: AnomalyDetectorRunner.java    From anomaly-detection with Apache License 2.0 5 votes vote down vote up
/**
 * run anomaly detector and return anomaly result.
 *
 * @param detector  anomaly detector instance
 * @param startTime detection period start time
 * @param endTime   detection period end time
 * @param listener handle anomaly result
 * @throws IOException - if a user gives wrong query input when defining a detector
 */
public void executeDetector(AnomalyDetector detector, Instant startTime, Instant endTime, ActionListener<List<AnomalyResult>> listener)
    throws IOException {
    featureManager.getPreviewFeatures(detector, startTime.toEpochMilli(), endTime.toEpochMilli(), ActionListener.wrap(features -> {
        try {
            List<ThresholdingResult> results = modelManager.getPreviewResults(features.getProcessedFeatures());
            listener.onResponse(sample(parsePreviewResult(detector, features, results), maxPreviewResults));
        } catch (Exception e) {
            onFailure(e, listener, detector.getDetectorId());
        }
    }, e -> onFailure(e, listener, detector.getDetectorId())));

}
 
Example #21
Source File: FeatureManager.java    From anomaly-detection with Apache License 2.0 5 votes vote down vote up
private void processColdStartSamples(Optional<Entry<double[][], Integer>> samples, ActionListener<Optional<double[][]>> listener) {
    listener
        .onResponse(
            samples
                .map(
                    results -> transpose(
                        interpolator.interpolate(transpose(results.getKey()), results.getValue() * (results.getKey().length - 1) + 1)
                    )
                )
                .map(points -> batchShingle(points, shingleSize))
        );
}
 
Example #22
Source File: KerberizedClient.java    From elasticsearch-shield-kerberos-realm with Apache License 2.0 5 votes vote down vote up
private KerberosActionListener(final ActionListener inner, final Action action, final ActionRequest<ActionRequest> request,
        final GSSContext context) {
    super();
    this.inner = inner;
    this.action = action;
    this.request = request;
    this.context = context;
}
 
Example #23
Source File: SearchFeatureDao.java    From anomaly-detection with Apache License 2.0 5 votes vote down vote up
/**
 * Returns to listener features for the given time period.
 *
 * @param detector info about indices, feature query
 * @param startTime epoch milliseconds at the beginning of the period
 * @param endTime epoch milliseconds at the end of the period
 * @param listener onResponse is called with features for the given time period.
 */
public void getFeaturesForPeriod(AnomalyDetector detector, long startTime, long endTime, ActionListener<Optional<double[]>> listener) {
    SearchRequest searchRequest = createFeatureSearchRequest(detector, startTime, endTime, Optional.empty());
    client
        .search(
            searchRequest,
            ActionListener
                .wrap(response -> listener.onResponse(parseResponse(response, detector.getEnabledFeatureIds())), listener::onFailure)
        );
}
 
Example #24
Source File: ClientUtil.java    From anomaly-detection with Apache License 2.0 5 votes vote down vote up
/**
 * Send an asynchronous request and handle response with the provided listener.
 * @param <Request> ActionRequest
 * @param <Response> ActionResponse
 * @param request request body
 * @param consumer request method, functional interface to operate as a client request like client::get
 * @param listener needed to handle response
 */
public <Request extends ActionRequest, Response extends ActionResponse> void asyncRequest(
    Request request,
    BiConsumer<Request, ActionListener<Response>> consumer,
    ActionListener<Response> listener
) {
    consumer
        .accept(
            request,
            ActionListener.wrap(response -> { listener.onResponse(response); }, exception -> { listener.onFailure(exception); })
        );
}
 
Example #25
Source File: TransportFetchNodeAction.java    From crate with Apache License 2.0 5 votes vote down vote up
public void execute(String targetNode,
                    final IntObjectMap<Streamer[]> streamers,
                    final NodeFetchRequest request,
                    RamAccounting ramAccounting,
                    ActionListener<NodeFetchResponse> listener) {
    transports.sendRequest(TRANSPORT_ACTION, targetNode, request, listener,
        new ActionListenerResponseHandler<>(listener, in -> new NodeFetchResponse(in, streamers, ramAccounting)));
}
 
Example #26
Source File: TransportsTest.java    From crate with Apache License 2.0 5 votes vote down vote up
@Test
public void testOnFailureOnListenerIsCalledIfNodeIsNotInClusterState() throws Exception {
    Transports transports = new Transports(clusterService, mock(TransportService.class));
    ActionListener actionListener = mock(ActionListener.class);
    transports.sendRequest("actionName",
        "invalid", mock(TransportRequest.class), actionListener, mock(TransportResponseHandler.class));

    verify(actionListener, times(1)).onFailure(any(ConnectTransportException.class));
}
 
Example #27
Source File: TransportUpgradeAction.java    From Elasticsearch with Apache License 2.0 5 votes vote down vote up
private void updateSettings(final UpgradeResponse upgradeResponse, final ActionListener<UpgradeResponse> listener) {
    UpgradeSettingsRequest upgradeSettingsRequest = new UpgradeSettingsRequest(upgradeResponse.versions());
    upgradeSettingsAction.execute(upgradeSettingsRequest, new ActionListener<UpgradeSettingsResponse>() {
        @Override
        public void onResponse(UpgradeSettingsResponse updateSettingsResponse) {
            listener.onResponse(upgradeResponse);
        }

        @Override
        public void onFailure(Throwable e) {
            listener.onFailure(e);
        }
    });
}
 
Example #28
Source File: Search.java    From elasticsearch-rest-command with The Unlicense 5 votes vote down vote up
public void executeQueryWithNonJoin(ActionListener<SearchResponse> listener,
		int from, final int size, String[] sortFields) {

	// jobHandler,执行期才知道要排序
	for (String field : sortFields) {
		if(field != null)addSortToQuery(field);
	}
	querySearch.setSearchType(SearchType.QUERY_THEN_FETCH).setFrom(from).setSize(size);
	dumpSearchScript(querySearch, logger);
	
	querySearch.execute(listener);
}
 
Example #29
Source File: ClientUtil.java    From anomaly-detection with Apache License 2.0 5 votes vote down vote up
/**
 * Execute a transport action and handle response with the provided listener.
 * @param <Request> ActionRequest
 * @param <Response> ActionResponse
 * @param action transport action
 * @param request request body
 * @param listener needed to handle response
 */
public <Request extends ActionRequest, Response extends ActionResponse> void execute(
    ActionType<Response> action,
    Request request,
    ActionListener<Response> listener
) {
    client
        .execute(
            action,
            request,
            ActionListener.wrap(response -> { listener.onResponse(response); }, exception -> { listener.onFailure(exception); })
        );
}
 
Example #30
Source File: RecoverySourceHandler.java    From crate with Apache License 2.0 5 votes vote down vote up
static void runUnderPrimaryPermit(CancellableThreads.Interruptable runnable, String reason,
                                  IndexShard primary, CancellableThreads cancellableThreads, Logger logger) {
    cancellableThreads.execute(() -> {
        CompletableFuture<Releasable> permit = new CompletableFuture<>();
        final ActionListener<Releasable> onAcquired = new ActionListener<>() {
            @Override
            public void onResponse(Releasable releasable) {
                if (permit.complete(releasable) == false) {
                    releasable.close();
                }
            }

            @Override
            public void onFailure(Exception e) {
                permit.completeExceptionally(e);
            }
        };
        primary.acquirePrimaryOperationPermit(onAcquired, ThreadPool.Names.SAME, reason);
        try (Releasable ignored = FutureUtils.get(permit)) {
            // check that the IndexShard still has the primary authority. This needs to be checked under operation permit to prevent
            // races, as IndexShard will switch its authority only when it holds all operation permits, see IndexShard.relocated()
            if (primary.isRelocatedPrimary()) {
                throw new IndexShardRelocatedException(primary.shardId());
            }
            runnable.run();
        } finally {
            // just in case we got an exception (likely interrupted) while waiting for the get
            permit.whenComplete((r, e) -> {
                if (r != null) {
                    r.close();
                }
                if (e != null) {
                    logger.trace("suppressing exception on completion (it was already bubbled up or the operation was aborted)", e);
                }
            });
        }
    });
}