Code review comment: For a ExecutionException, if it's not TIMEOUT, then it's THRIFT_RPC_ERROR. I think the logic is not reasonable.

Code before review:
private RowBatch getNextInternal(Status status, Backend backend) throws TException {
long timeoutTs = System.currentTimeMillis() + timeoutMs;
RowBatch rowBatch = new RowBatch();
InternalService.PTabletKeyLookupResponse pResult = null;
try {
Preconditions.checkNotNull(shortCircuitQueryContext.serializedDescTable);
InternalService.PTabletKeyLookupRequest.Builder requestBuilder
= InternalService.PTabletKeyLookupRequest.newBuilder()
.setTabletId(tabletID)
.setDescTbl(shortCircuitQueryContext.serializedDescTable)
.setOutputExpr(shortCircuitQueryContext.serializedOutputExpr)
.setQueryOptions(shortCircuitQueryContext.serializedQueryOptions)
.setIsBinaryRow(ConnectContext.get().command == MysqlCommand.COM_STMT_EXECUTE);
if (versions != null && !versions.isEmpty()) {
requestBuilder.setVersion(versions.get(0));
}
if (shortCircuitQueryContext.cacheID != null) {
InternalService.UUID.Builder uuidBuilder = InternalService.UUID.newBuilder();
uuidBuilder.setUuidHigh(shortCircuitQueryContext.cacheID.getMostSignificantBits());
uuidBuilder.setUuidLow(shortCircuitQueryContext.cacheID.getLeastSignificantBits());
requestBuilder.setUuid(uuidBuilder);
}
addKeyTuples(requestBuilder);
while (pResult == null) {
InternalService.PTabletKeyLookupRequest request = requestBuilder.build();
Future<InternalService.PTabletKeyLookupResponse> futureResponse =
BackendServiceProxy.getInstance().fetchTabletDataAsync(backend.getBrpcAddress(), request);
long currentTs = System.currentTimeMillis();
if (currentTs >= timeoutTs) {
LOG.warn("fetch result timeout {}", backend.getBrpcAddress());
status.updateStatus(TStatusCode.INTERNAL_ERROR, "query timeout");
return null;
}
try {
pResult = futureResponse.get(timeoutTs - currentTs, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
LOG.info("future get interrupted Exception");
if (isCancel) {
status.updateStatus(TStatusCode.CANCELLED, "cancelled");
return null;
}
} catch (TimeoutException e) {
futureResponse.cancel(true);
LOG.warn("fetch result timeout {}, addr {}", timeoutTs - currentTs, backend.getBrpcAddress());
status.updateStatus(TStatusCode.INTERNAL_ERROR, "query timeout");
return null;
}
}
} catch (RpcException e) {
LOG.warn("fetch result rpc exception {}, e {}", backend.getBrpcAddress(), e);
status.updateStatus(TStatusCode.THRIFT_RPC_ERROR, e.getMessage());
SimpleScheduler.addToBlacklist(backend.getId(), e.getMessage());
return null;
} catch (ExecutionException e) {
LOG.warn("fetch result execution exception {}, addr {}", e, backend.getBrpcAddress());
if (e.getMessage().contains("time out")) {
status.updateStatus(TStatusCode.TIMEOUT, e.getMessage());
} else {
status.updateStatus(TStatusCode.THRIFT_RPC_ERROR, e.getMessage());
SimpleScheduler.addToBlacklist(backend.getId(), e.getMessage());
}
return null;
}
Status resultStatus = new Status(pResult.getStatus());
if (resultStatus.getErrorCode() != TStatusCode.OK) {
status.updateStatus(resultStatus.getErrorCode(), resultStatus.getErrorMsg());
return null;
}
if (pResult.hasEmptyBatch() && pResult.getEmptyBatch()) {
LOG.info("get empty rowbatch");
rowBatch.setEos(true);
return rowBatch;
} else if (pResult.hasRowBatch() && pResult.getRowBatch().size() > 0) {
byte[] serialResult = pResult.getRowBatch().toByteArray();
TResultBatch resultBatch = new TResultBatch();
TDeserializer deserializer = new TDeserializer(
new TCustomProtocolFactory(this.maxMsgSizeOfResultReceiver));
try {
deserializer.deserialize(resultBatch, serialResult);
} catch (TException e) {
if (e.getMessage().contains("MaxMessageSize reached")) {
throw new TException("MaxMessageSize reached, try increase max_msg_size_of_result_receiver");
} else {
throw e;
}
}
rowBatch.setBatch(resultBatch);
rowBatch.setEos(true);
return rowBatch;
}
if (isCancel) {
status.updateStatus(TStatusCode.CANCELLED, "cancelled");
}
return rowBatch;
}


Code after addressing the review:
private RowBatch getNextInternal(Status status, Backend backend) throws TException {
long timeoutTs = System.currentTimeMillis() + timeoutMs;
RowBatch rowBatch = new RowBatch();
InternalService.PTabletKeyLookupResponse pResult = null;
try {
Preconditions.checkNotNull(shortCircuitQueryContext.serializedDescTable);
InternalService.PTabletKeyLookupRequest.Builder requestBuilder
= InternalService.PTabletKeyLookupRequest.newBuilder()
.setTabletId(tabletID)
.setDescTbl(shortCircuitQueryContext.serializedDescTable)
.setOutputExpr(shortCircuitQueryContext.serializedOutputExpr)
.setQueryOptions(shortCircuitQueryContext.serializedQueryOptions)
.setIsBinaryRow(ConnectContext.get().command == MysqlCommand.COM_STMT_EXECUTE);
if (snapshotVisibleVersions != null && !snapshotVisibleVersions.isEmpty()) {
requestBuilder.setVersion(snapshotVisibleVersions.get(0));
}
if (shortCircuitQueryContext.cacheID != null) {
InternalService.UUID.Builder uuidBuilder = InternalService.UUID.newBuilder();
uuidBuilder.setUuidHigh(shortCircuitQueryContext.cacheID.getMostSignificantBits());
uuidBuilder.setUuidLow(shortCircuitQueryContext.cacheID.getLeastSignificantBits());
requestBuilder.setUuid(uuidBuilder);
}
addKeyTuples(requestBuilder);
InternalService.PTabletKeyLookupRequest request = requestBuilder.build();
Future<InternalService.PTabletKeyLookupResponse> futureResponse =
BackendServiceProxy.getInstance().fetchTabletDataAsync(backend.getBrpcAddress(), request);
long currentTs = System.currentTimeMillis();
if (currentTs >= timeoutTs) {
LOG.warn("fetch result timeout {}", backend.getBrpcAddress());
status.updateStatus(TStatusCode.INTERNAL_ERROR, "query request timeout");
return null;
}
try {
pResult = futureResponse.get(timeoutTs - currentTs, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
LOG.warn("future get interrupted Exception");
if (isCancel) {
status.updateStatus(TStatusCode.CANCELLED, "cancelled");
return null;
}
} catch (TimeoutException e) {
futureResponse.cancel(true);
LOG.warn("fetch result timeout {}, addr {}", timeoutTs - currentTs, backend.getBrpcAddress());
status.updateStatus(TStatusCode.INTERNAL_ERROR, "query fetch result timeout");
return null;
}
} catch (RpcException e) {
LOG.warn("query fetch rpc exception {}, e {}", backend.getBrpcAddress(), e);
status.updateStatus(TStatusCode.THRIFT_RPC_ERROR, e.getMessage());
SimpleScheduler.addToBlacklist(backend.getId(), e.getMessage());
return null;
} catch (ExecutionException e) {
LOG.warn("query fetch execution exception {}, addr {}", e, backend.getBrpcAddress());
if (e.getMessage().contains("time out")) {
status.updateStatus(TStatusCode.TIMEOUT, e.getMessage());
} else {
status.updateStatus(TStatusCode.THRIFT_RPC_ERROR, e.getMessage());
SimpleScheduler.addToBlacklist(backend.getId(), e.getMessage());
}
return null;
}
Status resultStatus = new Status(pResult.getStatus());
if (resultStatus.getErrorCode() != TStatusCode.OK) {
status.updateStatus(resultStatus.getErrorCode(), resultStatus.getErrorMsg());
return null;
}
if (pResult.hasEmptyBatch() && pResult.getEmptyBatch()) {
LOG.debug("get empty rowbatch");
rowBatch.setEos(true);
status.updateStatus(TStatusCode.OK, "");
return rowBatch;
} else if (pResult.hasRowBatch() && pResult.getRowBatch().size() > 0) {
byte[] serialResult = pResult.getRowBatch().toByteArray();
TResultBatch resultBatch = new TResultBatch();
TDeserializer deserializer = new TDeserializer(
new TCustomProtocolFactory(this.maxMsgSizeOfResultReceiver));
try {
deserializer.deserialize(resultBatch, serialResult);
} catch (TException e) {
if (e.getMessage().contains("MaxMessageSize reached")) {
throw new TException("MaxMessageSize reached, try increase max_msg_size_of_result_receiver");
} else {
throw e;
}
}
rowBatch.setBatch(resultBatch);
rowBatch.setEos(true);
status.updateStatus(TStatusCode.OK, "");
return rowBatch;
} else {
Preconditions.checkState(false, "No row batch or empty batch found");
}
if (isCancel) {
status.updateStatus(TStatusCode.CANCELLED, "cancelled");
}
return rowBatch;
}