|
@@ -24,6 +24,7 @@ import org.apache.lucene.index.IndexableField;
|
|
|
import org.apache.lucene.index.Term;
|
|
|
import org.apache.lucene.search.TermQuery;
|
|
|
import org.apache.lucene.search.TopDocs;
|
|
|
+import org.elasticsearch.Version;
|
|
|
import org.elasticsearch.action.DocWriteResponse;
|
|
|
import org.elasticsearch.action.bulk.BulkItemResponse;
|
|
|
import org.elasticsearch.action.bulk.BulkShardRequest;
|
|
@@ -141,10 +142,80 @@ public class IndexLevelReplicationTests extends ESIndexLevelReplicationTestCase
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ public void testRetryAppendOnlyAfterRecovering() throws Exception {
|
|
|
+ try (ReplicationGroup shards = createGroup(0)) {
|
|
|
+ shards.startAll();
|
|
|
+ final IndexRequest originalRequest = new IndexRequest(index.getName(), "type").source("{}", XContentType.JSON);
|
|
|
+ originalRequest.process(Version.CURRENT, null, index.getName());
|
|
|
+ final IndexRequest retryRequest = copyIndexRequest(originalRequest);
|
|
|
+ retryRequest.onRetry();
|
|
|
+ shards.index(retryRequest);
|
|
|
+ IndexShard replica = shards.addReplica();
|
|
|
+ shards.recoverReplica(replica);
|
|
|
+ shards.assertAllEqual(1);
|
|
|
+ shards.index(originalRequest); // original append-only arrives after recovery completed
|
|
|
+ shards.assertAllEqual(1);
|
|
|
+ assertThat(replica.getMaxSeenAutoIdTimestamp(), equalTo(originalRequest.getAutoGeneratedTimestamp()));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void testAppendOnlyRecoveryThenReplication() throws Exception {
|
|
|
+ CountDownLatch indexedOnPrimary = new CountDownLatch(1);
|
|
|
+ CountDownLatch recoveryDone = new CountDownLatch(1);
|
|
|
+ try (ReplicationGroup shards = new ReplicationGroup(buildIndexMetaData(1)) {
|
|
|
+ @Override
|
|
|
+ protected EngineFactory getEngineFactory(ShardRouting routing) {
|
|
|
+ return config -> new InternalEngine(config) {
|
|
|
+ @Override
|
|
|
+ public IndexResult index(Index op) throws IOException {
|
|
|
+ IndexResult result = super.index(op);
|
|
|
+ if (op.origin() == Operation.Origin.PRIMARY) {
|
|
|
+ indexedOnPrimary.countDown();
|
|
|
+ // prevent the indexing on the primary from returning (it was added to Lucene and translog already)
|
|
|
+ // to make sure that this operation is replicated to the replica via recovery, then via replication.
|
|
|
+ try {
|
|
|
+ recoveryDone.await();
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ throw new AssertionError(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ }
|
|
|
+ }) {
|
|
|
+ shards.startAll();
|
|
|
+ Thread thread = new Thread(() -> {
|
|
|
+ IndexRequest indexRequest = new IndexRequest(index.getName(), "type").source("{}", XContentType.JSON);
|
|
|
+ try {
|
|
|
+ shards.index(indexRequest);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new AssertionError(e);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ thread.start();
|
|
|
+ IndexShard replica = shards.addReplica();
|
|
|
+ Future<Void> fut = shards.asyncRecoverReplica(replica,
|
|
|
+ (shard, node) -> new RecoveryTarget(shard, node, recoveryListener, v -> {}){
|
|
|
+ @Override
|
|
|
+ public void prepareForTranslogOperations(boolean fileBasedRecovery, int totalTranslogOps) throws IOException {
|
|
|
+ try {
|
|
|
+ indexedOnPrimary.await();
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ throw new AssertionError(e);
|
|
|
+ }
|
|
|
+ super.prepareForTranslogOperations(fileBasedRecovery, totalTranslogOps);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ fut.get();
|
|
|
+ recoveryDone.countDown();
|
|
|
+ thread.join();
|
|
|
+ shards.assertAllEqual(1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
public void testInheritMaxValidAutoIDTimestampOnRecovery() throws Exception {
|
|
|
- //TODO: Enables this test with soft-deletes once we have timestamp
|
|
|
- Settings settings = Settings.builder().put(IndexSettings.INDEX_SOFT_DELETES_SETTING.getKey(), false).build();
|
|
|
- try (ReplicationGroup shards = createGroup(0, settings)) {
|
|
|
+ try (ReplicationGroup shards = createGroup(0)) {
|
|
|
shards.startAll();
|
|
|
final IndexRequest indexRequest = new IndexRequest(index.getName(), "type").source("{}", XContentType.JSON);
|
|
|
indexRequest.onRetry(); // force an update of the timestamp
|