Skip to content

Commit 27edd44

Browse files
Noop repository update should skip verification (#76067)
It is common to do an idempotent PUT of a repo, just to ensure it is there. This commit ensures that if the change is in fact a noop change, we no longer do any repository verification, since a node having trouble (for instance running out of heap) could then mean such a no-change repo update failing. Closes #76012
1 parent ff5017b commit 27edd44

File tree

2 files changed

+16
-8
lines changed

2 files changed

+16
-8
lines changed

server/src/internalClusterTest/java/org/elasticsearch/repositories/RepositoriesServiceIT.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.elasticsearch.client.Client;
1313
import org.elasticsearch.cluster.metadata.RepositoryMetadata;
1414
import org.elasticsearch.common.settings.Settings;
15+
import org.elasticsearch.env.Environment;
1516
import org.elasticsearch.plugins.Plugin;
1617
import org.elasticsearch.repositories.fs.FsRepository;
1718
import org.elasticsearch.snapshots.mockstore.MockRepository;
@@ -81,5 +82,12 @@ public void testUpdateRepository() {
8182

8283
final Repository updatedRepository = repositoriesService.repository(repositoryName);
8384
assertThat(updatedRepository, updated ? not(sameInstance(originalRepository)) : sameInstance(originalRepository));
85+
86+
// check that a noop update does not verify. Since the new data node does not share the same `path.repo`, verification will fail if
87+
// it runs.
88+
internalCluster().startDataOnlyNode(Settings.builder().put(Environment.PATH_REPO_SETTING.getKey(), createTempDir()).build());
89+
assertAcked(
90+
client.admin().cluster().preparePutRepository(repositoryName).setType(updatedRepositoryType).setSettings(repoSettings).get()
91+
);
8492
}
8593
}

server/src/main/java/org/elasticsearch/repositories/RepositoriesService.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -147,16 +147,16 @@ public void registerRepository(final PutRepositoryRequest request, final ActionL
147147
}
148148

149149
final StepListener<AcknowledgedResponse> acknowledgementStep = new StepListener<>();
150-
final StepListener<Void> publicationStep = new StepListener<>();
150+
final StepListener<Boolean> publicationStep = new StepListener<>(); // Boolean==changed.
151151

152152
if (request.verify()) {
153153

154154
// When publication has completed (and all acks received or timed out) then verify the repository.
155155
// (if acks timed out then acknowledgementStep completes before the master processes this cluster state, hence why we have
156156
// to wait for the publication to be complete too)
157157
final StepListener<List<DiscoveryNode>> verifyStep = new StepListener<>();
158-
publicationStep.whenComplete(ignored -> acknowledgementStep.whenComplete(clusterStateUpdateResponse -> {
159-
if (clusterStateUpdateResponse.isAcknowledged()) {
158+
publicationStep.whenComplete(changed -> acknowledgementStep.whenComplete(clusterStateUpdateResponse -> {
159+
if (clusterStateUpdateResponse.isAcknowledged() && changed) {
160160
// The response was acknowledged - all nodes should know about the new repository, let's verify them
161161
verifyRepository(request.name(), verifyStep);
162162
} else {
@@ -201,10 +201,6 @@ public ClusterState execute(ClusterState currentState) {
201201
List<RepositoryMetadata> repositoriesMetadata = new ArrayList<>(repositories.repositories().size() + 1);
202202
for (RepositoryMetadata repositoryMetadata : repositories.repositories()) {
203203
if (repositoryMetadata.name().equals(newRepositoryMetadata.name())) {
204-
if (newRepositoryMetadata.equalsIgnoreGenerations(repositoryMetadata)) {
205-
// Previous version is the same as this one no update is needed.
206-
return currentState;
207-
}
208204
Repository existing = RepositoriesService.this.repositories.get(request.name());
209205
if (existing == null) {
210206
existing = RepositoriesService.this.internalRepositories.get(request.name());
@@ -213,6 +209,10 @@ public ClusterState execute(ClusterState currentState) {
213209
assert existing.getMetadata() == repositoryMetadata;
214210
final RepositoryMetadata updatedMetadata;
215211
if (canUpdateInPlace(newRepositoryMetadata, existing)) {
212+
if (repositoryMetadata.settings().equals(newRepositoryMetadata.settings())) {
213+
// Previous version is the same as this one no update is needed.
214+
return currentState;
215+
}
216216
// we're updating in place so the updated metadata must point at the same uuid and generations
217217
updatedMetadata = repositoryMetadata.withSettings(newRepositoryMetadata.settings());
218218
} else {
@@ -256,7 +256,7 @@ public void clusterStateProcessed(String source, ClusterState oldState, ClusterS
256256
logger.info("put repository [{}]", request.name());
257257
}
258258
}
259-
publicationStep.onResponse(null);
259+
publicationStep.onResponse(oldState != newState);
260260
}
261261
}
262262
);

0 commit comments

Comments
 (0)