-
Couldn't load subscription status.
- Fork 2.3k
Description
Describe the bug
_update API allows to update a document using document Id. But, in case there are concurrent updates and user has provided retry_on_conflict > 0 and refresh=true, OpenSearch will internally get the new document and re-attempt the update operation. But as the previous attempt failed, it shouldn't trigger any refresh rather refresh only when update has succeeded. Today, OpenSearch triggers refreshes for failed attempts as well. This can results 1000s of refreshes every minute in case of lot of conflicts which impacts indexing performance badly.
TransportUpdateAction triggers the client.bulk()
OpenSearch/server/src/main/java/org/opensearch/action/update/TransportUpdateAction.java
Line 279 in 1717b55
| client.bulk(toSingleItemBulkRequest(indexRequest), wrapBulkResponse(ActionListener.<IndexResponse>wrap(response -> { |
and bulk operation in case of exception also, it returns true for a single document
OpenSearch/server/src/main/java/org/opensearch/action/bulk/TransportShardBulkAction.java
Lines 569 to 581 in 1717b55
| if (opType == DocWriteRequest.OpType.UPDATE) { | |
| final UpdateRequest updateRequest = (UpdateRequest) context.getCurrent(); | |
| try { | |
| updateResult = updateHelper.prepare(updateRequest, context.getPrimary(), nowInMillisSupplier); | |
| } catch (Exception failure) { | |
| // we may fail translating a update to index or delete operation | |
| // we use index result to communicate failure while translating update request | |
| final Engine.Result result = new Engine.IndexResult(failure, updateRequest.version()); | |
| context.setRequestToExecute(updateRequest); | |
| context.markOperationAsExecuted(result); | |
| context.markAsCompleted(context.getExecutionResult()); | |
| return true; | |
| } |
This results in setting operation failure as null and AsyncAfterWriteAction triggers refresh as part of runPostReplicationActions
OpenSearch/server/src/main/java/org/opensearch/action/bulk/TransportShardBulkAction.java
Lines 522 to 535 in 1717b55
| private void finishRequest() { | |
| ActionListener.completeWith( | |
| listener, | |
| () -> new WritePrimaryResult<>( | |
| context.getBulkShardRequest(), | |
| context.buildShardResponse(), | |
| context.getLocationToSync(), | |
| null, | |
| context.getPrimary(), | |
| logger | |
| ) | |
| ); | |
| } | |
| }.run(); |
Related component
Indexing
To Reproduce
- Go to '...'
- Click on '....'
- Scroll down to '....'
- See error
Expected behavior
In case _update API is triggered with retry_on_conflict > 0 and refresh = true, it should refresh only when update has succeeded and not for failed attempts.
Additional Details
No response