| 
 | 1 | +/*  | 
 | 2 | + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one  | 
 | 3 | + * or more contributor license agreements. Licensed under the "Elastic License  | 
 | 4 | + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side  | 
 | 5 | + * Public License v 1"; you may not use this file except in compliance with, at  | 
 | 6 | + * your election, the "Elastic License 2.0", the "GNU Affero General Public  | 
 | 7 | + * License v3.0 only", or the "Server Side Public License, v 1".  | 
 | 8 | + */  | 
 | 9 | + | 
 | 10 | +package org.elasticsearch.cluster;  | 
 | 11 | + | 
 | 12 | +import java.util.Optional;  | 
 | 13 | + | 
 | 14 | +import static org.elasticsearch.gateway.GatewayService.STATE_NOT_RECOVERED_BLOCK;  | 
 | 15 | + | 
 | 16 | +/**  | 
 | 17 | + * Utility to access {@link ClusterState} only when it is "ready", where "ready" means that we received a first clusterChanged event  | 
 | 18 | + * with no global block of type {@code STATE_NOT_RECOVERED_BLOCK}  | 
 | 19 | + * This guarantees that:  | 
 | 20 | + * - the initial cluster state has been set (see  | 
 | 21 | + * {@link org.elasticsearch.cluster.service.ClusterApplierService#setInitialState(ClusterState)});  | 
 | 22 | + * - the initial recovery process has completed.  | 
 | 23 | + */  | 
 | 24 | +public class SafeClusterStateSupplier implements ClusterStateSupplier, ClusterStateListener {  | 
 | 25 | +    private volatile ClusterState currentClusterState;  | 
 | 26 | + | 
 | 27 | +    @Override  | 
 | 28 | +    public void clusterChanged(ClusterChangedEvent event) {  | 
 | 29 | +        // In this default implementation, "ready" is really "is cluster state available", which after the initial recovery it should be.  | 
 | 30 | +        // If you need a different condition, feel free to add a different implementation of ClusterStateSupplier  | 
 | 31 | +        if (isInitialized() || event.state().blocks().hasGlobalBlock(STATE_NOT_RECOVERED_BLOCK) == false) {  | 
 | 32 | +            currentClusterState = event.state();  | 
 | 33 | +        }  | 
 | 34 | +    }  | 
 | 35 | + | 
 | 36 | +    private boolean isInitialized() {  | 
 | 37 | +        return currentClusterState != null;  | 
 | 38 | +    }  | 
 | 39 | + | 
 | 40 | +    @Override  | 
 | 41 | +    public Optional<ClusterState> get() {  | 
 | 42 | +        return Optional.ofNullable(currentClusterState);  | 
 | 43 | +    }  | 
 | 44 | +}  | 
0 commit comments