|  | @@ -9,16 +9,19 @@ package org.elasticsearch.xpack.core.ml.annotations;
 | 
	
		
			
				|  |  |  import org.elasticsearch.ResourceAlreadyExistsException;
 | 
	
		
			
				|  |  |  import org.elasticsearch.Version;
 | 
	
		
			
				|  |  |  import org.elasticsearch.action.ActionListener;
 | 
	
		
			
				|  |  | +import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
 | 
	
		
			
				|  |  | +import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
 | 
	
		
			
				|  |  |  import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
 | 
	
		
			
				|  |  |  import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
 | 
	
		
			
				|  |  |  import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
 | 
	
		
			
				|  |  |  import org.elasticsearch.action.support.master.AcknowledgedResponse;
 | 
	
		
			
				|  |  | -import org.elasticsearch.action.support.master.MasterNodeRequest;
 | 
	
		
			
				|  |  |  import org.elasticsearch.client.Client;
 | 
	
		
			
				|  |  | +import org.elasticsearch.client.Requests;
 | 
	
		
			
				|  |  |  import org.elasticsearch.cluster.ClusterState;
 | 
	
		
			
				|  |  |  import org.elasticsearch.cluster.metadata.IndexAbstraction;
 | 
	
		
			
				|  |  |  import org.elasticsearch.cluster.metadata.IndexMetadata;
 | 
	
		
			
				|  |  |  import org.elasticsearch.common.settings.Settings;
 | 
	
		
			
				|  |  | +import org.elasticsearch.common.unit.TimeValue;
 | 
	
		
			
				|  |  |  import org.elasticsearch.xpack.core.ml.MlMetadata;
 | 
	
		
			
				|  |  |  import org.elasticsearch.xpack.core.ml.job.persistence.ElasticsearchMappings;
 | 
	
		
			
				|  |  |  import org.elasticsearch.xpack.core.ml.utils.ExceptionsHelper;
 | 
	
	
		
			
				|  | @@ -40,20 +43,42 @@ public class AnnotationIndex {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /**
 | 
	
		
			
				|  |  |       * Create the .ml-annotations-6 index with correct mappings if it does not already exist. This index is read and written by the UI
 | 
	
		
			
				|  |  | -     * results views, so needs to exist when there might be ML results to view.
 | 
	
		
			
				|  |  | +     * results views, so needs to exist when there might be ML results to view.  This method also waits for the index to be ready to search
 | 
	
		
			
				|  |  | +     * before it returns.
 | 
	
		
			
				|  |  |       */
 | 
	
		
			
				|  |  | -    public static void createAnnotationsIndexIfNecessary(Client client, ClusterState state, final ActionListener<Boolean> finalListener) {
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        final ActionListener<Boolean> checkMappingsListener = ActionListener.wrap(success -> {
 | 
	
		
			
				|  |  | -            ElasticsearchMappings.addDocMappingIfMissing(
 | 
	
		
			
				|  |  | -                WRITE_ALIAS_NAME,
 | 
	
		
			
				|  |  | -                AnnotationIndex::annotationsMapping,
 | 
	
		
			
				|  |  | -                client,
 | 
	
		
			
				|  |  | -                state,
 | 
	
		
			
				|  |  | -                MasterNodeRequest.DEFAULT_MASTER_NODE_TIMEOUT,
 | 
	
		
			
				|  |  | -                finalListener);
 | 
	
		
			
				|  |  | +    public static void createAnnotationsIndexIfNecessaryAndWaitForYellow(Client client, ClusterState state, TimeValue masterNodeTimeout,
 | 
	
		
			
				|  |  | +                                                                         final ActionListener<Boolean> finalListener) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        final ActionListener<Boolean> annotationsIndexCreatedListener = ActionListener.wrap(success -> {
 | 
	
		
			
				|  |  | +            final ClusterHealthRequest request = Requests.clusterHealthRequest(READ_ALIAS_NAME)
 | 
	
		
			
				|  |  | +                .waitForYellowStatus()
 | 
	
		
			
				|  |  | +                .masterNodeTimeout(masterNodeTimeout);
 | 
	
		
			
				|  |  | +            executeAsyncWithOrigin(client.threadPool().getThreadContext(), ML_ORIGIN, request,
 | 
	
		
			
				|  |  | +                ActionListener.<ClusterHealthResponse>wrap(
 | 
	
		
			
				|  |  | +                    r -> finalListener.onResponse(r.isTimedOut() == false), finalListener::onFailure),
 | 
	
		
			
				|  |  | +                client.admin().cluster()::health);
 | 
	
		
			
				|  |  |          }, finalListener::onFailure);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        createAnnotationsIndexIfNecessary(client, state, masterNodeTimeout, annotationsIndexCreatedListener);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * Create the .ml-annotations-6 index with correct mappings if it does not already exist. This index is read and written by the UI
 | 
	
		
			
				|  |  | +     * results views, so needs to exist when there might be ML results to view.
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public static void createAnnotationsIndexIfNecessary(Client client, ClusterState state, TimeValue masterNodeTimeout,
 | 
	
		
			
				|  |  | +                                                         final ActionListener<Boolean> finalListener) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        final ActionListener<Boolean> checkMappingsListener = ActionListener.wrap(success ->
 | 
	
		
			
				|  |  | +                ElasticsearchMappings.addDocMappingIfMissing(
 | 
	
		
			
				|  |  | +                    WRITE_ALIAS_NAME,
 | 
	
		
			
				|  |  | +                    AnnotationIndex::annotationsMapping,
 | 
	
		
			
				|  |  | +                    client,
 | 
	
		
			
				|  |  | +                    state,
 | 
	
		
			
				|  |  | +                    masterNodeTimeout,
 | 
	
		
			
				|  |  | +                    finalListener),
 | 
	
		
			
				|  |  | +            finalListener::onFailure);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          final ActionListener<Boolean> createAliasListener = ActionListener.wrap(success -> {
 | 
	
		
			
				|  |  |              final IndicesAliasesRequest request =
 | 
	
		
			
				|  |  |                  client.admin().indices().prepareAliases()
 |