[Rollup] improve handling of failures on first search (#35269)

Improve error handling in the Indexer if an exception occurs during the very 1st retrieval (query execution)
This commit is contained in:
Hendrik Muhs 2018-11-08 16:28:48 +01:00 committed by GitHub
parent 07a69a528b
commit 433469d4d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 98 additions and 3 deletions

View File

@ -151,8 +151,13 @@ public abstract class AsyncTwoPhaseIndexer<JobPosition, JobStats extends Indexer
if (state.compareAndSet(IndexerState.STARTED, IndexerState.INDEXING)) { if (state.compareAndSet(IndexerState.STARTED, IndexerState.INDEXING)) {
// fire off the search. Note this is async, the method will return from here // fire off the search. Note this is async, the method will return from here
executor.execute(() -> doNextSearch(buildSearchRequest(), executor.execute(() -> {
ActionListener.wrap(this::onSearchResponse, exc -> finishWithFailure(exc)))); try {
doNextSearch(buildSearchRequest(), ActionListener.wrap(this::onSearchResponse, exc -> finishWithFailure(exc)));
} catch (Exception e) {
finishWithFailure(e);
}
});
logger.debug("Beginning to index [" + getJobId() + "], state: [" + currentState + "]"); logger.debug("Beginning to index [" + getJobId() + "], state: [" + currentState + "]");
return true; return true;
} else { } else {

View File

@ -110,6 +110,78 @@ public class AsyncTwoPhaseIndexerTests extends ESTestCase {
} }
private class MockIndexerThrowsFirstSearch extends AsyncTwoPhaseIndexer<Integer, MockJobStats> {
// test the execution order
private int step;
protected MockIndexerThrowsFirstSearch(Executor executor, AtomicReference<IndexerState> initialState, Integer initialPosition) {
super(executor, initialState, initialPosition, new MockJobStats());
}
@Override
protected String getJobId() {
return "mock";
}
@Override
protected IterationResult<Integer> doProcess(SearchResponse searchResponse) {
fail("should not be called");
return null;
}
@Override
protected SearchRequest buildSearchRequest() {
assertThat(step, equalTo(1));
++step;
return null;
}
@Override
protected void onStartJob(long now) {
assertThat(step, equalTo(0));
++step;
}
@Override
protected void doNextSearch(SearchRequest request, ActionListener<SearchResponse> nextPhase) {
throw new RuntimeException("Failed to build search request");
}
@Override
protected void doNextBulk(BulkRequest request, ActionListener<BulkResponse> nextPhase) {
fail("should not be called");
}
@Override
protected void doSaveState(IndexerState state, Integer position, Runnable next) {
assertThat(step, equalTo(2));
++step;
next.run();
}
@Override
protected void onFailure(Exception exc) {
assertThat(step, equalTo(3));
++step;
isFinished.set(true);
}
@Override
protected void onFinish() {
fail("should not be called");
}
@Override
protected void onAbort() {
fail("should not be called");
}
public int getStep() {
return step;
}
}
private static class MockJobStats extends IndexerJobStats { private static class MockJobStats extends IndexerJobStats {
@Override @Override
@ -121,7 +193,7 @@ public class AsyncTwoPhaseIndexerTests extends ESTestCase {
public void testStateMachine() throws InterruptedException { public void testStateMachine() throws InterruptedException {
AtomicReference<IndexerState> state = new AtomicReference<>(IndexerState.STOPPED); AtomicReference<IndexerState> state = new AtomicReference<>(IndexerState.STOPPED);
final ExecutorService executor = Executors.newFixedThreadPool(1); final ExecutorService executor = Executors.newFixedThreadPool(1);
isFinished.set(false);
try { try {
MockIndexer indexer = new MockIndexer(executor, state, 2); MockIndexer indexer = new MockIndexer(executor, state, 2);
@ -140,4 +212,22 @@ public class AsyncTwoPhaseIndexerTests extends ESTestCase {
executor.shutdownNow(); executor.shutdownNow();
} }
} }
public void testStateMachineBrokenSearch() throws InterruptedException {
AtomicReference<IndexerState> state = new AtomicReference<>(IndexerState.STOPPED);
final ExecutorService executor = Executors.newFixedThreadPool(1);
isFinished.set(false);
try {
MockIndexerThrowsFirstSearch indexer = new MockIndexerThrowsFirstSearch(executor, state, 2);
indexer.start();
assertThat(indexer.getState(), equalTo(IndexerState.STARTED));
assertTrue(indexer.maybeTriggerAsyncJob(System.currentTimeMillis()));
assertTrue(ESTestCase.awaitBusy(() -> isFinished.get()));
assertThat(indexer.getStep(), equalTo(4));
} finally {
executor.shutdownNow();
}
}
} }