Search in sources :

Example 26 with AsynchronousSearchActiveContext

use of org.opensearch.search.asynchronous.context.active.AsynchronousSearchActiveContext in project asynchronous-search by opensearch-project.

the class AsynchronousSearchService method freeContext.

/**
 * Attempts to find both an {@linkplain AsynchronousSearchActiveContext} and an {@linkplain AsynchronousSearchPersistenceContext}
 * and delete them. If at least one of the aforementioned objects are found and deleted successfully, the listener is invoked with
 * #true, else {@linkplain ResourceNotFoundException} is thrown.
 *
 * @param id                   asynchronous search id
 * @param asynchronousSearchContextId context id
 * @param user                 current user
 * @param listener             listener to invoke on deletion or failure to do so
 */
public void freeContext(String id, AsynchronousSearchContextId asynchronousSearchContextId, User user, ActionListener<Boolean> listener) {
    ActionListener<Boolean> exceptionTranslationWrapper = getExceptionTranslationWrapper(id, listener);
    Optional<AsynchronousSearchActiveContext> asynchronousSearchContextOptional = asynchronousSearchActiveStore.getContext(asynchronousSearchContextId);
    if (asynchronousSearchContextOptional.isPresent()) {
        logger.debug("Active context present for asynchronous search id [{}]", id);
        AsynchronousSearchActiveContext asynchronousSearchContext = asynchronousSearchContextOptional.get();
        if (isUserValid(user, asynchronousSearchContext.getUser())) {
            cancelAndFreeActiveAndPersistedContext(asynchronousSearchContext, exceptionTranslationWrapper, user);
        } else {
            exceptionTranslationWrapper.onFailure(new OpenSearchSecurityException("User doesn't have necessary roles to access the asynchronous search with id " + id, RestStatus.FORBIDDEN));
        }
    } else {
        logger.debug("Active context NOT present for asynchronous search [{}]", id);
        // asynchronous search context didn't exist so obviously we didn't delete
        // deleted persisted context if one exists. If not the listener returns acknowledged as false
        // we don't need to acquire lock if the in-memory context doesn't exist. For persistence context we have a distributed view
        // with the last writer wins policy
        logger.debug("Deleting asynchronous search [{}] from system index ", id);
        persistenceService.deleteResponse(id, user, exceptionTranslationWrapper);
    }
}
Also used : OpenSearchSecurityException(org.opensearch.OpenSearchSecurityException) AsynchronousSearchActiveContext(org.opensearch.search.asynchronous.context.active.AsynchronousSearchActiveContext)

Example 27 with AsynchronousSearchActiveContext

use of org.opensearch.search.asynchronous.context.active.AsynchronousSearchActiveContext in project asynchronous-search by opensearch-project.

the class AsynchronousSearchService method cancelAndFreeActiveAndPersistedContext.

// We are skipping user check in this while deleting from the persisted layer
// as we have already checked for user in the present active context.
private void cancelAndFreeActiveAndPersistedContext(AsynchronousSearchActiveContext asynchronousSearchContext, ActionListener<Boolean> listener, User user) {
    // if there are no context found to be cleaned up we throw a ResourceNotFoundException
    AtomicReference<Releasable> releasableReference = new AtomicReference<>(() -> {
    });
    ActionListener<Boolean> releasableListener = runAfter(listener, releasableReference.get()::close);
    GroupedActionListener<Boolean> groupedDeletionListener = new GroupedActionListener<>(wrap((responses) -> {
        if (responses.stream().anyMatch(r -> r)) {
            logger.debug("Free context for asynchronous search [{}] successful ", asynchronousSearchContext.getAsynchronousSearchId());
            releasableListener.onResponse(true);
        } else {
            logger.debug("Freeing context, asynchronous search [{}] not found ", asynchronousSearchContext.getAsynchronousSearchId());
            releasableListener.onFailure(new ResourceNotFoundException(asynchronousSearchContext.getAsynchronousSearchId()));
        }
    }, releasableListener::onFailure), 2);
    // We get a true or a ResourceNotFound from persistence layer. We want to translate it to either a true/false or any other exception
    // that should be surfaced up
    ActionListener<Boolean> translatedListener = wrap(groupedDeletionListener::onResponse, (ex) -> {
        if (ex instanceof ResourceNotFoundException) {
            groupedDeletionListener.onResponse(false);
        } else {
            logger.debug(() -> new ParameterizedMessage("Translating exception, received for asynchronous search [{}]", asynchronousSearchContext.getAsynchronousSearchId()), ex);
            groupedDeletionListener.onFailure(ex);
        }
    });
    String triggeredBy = user != null ? (" by user [" + user + "]") : "";
    String cancelTaskReason = "Delete asynchronous search [" + asynchronousSearchContext.getAsynchronousSearchId() + "] has been triggered" + triggeredBy + ". Attempting to cancel in-progress search task";
    // Intent of the lock here is to disallow ongoing migration to system index
    // as if that is underway we might end up creating a new document post a DELETE was executed
    asynchronousSearchContext.acquireContextPermitIfRequired(wrap(releasable -> {
        releasableReference.set(releasable);
        if (asynchronousSearchContext.keepOnCompletion()) {
            handleCancelTaskPermitAcquired(asynchronousSearchContext, groupedDeletionListener, cancelTaskReason);
            logger.debug("Deleting asynchronous search id [{}] from system index ", asynchronousSearchContext.getAsynchronousSearchId());
            persistenceService.deleteResponse(asynchronousSearchContext.getAsynchronousSearchId(), user, translatedListener);
        } else {
            // keep on completion is false. simply cancel task and clean up active context
            handleCancelTaskPermitAcquired(asynchronousSearchContext, wrap(r -> {
                if (r) {
                    releasableListener.onResponse(true);
                } else {
                    releasableListener.onFailure(new ResourceNotFoundException(asynchronousSearchContext.getAsynchronousSearchId()));
                }
            }, releasableListener::onFailure), cancelTaskReason);
        }
    }, exception -> {
        Throwable cause = ExceptionsHelper.unwrapCause(exception);
        if (cause instanceof TimeoutException) {
            // this should ideally not happen. This would mean we couldn't acquire permits within the timeout
            logger.debug(() -> new ParameterizedMessage("Failed to acquire permits for " + "asynchronous search id [{}] for updating context within timeout 5s", asynchronousSearchContext.getAsynchronousSearchId()), exception);
            listener.onFailure(new OpenSearchTimeoutException(asynchronousSearchContext.getAsynchronousSearchId()));
        } else {
            // best effort clean up with acknowledged as false
            if (asynchronousSearchContext.keepOnCompletion()) {
                handleCancelTaskPermitAcquisitionFailed(asynchronousSearchContext, groupedDeletionListener, cancelTaskReason, exception);
                logger.debug("Deleting asynchronous search id [{}] from system index ", asynchronousSearchContext.getAsynchronousSearchId());
                persistenceService.deleteResponse(asynchronousSearchContext.getAsynchronousSearchId(), user, translatedListener);
            } else {
                handleCancelTaskPermitAcquisitionFailed(asynchronousSearchContext, releasableListener, cancelTaskReason, exception);
            }
        }
    }), TimeValue.timeValueSeconds(5), "free context");
}
Also used : InternalAsynchronousSearchStats(org.opensearch.search.asynchronous.stats.InternalAsynchronousSearchStats) SearchStartedEvent(org.opensearch.search.asynchronous.context.state.event.SearchStartedEvent) PERSISTING(org.opensearch.search.asynchronous.context.state.AsynchronousSearchState.PERSISTING) LongSupplier(java.util.function.LongSupplier) ActionListener.runAfter(org.opensearch.action.ActionListener.runAfter) AsynchronousSearchState(org.opensearch.search.asynchronous.context.state.AsynchronousSearchState) TimeoutException(java.util.concurrent.TimeoutException) SearchDeletedEvent(org.opensearch.search.asynchronous.context.state.event.SearchDeletedEvent) GroupedActionListener(org.opensearch.action.support.GroupedActionListener) SUCCEEDED(org.opensearch.search.asynchronous.context.state.AsynchronousSearchState.SUCCEEDED) Locale(java.util.Locale) Map(java.util.Map) ActionListener(org.opensearch.action.ActionListener) SearchSuccessfulEvent(org.opensearch.search.asynchronous.context.state.event.SearchSuccessfulEvent) CancelTasksResponse(org.opensearch.action.admin.cluster.node.tasks.cancel.CancelTasksResponse) EnumSet(java.util.EnumSet) AsynchronousSearchTransition(org.opensearch.search.asynchronous.context.state.AsynchronousSearchTransition) AsynchronousSearchContext(org.opensearch.search.asynchronous.context.AsynchronousSearchContext) Client(org.opensearch.client.Client) TimeValue(org.opensearch.common.unit.TimeValue) SearchTask(org.opensearch.action.search.SearchTask) AsynchronousSearchPostProcessor(org.opensearch.search.asynchronous.processor.AsynchronousSearchPostProcessor) ExceptionsHelper(org.opensearch.ExceptionsHelper) Set(java.util.Set) Settings(org.opensearch.common.settings.Settings) SearchResponsePersistedEvent(org.opensearch.search.asynchronous.context.state.event.SearchResponsePersistedEvent) RestStatus(org.opensearch.rest.RestStatus) AsynchronousSearchPersistenceContext(org.opensearch.search.asynchronous.context.persistence.AsynchronousSearchPersistenceContext) Collectors(java.util.stream.Collectors) CLOSED(org.opensearch.search.asynchronous.context.state.AsynchronousSearchState.CLOSED) Objects(java.util.Objects) AbstractLifecycleComponent(org.opensearch.common.component.AbstractLifecycleComponent) RUNNING(org.opensearch.search.asynchronous.context.state.AsynchronousSearchState.RUNNING) Logger(org.apache.logging.log4j.Logger) SubmitAsynchronousSearchRequest(org.opensearch.search.asynchronous.request.SubmitAsynchronousSearchRequest) OpenSearchTimeoutException(org.opensearch.OpenSearchTimeoutException) Optional(java.util.Optional) AsynchronousSearchExceptionUtils(org.opensearch.search.asynchronous.utils.AsynchronousSearchExceptionUtils) ActionListener.wrap(org.opensearch.action.ActionListener.wrap) InternalAggregation(org.opensearch.search.aggregations.InternalAggregation) AsynchronousSearchActiveContext(org.opensearch.search.asynchronous.context.active.AsynchronousSearchActiveContext) AsynchronousSearchContextPermits(org.opensearch.search.asynchronous.context.permits.AsynchronousSearchContextPermits) SearchAction(org.opensearch.action.search.SearchAction) LegacyOpendistroAsynchronousSearchSettings(org.opensearch.search.asynchronous.settings.LegacyOpendistroAsynchronousSearchSettings) PERSIST_SUCCEEDED(org.opensearch.search.asynchronous.context.state.AsynchronousSearchState.PERSIST_SUCCEEDED) ThreadPool(org.opensearch.threadpool.ThreadPool) AsynchronousSearchProgressListener(org.opensearch.search.asynchronous.listener.AsynchronousSearchProgressListener) AsynchronousSearchContextId(org.opensearch.search.asynchronous.context.AsynchronousSearchContextId) AsynchronousSearchPlugin(org.opensearch.search.asynchronous.plugin.AsynchronousSearchPlugin) Releasable(org.opensearch.common.lease.Releasable) ResourceNotFoundException(org.opensearch.ResourceNotFoundException) ClusterStateListener(org.opensearch.cluster.ClusterStateListener) ParameterizedMessage(org.apache.logging.log4j.message.ParameterizedMessage) AtomicReference(java.util.concurrent.atomic.AtomicReference) Supplier(java.util.function.Supplier) UserAuthUtils.isUserValid(org.opensearch.search.asynchronous.utils.UserAuthUtils.isUserValid) NamedWriteableRegistry(org.opensearch.common.io.stream.NamedWriteableRegistry) BeginPersistEvent(org.opensearch.search.asynchronous.context.state.event.BeginPersistEvent) AsynchronousSearchStateMachine(org.opensearch.search.asynchronous.context.state.AsynchronousSearchStateMachine) UUIDs(org.opensearch.common.UUIDs) AsynchronousSearchContextEventListener(org.opensearch.search.asynchronous.listener.AsynchronousSearchContextEventListener) SearchFailureEvent(org.opensearch.search.asynchronous.context.state.event.SearchFailureEvent) AsynchronousSearchStateMachineClosedException(org.opensearch.search.asynchronous.context.state.AsynchronousSearchStateMachineClosedException) Setting(org.opensearch.common.settings.Setting) TaskId(org.opensearch.tasks.TaskId) SearchResponsePersistFailedEvent(org.opensearch.search.asynchronous.context.state.event.SearchResponsePersistFailedEvent) OpenSearchSecurityException(org.opensearch.OpenSearchSecurityException) AtomicLong(java.util.concurrent.atomic.AtomicLong) FAILED(org.opensearch.search.asynchronous.context.state.AsynchronousSearchState.FAILED) INIT(org.opensearch.search.asynchronous.context.state.AsynchronousSearchState.INIT) User(org.opensearch.commons.authuser.User) CancelTasksRequest(org.opensearch.action.admin.cluster.node.tasks.cancel.CancelTasksRequest) ClusterService(org.opensearch.cluster.service.ClusterService) PERSIST_FAILED(org.opensearch.search.asynchronous.context.state.AsynchronousSearchState.PERSIST_FAILED) AsynchronousSearchActiveStore(org.opensearch.search.asynchronous.context.active.AsynchronousSearchActiveStore) AsynchronousSearchStats(org.opensearch.search.asynchronous.stats.AsynchronousSearchStats) LogManager(org.apache.logging.log4j.LogManager) Collections(java.util.Collections) ClusterChangedEvent(org.opensearch.cluster.ClusterChangedEvent) OpenSearchTimeoutException(org.opensearch.OpenSearchTimeoutException) AtomicReference(java.util.concurrent.atomic.AtomicReference) GroupedActionListener(org.opensearch.action.support.GroupedActionListener) Releasable(org.opensearch.common.lease.Releasable) ParameterizedMessage(org.apache.logging.log4j.message.ParameterizedMessage) ResourceNotFoundException(org.opensearch.ResourceNotFoundException) TimeoutException(java.util.concurrent.TimeoutException) OpenSearchTimeoutException(org.opensearch.OpenSearchTimeoutException)

Example 28 with AsynchronousSearchActiveContext

use of org.opensearch.search.asynchronous.context.active.AsynchronousSearchActiveContext in project asynchronous-search by opensearch-project.

the class AsynchronousSearchPostProcessor method processSearchFailure.

public AsynchronousSearchResponse processSearchFailure(Exception exception, AsynchronousSearchContextId asynchronousSearchContextId) {
    final Optional<AsynchronousSearchActiveContext> asynchronousSearchContextOptional = asynchronousSearchActiveStore.getContext(asynchronousSearchContextId);
    try {
        if (asynchronousSearchContextOptional.isPresent()) {
            AsynchronousSearchActiveContext asynchronousSearchContext = asynchronousSearchContextOptional.get();
            asynchronousSearchStateMachine.trigger(new SearchFailureEvent(asynchronousSearchContext, exception));
            handlePersist(asynchronousSearchContext);
            return asynchronousSearchContext.getAsynchronousSearchResponse();
        }
        // Best effort to return the response.
        return new AsynchronousSearchResponse(AsynchronousSearchState.FAILED, -1L, -1L, null, ExceptionsHelper.convertToOpenSearchException(exception));
    } catch (AsynchronousSearchStateMachineClosedException ex) {
        // Best effort to return the response.
        return new AsynchronousSearchResponse(AsynchronousSearchState.FAILED, -1L, -1L, null, ExceptionsHelper.convertToOpenSearchException(exception));
    }
}
Also used : AsynchronousSearchResponse(org.opensearch.search.asynchronous.response.AsynchronousSearchResponse) SearchFailureEvent(org.opensearch.search.asynchronous.context.state.event.SearchFailureEvent) AsynchronousSearchActiveContext(org.opensearch.search.asynchronous.context.active.AsynchronousSearchActiveContext) AsynchronousSearchStateMachineClosedException(org.opensearch.search.asynchronous.context.state.AsynchronousSearchStateMachineClosedException)

Example 29 with AsynchronousSearchActiveContext

use of org.opensearch.search.asynchronous.context.active.AsynchronousSearchActiveContext in project asynchronous-search by opensearch-project.

the class AsynchronousSearchPostProcessor method processSearchResponse.

public AsynchronousSearchResponse processSearchResponse(SearchResponse searchResponse, AsynchronousSearchContextId asynchronousSearchContextId) {
    final Optional<AsynchronousSearchActiveContext> asynchronousSearchContextOptional = asynchronousSearchActiveStore.getContext(asynchronousSearchContextId);
    try {
        if (asynchronousSearchContextOptional.isPresent()) {
            AsynchronousSearchActiveContext asynchronousSearchContext = asynchronousSearchContextOptional.get();
            asynchronousSearchStateMachine.trigger(new SearchSuccessfulEvent(asynchronousSearchContext, searchResponse));
            handlePersist(asynchronousSearchContext);
            return asynchronousSearchContext.getAsynchronousSearchResponse();
        }
        // Best effort to return the response.
        return new AsynchronousSearchResponse(AsynchronousSearchState.SUCCEEDED, -1L, -1L, searchResponse, null);
    } catch (AsynchronousSearchStateMachineClosedException ex) {
        // Best effort to return the response.
        return new AsynchronousSearchResponse(AsynchronousSearchState.SUCCEEDED, -1L, -1L, searchResponse, null);
    }
}
Also used : AsynchronousSearchResponse(org.opensearch.search.asynchronous.response.AsynchronousSearchResponse) SearchSuccessfulEvent(org.opensearch.search.asynchronous.context.state.event.SearchSuccessfulEvent) AsynchronousSearchActiveContext(org.opensearch.search.asynchronous.context.active.AsynchronousSearchActiveContext) AsynchronousSearchStateMachineClosedException(org.opensearch.search.asynchronous.context.state.AsynchronousSearchStateMachineClosedException)

Example 30 with AsynchronousSearchActiveContext

use of org.opensearch.search.asynchronous.context.active.AsynchronousSearchActiveContext in project asynchronous-search by opensearch-project.

the class TransportSubmitAsynchronousSearchAction method doExecute.

@Override
protected void doExecute(Task task, SubmitAsynchronousSearchRequest request, ActionListener<AsynchronousSearchResponse> listener) {
    AsynchronousSearchContext asynchronousSearchContext = null;
    String userStr = threadPool.getThreadContext().getTransient(ConfigConstants.OPENSEARCH_SECURITY_USER_INFO_THREAD_CONTEXT);
    User user = User.parse(userStr);
    try {
        final long relativeStartTimeInMillis = threadPool.relativeTimeInMillis();
        asynchronousSearchContext = asynchronousSearchService.createAndStoreContext(request, relativeStartTimeInMillis, () -> searchService.aggReduceContextBuilder(request.getSearchRequest()), user);
        assert asynchronousSearchContext.getAsynchronousSearchProgressListener() != null : "missing progress listener for an active context";
        AsynchronousSearchProgressListener progressListener = asynchronousSearchContext.getAsynchronousSearchProgressListener();
        // making it effectively final for usage in anonymous class.
        AsynchronousSearchContext context = asynchronousSearchContext;
        SearchRequest searchRequest = new SearchRequest(request.getSearchRequest()) {

            @Override
            public SearchTask createTask(long id, String type, String action, TaskId parentTaskId, Map<String, String> headers) {
                AsynchronousSearchTask asynchronousSearchTask = new AsynchronousSearchTask(id, type, AsynchronousSearchTask.NAME, parentTaskId, headers, (AsynchronousSearchActiveContext) context, request, asynchronousSearchService::onCancelledFreeActiveContext);
                asynchronousSearchService.bootstrapSearch(asynchronousSearchTask, context.getContextId());
                PrioritizedActionListener<AsynchronousSearchResponse> wrappedListener = AsynchronousSearchTimeoutWrapper.wrapScheduledTimeout(threadPool, request.getWaitForCompletionTimeout(), AsynchronousSearchPlugin.OPEN_DISTRO_ASYNC_SEARCH_GENERIC_THREAD_POOL_NAME, listener, (actionListener) -> {
                    progressListener.searchProgressActionListener().removeListener(actionListener);
                    listener.onResponse(context.getAsynchronousSearchResponse());
                });
                progressListener.searchProgressActionListener().addOrExecuteListener(wrappedListener);
                return asynchronousSearchTask;
            }
        };
        // set the parent task as the submit task for cancellation on connection close
        searchRequest.setParentTask(task.taskInfo(clusterService.localNode().getId(), false).getTaskId());
        transportSearchAction.execute(searchRequest, progressListener);
    } catch (Exception e) {
        logger.error(() -> new ParameterizedMessage("Failed to submit asynchronous search request [{}]", request), e);
        if (asynchronousSearchContext != null) {
            AsynchronousSearchActiveContext asynchronousSearchActiveContext = (AsynchronousSearchActiveContext) asynchronousSearchContext;
            asynchronousSearchService.freeContext(asynchronousSearchActiveContext.getAsynchronousSearchId(), asynchronousSearchActiveContext.getContextId(), user, ActionListener.wrap((r) -> {
                logger.debug(() -> new ParameterizedMessage("Successfully cleaned up context on submit asynchronous" + " search [{}] on failure", asynchronousSearchActiveContext.getAsynchronousSearchId()), e);
                listener.onFailure(e);
            }, (ex) -> {
                logger.debug(() -> new ParameterizedMessage("Failed to cleaned up context on submit asynchronous search" + " [{}] on failure", asynchronousSearchActiveContext.getAsynchronousSearchId()), ex);
                listener.onFailure(e);
            }));
        } else {
            listener.onFailure(e);
        }
    }
}
Also used : AsynchronousSearchResponse(org.opensearch.search.asynchronous.response.AsynchronousSearchResponse) SearchRequest(org.opensearch.action.search.SearchRequest) SubmitAsynchronousSearchRequest(org.opensearch.search.asynchronous.request.SubmitAsynchronousSearchRequest) User(org.opensearch.commons.authuser.User) TaskId(org.opensearch.tasks.TaskId) AsynchronousSearchContext(org.opensearch.search.asynchronous.context.AsynchronousSearchContext) AsynchronousSearchActiveContext(org.opensearch.search.asynchronous.context.active.AsynchronousSearchActiveContext) AsynchronousSearchProgressListener(org.opensearch.search.asynchronous.listener.AsynchronousSearchProgressListener) AsynchronousSearchTask(org.opensearch.search.asynchronous.task.AsynchronousSearchTask) ParameterizedMessage(org.apache.logging.log4j.message.ParameterizedMessage) Map(java.util.Map)

Aggregations

AsynchronousSearchActiveContext (org.opensearch.search.asynchronous.context.active.AsynchronousSearchActiveContext)30 ClusterService (org.opensearch.cluster.service.ClusterService)24 NamedWriteableRegistry (org.opensearch.common.io.stream.NamedWriteableRegistry)24 AsynchronousSearchActiveStore (org.opensearch.search.asynchronous.context.active.AsynchronousSearchActiveStore)24 SubmitAsynchronousSearchRequest (org.opensearch.search.asynchronous.request.SubmitAsynchronousSearchRequest)24 InternalAsynchronousSearchStats (org.opensearch.search.asynchronous.stats.InternalAsynchronousSearchStats)23 ThreadPool (org.opensearch.threadpool.ThreadPool)23 SearchRequest (org.opensearch.action.search.SearchRequest)20 DiscoveryNode (org.opensearch.cluster.node.DiscoveryNode)20 TestThreadPool (org.opensearch.threadpool.TestThreadPool)20 TimeValue (org.opensearch.common.unit.TimeValue)19 User (org.opensearch.commons.authuser.User)16 AsynchronousSearchTask (org.opensearch.search.asynchronous.task.AsynchronousSearchTask)15 AsynchronousSearchContext (org.opensearch.search.asynchronous.context.AsynchronousSearchContext)14 CountDownLatch (java.util.concurrent.CountDownLatch)13 AsynchronousSearchProgressListener (org.opensearch.search.asynchronous.listener.AsynchronousSearchProgressListener)12 ResourceNotFoundException (org.opensearch.ResourceNotFoundException)11 AsynchronousSearchContextId (org.opensearch.search.asynchronous.context.AsynchronousSearchContextId)11 AsynchronousSearchStateMachine (org.opensearch.search.asynchronous.context.state.AsynchronousSearchStateMachine)10 SearchStartedEvent (org.opensearch.search.asynchronous.context.state.event.SearchStartedEvent)10