Skip to content

Commit 3b5038b

Browse files
Implement Eventually Consistent Mock Repository for SnapshotResiliencyTests (#40893) (#44570)
* Add eventually consistent mock repository for reproducing and testing AWS S3 blob store behavior * Relates #38941
1 parent 8445c41 commit 3b5038b

File tree

4 files changed

+560
-17
lines changed

4 files changed

+560
-17
lines changed

server/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -166,13 +166,13 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
166166

167167
private static final int BUFFER_SIZE = 4096;
168168

169-
private static final String SNAPSHOT_PREFIX = "snap-";
169+
public static final String SNAPSHOT_PREFIX = "snap-";
170170

171-
private static final String SNAPSHOT_CODEC = "snapshot";
171+
public static final String SNAPSHOT_CODEC = "snapshot";
172172

173173
private static final String INDEX_FILE_PREFIX = "index-";
174174

175-
private static final String INDEX_LATEST_BLOB = "index.latest";
175+
public static final String INDEX_LATEST_BLOB = "index.latest";
176176

177177
private static final String TESTS_FILE = "tests-";
178178

@@ -210,7 +210,7 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
210210

211211
private ChecksumBlobStoreFormat<IndexMetaData> indexMetaDataFormat;
212212

213-
private ChecksumBlobStoreFormat<SnapshotInfo> snapshotFormat;
213+
protected ChecksumBlobStoreFormat<SnapshotInfo> snapshotFormat;
214214

215215
private final boolean readOnly;
216216

server/src/test/java/org/elasticsearch/snapshots/SnapshotResiliencyTests.java

+37-13
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@
108108
import org.elasticsearch.cluster.service.ClusterApplierService;
109109
import org.elasticsearch.cluster.service.ClusterService;
110110
import org.elasticsearch.cluster.service.MasterService;
111+
import org.elasticsearch.common.Nullable;
111112
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
112113
import org.elasticsearch.common.network.NetworkModule;
113114
import org.elasticsearch.common.settings.ClusterSettings;
@@ -152,6 +153,7 @@
152153
import org.elasticsearch.search.SearchService;
153154
import org.elasticsearch.search.builder.SearchSourceBuilder;
154155
import org.elasticsearch.search.fetch.FetchPhase;
156+
import org.elasticsearch.snapshots.mockstore.MockEventuallyConsistentRepository;
155157
import org.elasticsearch.test.ESTestCase;
156158
import org.elasticsearch.test.disruption.DisruptableMockTransport;
157159
import org.elasticsearch.test.disruption.NetworkDisruption;
@@ -203,16 +205,28 @@ public class SnapshotResiliencyTests extends ESTestCase {
203205

204206
private Path tempDir;
205207

208+
/**
209+
* Context shared by all the node's {@link Repository} instances if the eventually consistent blobstore is to be used.
210+
* {@code null} if not using the eventually consistent blobstore.
211+
*/
212+
@Nullable private MockEventuallyConsistentRepository.Context blobStoreContext;
213+
206214
@Before
207215
public void createServices() {
208216
tempDir = createTempDir();
217+
if (randomBoolean()) {
218+
blobStoreContext = new MockEventuallyConsistentRepository.Context();
219+
}
209220
deterministicTaskQueue =
210221
new DeterministicTaskQueue(Settings.builder().put(NODE_NAME_SETTING.getKey(), "shared").build(), random());
211222
}
212223

213224
@After
214225
public void verifyReposThenStopServices() {
215226
try {
227+
if (blobStoreContext != null) {
228+
blobStoreContext.forceConsistent();
229+
}
216230
BlobStoreTestUtil.assertConsistency(
217231
(BlobStoreRepository) testClusterNodes.randomMasterNodeSafe().repositoriesService.repository("repo"),
218232
Runnable::run);
@@ -900,19 +914,7 @@ public void onFailure(final Exception e) {
900914
final IndexNameExpressionResolver indexNameExpressionResolver = new IndexNameExpressionResolver();
901915
repositoriesService = new RepositoriesService(
902916
settings, clusterService, transportService,
903-
Collections.singletonMap(FsRepository.TYPE, metaData -> {
904-
final Repository repository = new FsRepository(metaData, environment, xContentRegistry(), threadPool) {
905-
@Override
906-
protected void assertSnapshotOrGenericThread() {
907-
// eliminate thread name check as we create repo in the test thread
908-
}
909-
};
910-
repository.start();
911-
return repository;
912-
}
913-
),
914-
emptyMap(),
915-
threadPool
917+
Collections.singletonMap(FsRepository.TYPE, getRepoFactory(environment)), emptyMap(), threadPool
916918
);
917919
snapshotsService =
918920
new SnapshotsService(settings, clusterService, indexNameExpressionResolver, repositoriesService, threadPool);
@@ -1093,6 +1095,28 @@ searchTransportService, new SearchPhaseController(searchService::createReduceCon
10931095
client.initialize(actions, () -> clusterService.localNode().getId(), transportService.getRemoteClusterService());
10941096
}
10951097

1098+
private Repository.Factory getRepoFactory(Environment environment) {
1099+
// Run half the tests with the eventually consistent repository
1100+
if (blobStoreContext == null) {
1101+
return metaData -> {
1102+
final Repository repository = new FsRepository(metaData, environment, xContentRegistry(), threadPool) {
1103+
@Override
1104+
protected void assertSnapshotOrGenericThread() {
1105+
// eliminate thread name check as we create repo in the test thread
1106+
}
1107+
};
1108+
repository.start();
1109+
return repository;
1110+
};
1111+
} else {
1112+
return metaData -> {
1113+
final Repository repository = new MockEventuallyConsistentRepository(
1114+
metaData, environment, xContentRegistry(), deterministicTaskQueue.getThreadPool(), blobStoreContext);
1115+
repository.start();
1116+
return repository;
1117+
};
1118+
}
1119+
}
10961120
public void restart() {
10971121
testClusterNodes.disconnectNode(this);
10981122
final ClusterState oldState = this.clusterService.state();

0 commit comments

Comments
 (0)