Currently if you provide an ANN search using the `knn` search section, the search doesn't respect cancellation. This is because ANN searches use their own Lucene data structures that aren't covered by `ExitableDirectoryReader`.

This class is forked from Lucene, and in Lucene's version we recently added fine-grained cancellation for ANN search (https://github.com/apache/lucene/pull/833). So I think we just need to fold in the changes to the Elasticsearch version.
server/src/main/java/org/elasticsearch/search/internal/ExitableDirectoryReader.java
private static final int MAX_CALLS_BEFORE_QUERY_TIMEOUT_CHECK = (1 << 4) - 1; 
        private int calls;
        private final QueryCancellation queryCancellation;
        private ExitableTermsEnum(TermsEnum termsEnum, QueryCancellation queryCancellation) {
            super(termsEnum);
            this.queryCancellation = queryCancellation;
            this.queryCancellation.checkCancelled();
        }
        private void checkAndThrowWithSampling() {
            if ((calls++ & MAX_CALLS_BEFORE_QUERY_TIMEOUT_CHECK) == 0) {
                queryCancellation.checkCancelled();
            }
        }
        @Override
        public BytesRef next() throws IOException {
            checkAndThrowWithSampling();
            return in.next();
        }
    }
    /**
     * Wrapper class for {@link PointValues} that checks for query cancellation or timeout.
     */
    static class ExitablePointValues extends PointValues {