private CompletableFuture<OpenScannerResponse> openScanner(int replicaId) {
    try (Scope ignored = span.makeCurrent()) {
      return conn.callerFactory.<OpenScannerResponse> single().table(tableName)
        .row(scan.getStartRow()).replicaId(replicaId).locateType(getLocateType(scan))
        .priority(scan.getPriority()).rpcTimeout(rpcTimeoutNs, TimeUnit.NANOSECONDS)
        .operationTimeout(scanTimeoutNs, TimeUnit.NANOSECONDS).pause(pauseNs, TimeUnit.NANOSECONDS)
        .pauseForServerOverloaded(pauseNsForServerOverloaded, TimeUnit.NANOSECONDS)
        .maxAttempts(maxAttempts).startLogErrorsCnt(startLogErrorsCnt)
        .setRequestAttributes(requestAttributes).action(this::callOpenScanner).call();
    }
  }
The asynchronous client scanner implementation.
<p>
Here we will call OpenScanner first and use the returned scannerId to create a
{@link AsyncScanSingleRegionRpcRetryingCaller} to do the real scan operation. The return value of
{@link AsyncScanSingleRegionRpcRetryingCaller} will tell us whether open a new scanner or finish
scan.
hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncClientScanner.java