|
30 | 30 | import java.util.Objects;
|
31 | 31 | import java.util.Set;
|
32 | 32 | import java.util.concurrent.atomic.AtomicIntegerArray;
|
| 33 | +import java.util.function.Function; |
33 | 34 | import java.util.stream.Collectors;
|
34 | 35 | import java.util.stream.IntStream;
|
35 | 36 |
|
@@ -105,47 +106,87 @@ BulkRequest getBulkRequest() {
|
105 | 106 | * If documents were dropped or failed in ingest, this method wraps the action listener that will be notified when the
|
106 | 107 | * updated bulk operation is completed. The wrapped listener combines the dropped and failed document results from the ingest
|
107 | 108 | * service with the results returned from running the remaining write operations.
|
| 109 | + * <br> |
| 110 | + * Use this method when you want the ingest time to be taken from the actual {@link BulkResponse} such as if you are wrapping |
| 111 | + * a response multiple times and wish to preserve an already calculated ingest time. |
108 | 112 | *
|
109 |
| - * @param ingestTookInMillis Time elapsed for ingestion to be passed to final result. |
110 |
| - * @param actionListener The action listener that expects the final bulk response. |
111 |
| - * @return An action listener that combines ingest failure results with the results from writing the remaining documents. |
| 113 | + * @param actionListener the listener to wrap |
| 114 | + * @return a wrapped listener that merges ingest and bulk results, or the original listener if no items were dropped/failed |
| 115 | + */ |
| 116 | + ActionListener<BulkResponse> wrapActionListenerIfNeeded(ActionListener<BulkResponse> actionListener) { |
| 117 | + if (itemResponses.isEmpty()) { |
| 118 | + return actionListener; |
| 119 | + } else { |
| 120 | + return doWrapActionListenerIfNeeded(BulkResponse::getIngestTookInMillis, actionListener); |
| 121 | + } |
| 122 | + } |
| 123 | + |
| 124 | + /** |
| 125 | + * If documents were dropped or failed in ingest, this method wraps the action listener that will be notified when the |
| 126 | + * updated bulk operation is completed. The wrapped listener combines the dropped and failed document results from the ingest |
| 127 | + * service with the results returned from running the remaining write operations. |
| 128 | + * <br> |
| 129 | + * This variant is used when the ingest time is already known and should be explicitly set in the final response, |
| 130 | + * rather than extracted from the {@link BulkResponse}. |
| 131 | + * |
| 132 | + * @param ingestTookInMillis the ingest time in milliseconds to use in the final response |
| 133 | + * @param actionListener the listener to wrap |
| 134 | + * @return a wrapped listener that merges ingest and bulk results, or the original listener if no items were dropped/failed |
112 | 135 | */
|
113 | 136 | ActionListener<BulkResponse> wrapActionListenerIfNeeded(long ingestTookInMillis, ActionListener<BulkResponse> actionListener) {
|
114 | 137 | if (itemResponses.isEmpty()) {
|
115 | 138 | return actionListener.map(
|
116 | 139 | response -> new BulkResponse(
|
117 | 140 | response.getItems(),
|
118 |
| - response.getTook().getMillis(), |
| 141 | + response.getTookInMillis(), |
119 | 142 | ingestTookInMillis,
|
120 | 143 | response.getIncrementalState()
|
121 | 144 | )
|
122 | 145 | );
|
123 | 146 | } else {
|
124 |
| - return actionListener.map(response -> { |
125 |
| - // these items are the responses from the subsequent bulk request, their 'slots' |
126 |
| - // are not correct for this response we're building |
127 |
| - final BulkItemResponse[] bulkResponses = response.getItems(); |
| 147 | + return doWrapActionListenerIfNeeded(ignoredResponse -> ingestTookInMillis, actionListener); |
| 148 | + } |
| 149 | + } |
| 150 | + |
| 151 | + /** |
| 152 | + * If documents were dropped or failed in ingest, this method wraps the action listener that will be notified when the |
| 153 | + * updated bulk operation is completed. The wrapped listener combines the dropped and failed document results from the ingest |
| 154 | + * service with the results returned from running the remaining write operations. |
| 155 | + * |
| 156 | + * @param ingestTimeProviderFunction A function to provide the ingest time taken for this response |
| 157 | + * @param actionListener The action listener that expects the final bulk response. |
| 158 | + * @return An action listener that combines ingest failure results with the results from writing the remaining documents. |
| 159 | + */ |
| 160 | + private ActionListener<BulkResponse> doWrapActionListenerIfNeeded( |
| 161 | + Function<BulkResponse, Long> ingestTimeProviderFunction, |
| 162 | + ActionListener<BulkResponse> actionListener |
| 163 | + ) { |
| 164 | + return actionListener.map(response -> { |
| 165 | + // these items are the responses from the subsequent bulk request, their 'slots' |
| 166 | + // are not correct for this response we're building |
| 167 | + final BulkItemResponse[] bulkResponses = response.getItems(); |
128 | 168 |
|
129 |
| - final BulkItemResponse[] allResponses = new BulkItemResponse[bulkResponses.length + itemResponses.size()]; |
| 169 | + final BulkItemResponse[] allResponses = new BulkItemResponse[bulkResponses.length + itemResponses.size()]; |
130 | 170 |
|
131 |
| - // the item responses are from the original request, so their slots are correct. |
132 |
| - // these are the responses for requests that failed early and were not passed on to the subsequent bulk. |
133 |
| - for (BulkItemResponse item : itemResponses) { |
134 |
| - allResponses[item.getItemId()] = item; |
135 |
| - } |
| 171 | + // the item responses are from the original request, so their slots are correct. |
| 172 | + // these are the responses for requests that failed early and were not passed on to the subsequent bulk. |
| 173 | + for (BulkItemResponse item : itemResponses) { |
| 174 | + allResponses[item.getItemId()] = item; |
| 175 | + } |
136 | 176 |
|
137 |
| - // use the original slots for the responses from the bulk |
138 |
| - for (int i = 0; i < bulkResponses.length; i++) { |
139 |
| - allResponses[originalSlots.get(i)] = bulkResponses[i]; |
140 |
| - } |
| 177 | + // use the original slots for the responses from the bulk |
| 178 | + for (int i = 0; i < bulkResponses.length; i++) { |
| 179 | + allResponses[originalSlots.get(i)] = bulkResponses[i]; |
| 180 | + } |
141 | 181 |
|
142 |
| - if (Assertions.ENABLED) { |
143 |
| - assertResponsesAreCorrect(bulkResponses, allResponses); |
144 |
| - } |
| 182 | + if (Assertions.ENABLED) { |
| 183 | + assertResponsesAreCorrect(bulkResponses, allResponses); |
| 184 | + } |
145 | 185 |
|
146 |
| - return new BulkResponse(allResponses, response.getTook().getMillis(), ingestTookInMillis, response.getIncrementalState()); |
147 |
| - }); |
148 |
| - } |
| 186 | + var ingestTookInMillis = ingestTimeProviderFunction.apply(response); |
| 187 | + |
| 188 | + return new BulkResponse(allResponses, response.getTook().getMillis(), ingestTookInMillis, response.getIncrementalState()); |
| 189 | + }); |
149 | 190 | }
|
150 | 191 |
|
151 | 192 | private void assertResponsesAreCorrect(BulkItemResponse[] bulkResponses, BulkItemResponse[] allResponses) {
|
|
0 commit comments