use of com.google.appengine.api.search.OperationResult in project teammates by TEAMMATES.
the class SearchManager method putDocumentWithRetry.
/**
* Tries putting a document, handling transient errors by retrying with exponential backoff.
*
* @throws PutException if a non-transient error is encountered.
* @throws MaximumRetriesExceededException with final {@link OperationResult}'s message as final message,
* if operation fails after maximum retries.
*/
private static void putDocumentWithRetry(String indexName, final Document document) throws PutException, MaximumRetriesExceededException {
final Index index = getIndex(indexName);
/*
* The GAE Search API signals put document failure in two ways: it either
* returns a PutResponse containing an OperationResult with a non-OK StatusCode, or
* throws a PutException that also contains an embedded OperationResult.
* We handle both ways by examining the OperationResult to determine what kind of error it is. If it is
* transient, we use RetryManager to retry the operation; if it is
* non-transient, we do not retry but throw a PutException upwards instead.
*/
RM.runUntilSuccessful(new RetryableTaskThrows<PutException>("Put document") {
private OperationResult lastResult;
@Override
public void run() {
try {
PutResponse response = index.put(document);
lastResult = response.getResults().get(0);
} catch (PutException e) {
lastResult = e.getOperationResult();
}
}
@Override
public boolean isSuccessful() throws PutException {
// Update the final message to be shown if the task fails after maximum retries
finalMessage = lastResult.getMessage();
if (StatusCode.OK.equals(lastResult.getCode())) {
return true;
} else if (StatusCode.TRANSIENT_ERROR.equals(lastResult.getCode())) {
// A transient error can be retried
return false;
} else {
// A non-transient error signals that the operation should not be retried
throw new PutException(lastResult);
}
}
});
}
use of com.google.appengine.api.search.OperationResult in project teammates by TEAMMATES.
the class SearchManager method putDocumentsWithRetry.
/**
* Tries putting multiple documents, handling transient errors by retrying with exponential backoff.
*
* @throws PutException when only non-transient errors are encountered.
* @throws MaximumRetriesExceededException with list of failed {@link Document}s as final data and
* final {@link OperationResult}'s message as final message, if operation fails after maximum retries.
*/
private static void putDocumentsWithRetry(String indexName, final List<Document> documents) throws PutException, MaximumRetriesExceededException {
final Index index = getIndex(indexName);
/*
* The GAE Search API allows batch putting a List of Documents.
* Results for each document are reported via a List of OperationResults.
* We use RetryManager to retry putting a List of Documents, with each retry re-putting only
* the documents that failed in the previous retry.
* If we encounter one or more transient errors, we retry the operation.
* If all results are non-transient errors, we give up and throw a PutException upwards.
*/
RM.runUntilSuccessful(new RetryableTaskThrows<PutException>("Put documents") {
private List<Document> documentsToPut = documents;
private List<OperationResult> lastResults;
private List<String> lastIds;
@Override
public void run() throws PutException {
try {
PutResponse response = index.put(documentsToPut);
lastResults = response.getResults();
lastIds = response.getIds();
} catch (PutException e) {
lastResults = e.getResults();
lastIds = e.getIds();
}
}
@Override
public boolean isSuccessful() {
boolean hasTransientError = false;
List<Document> failedDocuments = new ArrayList<>();
for (int i = 0; i < documentsToPut.size(); i++) {
StatusCode code = lastResults.get(i).getCode();
if (!StatusCode.OK.equals(code)) {
failedDocuments.add(documentsToPut.get(i));
if (StatusCode.TRANSIENT_ERROR.equals(code)) {
hasTransientError = true;
}
}
}
// Update the list of documents to be put during the next retry
documentsToPut = failedDocuments;
// Update the final message and data to be shown if the task fails after maximum retries
finalMessage = lastResults.get(0).getMessage();
finalData = documentsToPut;
if (documentsToPut.isEmpty()) {
return true;
} else if (hasTransientError) {
// If there is at least one transient error, continue retrying
return false;
} else {
// If all errors are non-transient, do not continue retrying
throw new PutException(lastResults.get(0), lastResults, lastIds);
}
}
});
}
Aggregations