/** * Submits a query via the session. * * @param query The query to submit. * @param <T> The query output type. * @return A completable future to be completed with the query output. */ public <T> CompletableFuture<T> submit(Query<T> query) { if (!isOpen()) return Futures.exceptionalFuture(new IllegalStateException("session not open")); CompletableFuture<T> future = new CompletableFuture<>(); context .executor() .execute( () -> { QueryRequest request; if (query.consistency() == Query.ConsistencyLevel.CAUSAL) { request = QueryRequest.builder() .withSession(id) .withSequence(commandResponse) .withVersion(responseVersion) .withQuery(query) .build(); } else { request = QueryRequest.builder() .withSession(id) .withSequence(commandRequest) .withVersion(responseVersion) .withQuery(query) .build(); } submit(request, future); }); return future; }
/** Recursively submits a query. */ @SuppressWarnings("unchecked") private <T> CompletableFuture<T> submit(QueryRequest request, CompletableFuture<T> future) { if (!isOpen()) { future.completeExceptionally(new IllegalStateException("session not open")); return future; } long sequence = ++requestSequence; this.<QueryRequest, QueryResponse>request(request) .whenComplete( (response, error) -> { if (error == null) { // If the query consistency level is CAUSAL, we can simply complete queries in // sequential order. if (request.query().consistency() == Query.ConsistencyLevel.CAUSAL) { sequenceResponse( sequence, () -> { responseVersion = Math.max(responseVersion, response.version()); completeResponse(response, future); }); } // If the query consistency level is strong, the query must be executed // sequentially. In order to ensure responses // are received in a sequential manner, we compare the response version number with // the highest version for which // we've received a response and resubmit queries with output resulting from stale // (prior) versions. else { sequenceResponse( sequence, () -> { if (response.version() > 0 && response.version() < responseVersion) { submit(request, future); } else { responseVersion = Math.max(responseVersion, response.version()); completeResponse(response, future); } }); } } else { future.completeExceptionally(error); } }); return future; }