Skip to content

Commit 6911227

Browse files
authored
Add ClusterStateSupplier interface + standard implementation (#115931)
1 parent 427b594 commit 6911227

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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+
import java.util.function.Function;
14+
import java.util.function.Supplier;
15+
16+
/**
17+
* Utility to access {@link ClusterState} only when it is "ready", with a fallback if it's not. The definition of "ready" is left to the
18+
* class implementations.
19+
*/
20+
public interface ClusterStateSupplier extends Supplier<Optional<ClusterState>> {
21+
default <T> T withCurrentClusterState(Function<ClusterState, T> clusterStateFunction, T fallbackIfNotReady) {
22+
var x = get();
23+
return x.map(clusterStateFunction).orElse(fallbackIfNotReady);
24+
}
25+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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

Comments
 (0)