@Override public CompletableFuture<List<Map.Entry<UUID, Long>>> getNext() { return READ_RETRY .runAsync(this::getNextPageEntries, executor) .thenApply(pageEntries -> { if (pageEntries == null) { // We are done. return null; } val result = pageEntries.stream() .map(e -> Maps.immutableEntry(deserializeKey(e.getKey()), deserializeValue(e.getValue()))) .collect(Collectors.toList()); if (result.size() > 0) { // Update the last Attribute Id and also indicate that we have processed at least one iteration. this.lastProcessedId.set(result.get(result.size() - 1).getKey()); this.firstInvocation.set(false); } return result; }) .exceptionally(SegmentAttributeBTreeIndex.this::handleIndexOperationException); }
return READ_RETRY.runAsync(() -> this.index.get(serializedKeys, timeout), this.executor) .thenApply(entries -> { assert entries.size() == keys.size() : "Unexpected number of entries returned by the index search.";
/** * Executes the given Index Operation with retries. Retries are only performed in case of conditional update failures, * represented by BadOffsetException. * * @param indexOperation A Function, that, when invoked, returns a CompletableFuture which indicates when the index * operation completes. * @param timeout Timeout for the operation. * @return A CompletableFuture that will indicate when the operation completes. */ private CompletableFuture<Void> executeConditionally(Function<Duration, CompletableFuture<Long>> indexOperation, Duration timeout) { TimeoutTimer timer = new TimeoutTimer(timeout); return UPDATE_RETRY .runAsync(() -> executeConditionallyOnce(indexOperation, timer), this.executor) .exceptionally(this::handleIndexOperationException) .thenAccept(Callbacks::doNothing); }