code: private CompletableFuture<TableBucket> getNextBucket() {
          val fromBatch = getNextBucketFromExistingBatch();
          if (fromBatch != null) {
              return CompletableFuture.completedFuture(fromBatch);
          }
  
          val canContinue = new AtomicBoolean(true);
          return Futures.loop(canContinue::get, this::fetchNextTableBuckets, canContinue::set, this.executor)
                  .thenApply(v -> getNextBucketFromExistingBatch());
      }
docs: Gets the next {@link TableBucket} in the iteration. This will either be served directly from the cached batch
  of {@link TableBucket}s or a new invocation to the underlying indexHashIterator will be performed to fetch the next
  {@link TableBucket}.