muttakin2301/ccr_train_1000 huggingface dataset:
Code review comment: Hm this is concerning - if we start with 0 shards, the queue is forever doomed to be of size 1 which is probably quite bad for performance.

Code before review:
void start() throws TransientKinesisException {
ImmutableMap.Builder<String, ShardRecordsIterator> shardsMap = ImmutableMap.builder();
for (ShardCheckpoint checkpoint : initialCheckpoint) {
shardsMap.put(checkpoint.getShardId(), createShardIterator(kinesis, checkpoint));
}
shardIteratorsMap.set(shardsMap.build());
if (!shardIteratorsMap.get().isEmpty()) {
recordsQueue = new ArrayBlockingQueue<>(
queueCapacityPerShard * shardIteratorsMap.get().size());
startReadingShards(shardIteratorsMap.get().values());
} else {
recordsQueue = new ArrayBlockingQueue<>(1);
}
}

Line under review: }

Code after addressing the review:
void start() throws TransientKinesisException {
ImmutableMap.Builder<String, ShardRecordsIterator> shardsMap = ImmutableMap.builder();
for (ShardCheckpoint checkpoint : initialCheckpoint) {
shardsMap.put(checkpoint.getShardId(), createShardIterator(kinesis, checkpoint));
}
shardIteratorsMap.set(shardsMap.build());
if (!shardIteratorsMap.get().isEmpty()) {
recordsQueue = new ArrayBlockingQueue<>(
queueCapacityPerShard * shardIteratorsMap.get().size());
startReadingShards(shardIteratorsMap.get().values());
} else {
recordsQueue = new ArrayBlockingQueue<>(1);
}
}
Code review comment: Ok, I changed a total time of retrying to 1 minute. I believe it should be quite enough for most of the cases as a default value. 

Code before review:
private void flush(int numMax) throws InterruptedException, IOException {
int retries = spec.getRetries();
int numOutstandingRecords = producer.getOutstandingRecordsCount();
while (numOutstandingRecords > numMax && retries-- > 0) {
producer.flush();
Thread.sleep(1000);
numOutstandingRecords = producer.getOutstandingRecordsCount();
}
if (numOutstandingRecords > numMax) {
String message =
String.format(
"Number of outstanding records [%d] are greater than required [%d].",
numOutstandingRecords,
numMax);
LOG.error(message);
throw new IOException(message);
}
}

Line under review: }

Code after addressing the review:
private void flush(int numMax) throws InterruptedException, IOException {
int retries = spec.getRetries();
int numOutstandingRecords = producer.getOutstandingRecordsCount();
int retryTimeout = 1000;
while (numOutstandingRecords > numMax && retries-- > 0) {
producer.flush();
Thread.sleep(retryTimeout);
numOutstandingRecords = producer.getOutstandingRecordsCount();
retryTimeout *= 2;
}
if (numOutstandingRecords > numMax) {
String message = String.format(
"After [%d] retries, number of outstanding records [%d] is still greater than "
+ "required [%d].",
spec.getRetries(), numOutstandingRecords, numMax);
LOG.error(message);
throw new IOException(message);
}
}
Code review comment: you are right, i will fix it.

Code before review:
private boolean executeStatement(String statement, ExecutionMode executionMode) {
try {
final Optional<Operation> operation = parseCommand(statement);
operation.ifPresent(op -> callOperation(op, executionMode));
} catch (SqlExecutionException e) {
Throwable t = ExceptionUtils.getRootCause(e);
if (t instanceof InterruptedException) {
printExecutionException(t);
} else {
printExecutionException(e);
}
return false;
}
return true;
}

Line under review: }

Code after addressing the review:
private boolean executeStatement(String statement, ExecutionMode executionMode) {
try {
final Optional<Operation> operation = parseCommand(statement);
operation.ifPresent(
op -> {
final Thread thread = Thread.currentThread();
final Terminal.SignalHandler previousHandler =
terminal.handle(
Terminal.Signal.INT, (signal) -> thread.interrupt());
try {
callOperation(op, executionMode);
} finally {
terminal.handle(Terminal.Signal.INT, previousHandler);
}
});
} catch (SqlExecutionException e) {
printExecutionException(e);
return false;
}
return true;
}
Code review comment: I think this should be testing the json content rather than an exact JSON string. For some examples see: https://github.com/rest-assured/rest-assured/wiki/usage .  I think it should be more like:  .body("errorMessage", is("Resource Not Found")) .body("existingResourcesDetails.basePath",is("/"))  etc   

Code before review:
public void testJsonResourceNotFound() {
RestAssured.given().accept(ContentType.JSON)
.when().get("/not_found")
.then()
.statusCode(404)
.body(Matchers.is("{\"errorMessage\":\"Resource Not Found\",\"existingResourcesDetails\":" +
"[{\"basePath\":\"/\",\"calls\":[{\"fullPath\":\"/\",\"method\":\"GET\"}]}]}"));
}

Line under review: .body(Matchers.is("{\"errorMessage\":\"Resource Not Found\",\"existingResourcesDetails\":" +

Code after addressing the review:
public void testJsonResourceNotFound() {
RestAssured.given().accept(ContentType.JSON)
.when().get("/not_found")
.then()
.statusCode(404)
.body("errorMessage", is("Resource Not Found"))
.body("existingResourcesDetails[0].basePath", is("/"));
}
Code review comment: Hm based on that I think what you had before (hard-code "0.11.3") would be preferable.That way the test is deterministic.  Let's break it out into a constant `LOCALSTACK_VERSION` or something though.   Sorry for the churn :grimacing: 

Code before review:
private static void setupLocalstack() throws Exception {
System.setProperty(SDKGlobalConfiguration.DISABLE_CERT_CHECKING_SYSTEM_PROPERTY, "true");
System.setProperty(SDKGlobalConfiguration.AWS_CBOR_DISABLE_SYSTEM_PROPERTY, "true");
now = Instant.ofEpochMilli(Long.divideUnsigned(Instant.now().getMillis(), 1000));
localstackContainer =
new LocalStackContainer("0.11.3")
.withServices(LocalStackContainer.Service.KINESIS)
.withEnv("USE_SSL", "true")
.withStartupAttempts(3);
localstackContainer.start();
options.setAwsServiceEndpoint(
localstackContainer
.getEndpointConfiguration(LocalStackContainer.Service.KINESIS)
.getServiceEndpoint()
.replace("http", "https"));
options.setAwsKinesisRegion(
localstackContainer
.getEndpointConfiguration(LocalStackContainer.Service.KINESIS)
.getSigningRegion());
options.setAwsAccessKey(
localstackContainer.getDefaultCredentialsProvider().getCredentials().getAWSAccessKeyId());
options.setAwsSecretKey(
localstackContainer.getDefaultCredentialsProvider().getCredentials().getAWSSecretKey());
options.setNumberOfRecords(1000);
options.setNumberOfShards(1);
options.setAwsKinesisStream("beam_kinesis_test");
options.setAwsVerifyCertificate(false);
createStream(options.getAwsKinesisStream());
}

Line under review: new LocalStackContainer("0.11.3")

Code after addressing the review:
private static void setupLocalstack() {
now = Instant.ofEpochMilli(Long.divideUnsigned(now.getMillis(), 1000L));
System.setProperty(SDKGlobalConfiguration.DISABLE_CERT_CHECKING_SYSTEM_PROPERTY, "true");
System.setProperty(SDKGlobalConfiguration.AWS_CBOR_DISABLE_SYSTEM_PROPERTY, "true");
localstackContainer =
new LocalStackContainer(LOCALSTACK_VERSION)
.withServices(LocalStackContainer.Service.KINESIS)
.withEnv("USE_SSL", "true")
.withStartupAttempts(3);
localstackContainer.start();
options.setAwsServiceEndpoint(
localstackContainer
.getEndpointConfiguration(LocalStackContainer.Service.KINESIS)
.getServiceEndpoint()
.replace("http", "https"));
options.setAwsKinesisRegion(
localstackContainer
.getEndpointConfiguration(LocalStackContainer.Service.KINESIS)
.getSigningRegion());
options.setAwsAccessKey(
localstackContainer.getDefaultCredentialsProvider().getCredentials().getAWSAccessKeyId());
options.setAwsSecretKey(
localstackContainer.getDefaultCredentialsProvider().getCredentials().getAWSSecretKey());
options.setNumberOfRecords(1000);
options.setNumberOfShards(1);
options.setAwsKinesisStream("beam_kinesis_test");
options.setAwsVerifyCertificate(false);
}
Code review comment: I don't think we want this, doesn't this essentially remove batching?

Code before review:
public void processElement(ProcessContext c, BoundedWindow window) throws Exception {
for (Future<?> f = outstandingWrites.peek();
f != null && f.isDone();
f = outstandingWrites.peek()) {
outstandingWrites.remove().get();
}
checkForFailures();
KV<ByteString, Iterable<Mutation>> record = c.element();
Instant writeStart = Instant.now();
pendingThrottlingMsecs = 0;
CompletableFuture<Void> f =
bigtableWriter
.writeRecord(record)
.handle(handleMutationException(record, window, writeStart));
outstandingWrites.add(f);
if (pendingThrottlingMsecs > 0) {
throttlingMsecs.inc(pendingThrottlingMsecs);
}
++recordsWritten;
seenWindows.compute(window, (key, count) -> (count != null ? count : 0) + 1);
}

Line under review: for (Future<?> f = outstandingWrites.peek();

Code after addressing the review:
public void processElement(ProcessContext c, BoundedWindow window) throws Exception {
drainCompletedElementFutures();
checkForFailures();
KV<ByteString, Iterable<Mutation>> record = c.element();
Instant writeStart = Instant.now();
pendingThrottlingMsecs = 0;
CompletableFuture<Void> f =
bigtableWriter
.writeRecord(record)
.handle(handleMutationException(record, window, writeStart));
outstandingWrites.add(f);
if (pendingThrottlingMsecs > 0) {
throttlingMsecs.inc(pendingThrottlingMsecs);
}
++recordsWritten;
seenWindows.compute(window, (key, count) -> (count != null ? count : 0) + 1);
}
Code review comment: this function is just called by line 80, is this a function for debugging?

Code before review:
private static String addLineNumber(String code) {
String[] lines = code.split("\n");
StringBuilder builder = new StringBuilder();
for (int i = 0; i < lines.length; i++) {
builder.append(i + 1).append(" ").append(lines[i]).append("\n");
}
return builder.toString();
}

Line under review: builder.append(i + 1).append(" ").append(lines[i]).append("\n");

Code after addressing the review:
private static String addLineNumber(String code) {
String[] lines = code.split("\n");
StringBuilder builder = new StringBuilder();
for (int i = 0; i < lines.length; i++) {
builder.append(i + 1).append(" ").append(lines[i]).append("\n");
}
return builder.toString();
}
Code review comment: Shall we convert the static collections to instance collections?

Code before review:
private void loadServices() {
if (!CodeActionProvidersHolder.nodeBasedProviders.isEmpty()) {
return;
}
ServiceLoader<LSCodeActionProvider> serviceLoader = ServiceLoader.load(LSCodeActionProvider.class);
for (CodeActionNodeType nodeType : CodeActionNodeType.values()) {
CodeActionProvidersHolder.nodeBasedProviders.put(nodeType, new ArrayList<>());
}
for (LSCodeActionProvider provider : serviceLoader) {
if (provider == null) {
continue;
}
if (provider.isNodeBasedSupported()) {
for (CodeActionNodeType nodeType : provider.getCodeActionNodeTypes()) {
CodeActionProvidersHolder.nodeBasedProviders.get(nodeType).add(provider);
}
}
if (provider.isDiagBasedSupported()) {
CodeActionProvidersHolder.diagnosticsBasedProviders.add(provider);
}
}
}

Line under review: CodeActionProvidersHolder.nodeBasedProviders.put(nodeType, new ArrayList<>());

Code after addressing the review:
private void loadServices() {
if (!CodeActionProvidersHolder.nodeBasedProviders.isEmpty()) {
return;
}
ServiceLoader<LSCodeActionProvider> serviceLoader = ServiceLoader.load(LSCodeActionProvider.class);
for (CodeActionNodeType nodeType : CodeActionNodeType.values()) {
CodeActionProvidersHolder.nodeBasedProviders.put(nodeType, new ArrayList<>());
}
for (LSCodeActionProvider provider : serviceLoader) {
if (provider == null) {
continue;
}
if (provider.isNodeBasedSupported()) {
for (CodeActionNodeType nodeType : provider.getCodeActionNodeTypes()) {
CodeActionProvidersHolder.nodeBasedProviders.get(nodeType).add(provider);
}
}
if (provider.isDiagBasedSupported()) {
CodeActionProvidersHolder.diagnosticsBasedProviders.add(provider);
}
}
}
Code review comment: Currently what happens is the following:  If the user doesn't specify anything, the default is used. If the user does specify something that is not resolvable from the classpath root, we print a warning message. If it is resolvable, we show it and also show the "Powered by..." text

Code before review:
private String readBannerFile(BannerConfig config) {
URL resource = Thread.currentThread().getContextClassLoader().getResource(config.path);
if (resource != null) {
try (InputStream is = resource.openStream()) {
byte[] content = FileUtil.readFileContents(is);
StringBuilder bannerTitle = new StringBuilder(new String(content, StandardCharsets.UTF_8));
bannerTitle.append('\n');
if (!config.isDefaultPath()) {
bannerTitle.append("Powered by Quarkus v").append(Version.getVersion()).append('\n');
}
return bannerTitle.toString();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
} else {
logger.warn("Could not read banner file");
return "";
}
}

Line under review: if (!config.isDefaultPath()) {

Code after addressing the review:
private String readBannerFile(BannerConfig config) {
try {
Map.Entry<URL, Boolean> entry = getBanner(config);
URL bannerResourceURL = entry.getKey();
if (bannerResourceURL == null) {
logger.warn("Could not locate banner file");
return "";
}
try (InputStream is = bannerResourceURL.openStream()) {
byte[] content = FileUtil.readFileContents(is);
String bannerTitle = new String(content, StandardCharsets.UTF_8);
int width = 0;
Scanner scanner = new Scanner(bannerTitle);
while (scanner.hasNextLine()) {
width = Math.max(width, scanner.nextLine().length());
}
String tagline = "\n";
Boolean isDefaultBanner = entry.getValue();
if (!isDefaultBanner) {
tagline = String.format("\n%" + width + "s\n", "Powered by Quarkus v" + Version.getVersion());
}
return bannerTitle + tagline;
}
} catch (IOException e) {
logger.warn("Unable to read banner file");
return "";
}
}
Code review comment: nit, also remove the `public` in function `testJoinWithFilter()` below. BTW, maybe we need to consider how to make the weak constraint about removing `public` in test functions  more conspicuous.

Code before review:
void testLeftOuterJoinWithLiteralTrue() {
String sinkTableDdl =
"CREATE TABLE MySink (\n"
+ "  a varchar,\n"
+ "  b varchar\n"
+ ") with (\n"
+ "  'connector' = 'values',\n"
+ "  'table-sink-class' = 'DEFAULT')";
tEnv.executeSql(sinkTableDdl);
util.addTemporarySystemFunction("func1", TableFunc1.class);
String sqlQuery =
"insert into MySink SELECT c, s FROM MyTable LEFT JOIN LATERAL TABLE(func1(c)) AS T(s) ON TRUE";
util.verifyJsonPlan(sqlQuery);
}

Line under review: + "  a varchar,\n"

Code after addressing the review:
void testLeftOuterJoinWithLiteralTrue() {
String sinkTableDdl =
"CREATE TABLE MySink (\n"
+ "  a varchar,\n"
+ "  b varchar\n"
+ ") with (\n"
+ "  'connector' = 'values',\n"
+ "  'table-sink-class' = 'DEFAULT')";
tEnv.executeSql(sinkTableDdl);
util.addTemporarySystemFunction("func1", TableFunc1.class);
String sqlQuery =
"insert into MySink SELECT c, s FROM MyTable LEFT JOIN LATERAL TABLE(func1(c)) AS T(s) ON TRUE";
util.verifyJsonPlan(sqlQuery);
}
Code review comment: shouldn't we change the order here as discussed offline? ``` .doOnError(throwable -> {                             this.refreshInProgress.set(null);                             logger.warn("Background refresh task failed", throwable); ```

Code before review:
private Mono<TValue> createBackgroundRefreshTask(Function<TValue, Mono<TValue>> createRefreshFunction) {
return this.value
.get()
.flatMap(cachedValue -> createRefreshFunction.apply(cachedValue))
.flatMap(response -> {
this.refreshInProgress.set(null);
return this.value.updateAndGet(existingValue -> Mono.just(response));
})
.doOnError(throwable -> {
logger.warn("Background refresh task failed", throwable);
this.refreshInProgress.set(null);
})
.cache();
}

Line under review: this.refreshInProgress.set(null);

Code after addressing the review:
private Mono<TValue> createBackgroundRefreshTask(Function<TValue, Mono<TValue>> createRefreshFunction) {
return this.value
.get()
.flatMap(createRefreshFunction)
.flatMap(response -> {
this.refreshInProgress.set(null);
return this.value.updateAndGet(existingValue -> Mono.just(response));
})
.doOnError(throwable -> {
this.refreshInProgress.set(null);
logger.warn("Background refresh task failed", throwable);
})
.cache();
}
Code review comment: Unable to obtain catalog name

Code before review:
public void analyze(Analyzer analyzer) throws AnalysisException, UserException {
super.analyze(analyzer);
if (Strings.isNullOrEmpty(db)) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_WRONG_DB_NAME, db);
}
if (!Env.getCurrentEnv().getAccessManager()
.checkDbPriv(ConnectContext.get(), InternalCatalog.INTERNAL_CATALOG_NAME, db,
PrivPredicate.ALTER_CREATE_DROP)) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_DBACCESS_DENIED_ERROR,
ConnectContext.get().getQualifiedUser(), db);
}
}

Line under review: .checkDbPriv(ConnectContext.get(), InternalCatalog.INTERNAL_CATALOG_NAME, db,

Code after addressing the review:
public void analyze(Analyzer analyzer) throws AnalysisException, UserException {
super.analyze(analyzer);
if (Strings.isNullOrEmpty(db)) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_WRONG_DB_NAME, db);
}
if (!Env.getCurrentEnv().getAccessManager()
.checkDbPriv(ConnectContext.get(), InternalCatalog.INTERNAL_CATALOG_NAME, db,
PrivPredicate.ALTER_CREATE_DROP)) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_DBACCESS_DENIED_ERROR,
ConnectContext.get().getQualifiedUser(), db);
}
}
Code review comment: also plz add test case for this grant

Code before review:
public void saveV2(DataOutputStream dos) throws IOException {
try {
final int cnt = 1 + 1 + userToPrivilegeCollection.size() * 2
+ 1 + roleIdToPrivilegeCollection.size() * 2;
SRMetaBlockWriter writer = new SRMetaBlockWriter(dos, SRMetaBlockID.AUTHORIZATION_MGR, cnt);
writer.writeJson(this);
writer.writeJson(userToPrivilegeCollection.size());
Iterator<Map.Entry<UserIdentity, UserPrivilegeCollection>> iterator =
userToPrivilegeCollection.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<UserIdentity, UserPrivilegeCollection> entry = iterator.next();
writer.writeJson(entry.getKey());
writer.writeJson(entry.getValue());
}
writer.writeJson(roleIdToPrivilegeCollection.size());
Iterator<Map.Entry<Long, RolePrivilegeCollection>> roleIter =
roleIdToPrivilegeCollection.entrySet().iterator();
while (roleIter.hasNext()) {
Map.Entry<Long, RolePrivilegeCollection> entry = roleIter.next();
writer.writeJson(entry.getKey());
writer.writeJson(entry.getValue());
}
writer.close();
} catch (SRMetaBlockException e) {
throw new IOException("failed to save AuthenticationManager!", e);
}
}

Line under review: writer.writeJson(this);

Code after addressing the review:
public void saveV2(DataOutputStream dos) throws IOException {
try {
final int cnt = 1 + 1 + userToPrivilegeCollection.size() * 2
+ 1 + roleIdToPrivilegeCollection.size() * 2;
SRMetaBlockWriter writer = new SRMetaBlockWriter(dos, SRMetaBlockID.AUTHORIZATION_MGR, cnt);
writer.writeJson(this);
writer.writeJson(userToPrivilegeCollection.size());
Iterator<Map.Entry<UserIdentity, UserPrivilegeCollectionV2>> iterator =
userToPrivilegeCollection.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<UserIdentity, UserPrivilegeCollectionV2> entry = iterator.next();
writer.writeJson(entry.getKey());
writer.writeJson(entry.getValue());
}
writer.writeJson(roleIdToPrivilegeCollection.size());
Iterator<Map.Entry<Long, RolePrivilegeCollectionV2>> roleIter =
roleIdToPrivilegeCollection.entrySet().iterator();
while (roleIter.hasNext()) {
Map.Entry<Long, RolePrivilegeCollectionV2> entry = roleIter.next();
writer.writeJson(entry.getKey());
writer.writeJson(entry.getValue());
}
writer.close();
} catch (SRMetaBlockException e) {
throw new IOException("failed to save AuthenticationManager!", e);
}
}
Code review comment: I specifically did not want to use it, in case there is an exception (or restart of host-admin) after createTempFile and before the move: It would leave stray files in the directory.

Code before review:
private void writeBytes(byte[] content, boolean atomic) {
if (atomic) {
String tmpPath = path.toPath().toString() + ".FileSyncTmp";
new UnixPath(path.toPath().getFileSystem().getPath(tmpPath))
.writeBytes(content)
.atomicMove(path.toPath());
} else {
path.writeBytes(content);
}
}

Line under review: String tmpPath = path.toPath().toString() + ".FileSyncTmp";

Code after addressing the review:
private void writeBytes(byte[] content, boolean atomic) {
if (atomic) {
String tmpPath = path.toPath().toString() + ".FileSyncTmp";
new UnixPath(path.toPath().getFileSystem().getPath(tmpPath))
.writeBytes(content)
.atomicMove(path.toPath());
} else {
path.writeBytes(content);
}
}
Code review comment: I changed it to check the result of the operation into the assert

Code before review:
private void testCopy(S3Options options) throws IOException {
S3FileSystem s3FileSystem = buildMockedS3FileSystem(s3Options());
S3ResourceId sourcePath = S3ResourceId.fromUri("s3:
S3ResourceId destinationPath = S3ResourceId.fromUri("s3:
HeadObjectResponse.Builder builder = HeadObjectResponse.builder().contentLength(0L);
if (getSSECustomerKeyMd5(options) != null) {
builder.sseCustomerKeyMD5(getSSECustomerKeyMd5(options));
}
HeadObjectResponse headObjectResponse = builder.build();
assertGetObjectHead(
s3FileSystem, createObjectHeadRequest(sourcePath, options), options, headObjectResponse);
s3FileSystem.copy(sourcePath, destinationPath);
verify(s3FileSystem.getS3Client(), times(1)).copyObject(any(CopyObjectRequest.class));
headObjectResponse.toBuilder().contentLength(5_368_709_120L).build();
assertGetObjectHead(
s3FileSystem, createObjectHeadRequest(sourcePath, options), options, headObjectResponse);
try {
s3FileSystem.copy(sourcePath, destinationPath);
} catch (NullPointerException e) {
}
verify(s3FileSystem.getS3Client(), never()).copyObject((CopyObjectRequest) null);
}

Line under review: headObjectResponse.toBuilder().contentLength(5_368_709_120L).build();

Code after addressing the review:
private void testCopy(S3Options options) throws IOException {
S3FileSystem s3FileSystem = buildMockedS3FileSystem(s3Options());
S3ResourceId sourcePath = S3ResourceId.fromUri("s3:
S3ResourceId destinationPath = S3ResourceId.fromUri("s3:
HeadObjectResponse.Builder builder = HeadObjectResponse.builder().contentLength(0L);
if (getSSECustomerKeyMd5(options) != null) {
builder.sseCustomerKeyMD5(getSSECustomerKeyMd5(options));
}
HeadObjectResponse headObjectResponse = builder.build();
assertGetObjectHead(
s3FileSystem, createObjectHeadRequest(sourcePath, options), options, headObjectResponse);
s3FileSystem.copy(sourcePath, destinationPath);
verify(s3FileSystem.getS3Client(), times(1)).copyObject(any(CopyObjectRequest.class));
HeadObjectResponse bigHeadObjectResponse =
headObjectResponse.toBuilder().contentLength(5_368_709_120L).build();
assertGetObjectHead(
s3FileSystem, createObjectHeadRequest(sourcePath, options), options, bigHeadObjectResponse);
try {
s3FileSystem.copy(sourcePath, destinationPath);
} catch (NullPointerException e) {
}
verify(s3FileSystem.getS3Client(), never()).copyObject((CopyObjectRequest) null);
}
Code review comment: This TODO can be solved now

Code before review:
protected Mono<NetworkInterfaceInner> getInnerAsync() {
return this
.manager()
.inner()
.networkInterfaces()
.getByResourceGroupAsync(this.resourceGroupName(), this.name(), null);
}


Code after addressing the review:
protected Mono<NetworkInterfaceInner> getInnerAsync() {
return this
.manager()
.inner()
.networkInterfaces()
.getByResourceGroupAsync(this.resourceGroupName(), this.name());
}
Code review comment: imo, using a constant fro `$0092` will improve the readability of the code. It is not mandatory because it is using only in here.

Code before review:
public Value getChildByName(String name) throws DebugVariableException {
if (namedChildVariables == null) {
namedChildVariables = computeChildVariables();
}
if (!namedChildVariables.containsKey(name)) {
for (Map.Entry<String, Value> childVariable : namedChildVariables.entrySet()) {
String escaped = childVariable.getKey().replaceAll("\\$0092(\\$0092)?", "$1");
if (escaped.equals(name)) {
return childVariable.getValue();
}
}
throw new DebugVariableException("No child variables found with name: '" + name + "'");
}
return namedChildVariables.get(name);
}

Line under review: String escaped = childVariable.getKey().replaceAll("\\$0092(\\$0092)?", "$1");

Code after addressing the review:
public Value getChildByName(String name) throws DebugVariableException {
if (namedChildVariables == null) {
namedChildVariables = computeChildVariables();
}
if (!namedChildVariables.containsKey(name)) {
for (Map.Entry<String, Value> childVariable : namedChildVariables.entrySet()) {
String unicodeOfSlash = "&0092";
String escaped = childVariable.getKey()
.replaceAll(String.format("\\%s(\\%s)?", unicodeOfSlash, unicodeOfSlash), "$1");
if (escaped.equals(name)) {
return childVariable.getValue();
}
}
throw new DebugVariableException("No child variables found with name: '" + name + "'");
}
return namedChildVariables.get(name);
}
Code review comment: should be `replayDropNode`? this will be only focus on warehouse restore its internal state, not triggering starmgr to drop the node again because starmgr itself have edit log and can replay to its final state.

Code before review:
public void replayDropBackend(Backend backend) {
LOG.debug("replayDropBackend: {}", backend);
Map<Long, Backend> copiedBackends = Maps.newHashMap(idToBackendRef);
copiedBackends.remove(backend.getId());
idToBackendRef = ImmutableMap.copyOf(copiedBackends);
Map<Long, AtomicLong> copiedReportVerions = Maps.newHashMap(idToReportVersionRef);
copiedReportVerions.remove(backend.getId());
idToReportVersionRef = ImmutableMap.copyOf(copiedReportVerions);
final Cluster cluster = GlobalStateMgr.getCurrentState().getCluster();
if (null != cluster) {
cluster.removeBackend(backend.getId());
Warehouse warehouse = GlobalStateMgr.getCurrentWarehouseMgr().
getWarehouse(WarehouseManager.DEFAULT_WAREHOUSE_NAME);
if (warehouse != null) {
warehouse.getAnyAvailableCluster().dropNode(backend.getId());
}
if (RunMode.allowCreateLakeTable()) {
long starletPort = backend.getStarletPort();
if (starletPort == 0) {
return;
}
String workerAddr = backend.getHost() + ":" + starletPort;
long workerId = GlobalStateMgr.getCurrentState().getStarOSAgent().getWorkerId(workerAddr);
GlobalStateMgr.getCurrentState().getStarOSAgent().removeWorkerFromMap(workerId, workerAddr);
}
} else {
LOG.error("Cluster {} no exist.", SystemInfoService.DEFAULT_CLUSTER);
}
}

Line under review: warehouse.getAnyAvailableCluster().dropNode(backend.getId());

Code after addressing the review:
public void replayDropBackend(Backend backend) {
LOG.debug("replayDropBackend: {}", backend);
Map<Long, Backend> copiedBackends = Maps.newHashMap(idToBackendRef);
copiedBackends.remove(backend.getId());
idToBackendRef = ImmutableMap.copyOf(copiedBackends);
Map<Long, AtomicLong> copiedReportVerions = Maps.newHashMap(idToReportVersionRef);
copiedReportVerions.remove(backend.getId());
idToReportVersionRef = ImmutableMap.copyOf(copiedReportVerions);
dropComputeNodeFromWarehouse(backend);
final Cluster cluster = GlobalStateMgr.getCurrentState().getCluster();
if (null != cluster) {
cluster.removeBackend(backend.getId());
if (RunMode.allowCreateLakeTable()) {
long starletPort = backend.getStarletPort();
if (starletPort == 0) {
return;
}
String workerAddr = backend.getHost() + ":" + starletPort;
long workerId = GlobalStateMgr.getCurrentState().getStarOSAgent().getWorkerId(workerAddr);
GlobalStateMgr.getCurrentState().getStarOSAgent().removeWorkerFromMap(workerId, workerAddr);
}
} else {
LOG.error("Cluster {} no exist.", SystemInfoService.DEFAULT_CLUSTER);
}
}
Code review comment: You are right, It's my mistake.  I see this checkpointCoordinator isn't used, so removed it.   For the convenience of review, friendly reminder:  - It's recovered in the first commit, and I removed the `CheckpointCoordinator checkpointCoordinator =` due to it's not necessary. - I did some extra work in this PR during fix this comment. I migrate checkpoint coordinator related tests to junit5 in the 3rd commit. - The second and fourth commits are not updated.

Code before review:
private CheckpointCoordinator getCheckpointCoordinator(ExecutionGraph graph) throws Exception {
return new CheckpointCoordinatorBuilder()
.setCheckpointCoordinatorConfiguration(
CheckpointCoordinatorConfiguration.builder()
.setAlignedCheckpointTimeout(Long.MAX_VALUE)
.setMaxConcurrentCheckpoints(Integer.MAX_VALUE)
.build())
.setTimer(manuallyTriggeredScheduledExecutor)
.build(graph);
}

Line under review: .setTimer(manuallyTriggeredScheduledExecutor)

Code after addressing the review:
private CheckpointCoordinator getCheckpointCoordinator(ExecutionGraph graph) throws Exception {
return new CheckpointCoordinatorBuilder()
.setCheckpointCoordinatorConfiguration(
CheckpointCoordinatorConfiguration.builder()
.setAlignedCheckpointTimeout(Long.MAX_VALUE)
.setMaxConcurrentCheckpoints(Integer.MAX_VALUE)
.build())
.setTimer(manuallyTriggeredScheduledExecutor)
.build(graph);
}
Code review comment: Yes, if 'use v2 rollup' is true, only base index will be selected

Code before review:
public BestIndexInfo selectBestMV(ScanNode scanNode) throws UserException {
long start = System.currentTimeMillis();
Preconditions.checkState(scanNode instanceof OlapScanNode);
OlapScanNode olapScanNode = (OlapScanNode) scanNode;
ConnectContext connectContext = ConnectContext.get();
if (connectContext != null && connectContext.getSessionVariable().isUseV2Rollup()) {
OlapTable tbl = olapScanNode.getOlapTable();
String v2RollupIndexName = MaterializedViewHandler.NEW_STORAGE_FORMAT_INDEX_NAME_PREFIX + tbl.getName();
Long v2RollupIndexId = tbl.getIndexIdByName(v2RollupIndexName);
if (v2RollupIndexId != null) {
return new BestIndexInfo(v2RollupIndexId, false, "use_v2_rollup is true");
}
}
Map<Long, List<Column>> candidateIndexIdToSchema = predicates(olapScanNode);
long bestIndexId = priorities(olapScanNode, candidateIndexIdToSchema);
LOG.debug("The best materialized view is {} for scan node {} in query {}, cost {}",
bestIndexId, scanNode.getId(), selectStmt.toSql(), (System.currentTimeMillis() - start));
return new BestIndexInfo(bestIndexId, isPreAggregation, reasonOfDisable);
}

Line under review: if (connectContext != null && connectContext.getSessionVariable().isUseV2Rollup()) {

Code after addressing the review:
public BestIndexInfo selectBestMV(ScanNode scanNode) throws UserException {
long start = System.currentTimeMillis();
Preconditions.checkState(scanNode instanceof OlapScanNode);
OlapScanNode olapScanNode = (OlapScanNode) scanNode;
Map<Long, List<Column>> candidateIndexIdToSchema = predicates(olapScanNode);
long bestIndexId = priorities(olapScanNode, candidateIndexIdToSchema);
LOG.debug("The best materialized view is {} for scan node {} in query {}, cost {}",
bestIndexId, scanNode.getId(), selectStmt.toSql(), (System.currentTimeMillis() - start));
return new BestIndexInfo(bestIndexId, isPreAggregation, reasonOfDisable);
}
Code review comment: Need to update the doc comment with the new grammar.  Applicable for all places.

Code before review:
private STNode parseWhileStatement() {
startContext(ParserRuleContext.WHILE_BLOCK);
STNode whileKeyword = parseWhileKeyword();
STNode condition = parseExpression();
STNode whileBody = parseBlockNode();
endContext();
STNode onFailClause;
if (peek().kind == SyntaxKind.ON_KEYWORD) {
onFailClause = parseOnFailClause();
} else {
onFailClause = STNodeFactory.createEmptyNode();
}
return STNodeFactory.createWhileStatementNode(whileKeyword, condition, whileBody, onFailClause);
}

Line under review: if (peek().kind == SyntaxKind.ON_KEYWORD) {

Code after addressing the review:
private STNode parseWhileStatement() {
startContext(ParserRuleContext.WHILE_BLOCK);
STNode whileKeyword = parseWhileKeyword();
STNode condition = parseExpression();
STNode whileBody = parseBlockNode();
endContext();
STNode onFailClause = parseOptionalOnFailClause();
return STNodeFactory.createWhileStatementNode(whileKeyword, condition, whileBody, onFailClause);
}
Code review comment: Because `or expansion` could generate new CTE, it may break the assumption that the CTE anchor always is at the top of the plan in the rewritten CTE children

Code before review:
private static List<RewriteJob> getWholeTreeRewriteJobs(List<RewriteJob> jobs) {
return jobs(
topic("cte inline and pull up all cte anchor",
custom(RuleType.PULL_UP_CTE_ANCHOR, PullUpCteAnchor::new),
custom(RuleType.CTE_INLINE, CTEInline::new)
),
topic("process limit session variables",
custom(RuleType.ADD_DEFAULT_LIMIT, AddDefaultLimit::new)
),
topic("rewrite cte sub-tree",
custom(RuleType.REWRITE_CTE_CHILDREN, () -> new RewriteCteChildren(jobs))
),
topic("or expansion",
topDown(new OrExpansion())),
topic("whole plan check",
custom(RuleType.ADJUST_NULLABLE, AdjustNullable::new)
)
);
}

Line under review: topic("or expansion",

Code after addressing the review:
private static List<RewriteJob> getWholeTreeRewriteJobs(List<RewriteJob> jobs) {
return jobs(
topic("cte inline and pull up all cte anchor",
custom(RuleType.PULL_UP_CTE_ANCHOR, PullUpCteAnchor::new),
custom(RuleType.CTE_INLINE, CTEInline::new)
),
topic("process limit session variables",
custom(RuleType.ADD_DEFAULT_LIMIT, AddDefaultLimit::new)
),
topic("rewrite cte sub-tree",
custom(RuleType.REWRITE_CTE_CHILDREN, () -> new RewriteCteChildren(jobs))
),
topic("or expansion",
topDown(new OrExpansion())),
topic("whole plan check",
custom(RuleType.ADJUST_NULLABLE, AdjustNullable::new)
)
);
}
Code review comment: ```suggestion         LocalVariableProxyImpl selfVariable = stackFrame.visibleVariableByName(SELF_VAR_NAME); ```

Code before review:
private static String getFilteredStackFrame(StackFrameProxyImpl stackFrame) throws JdiProxyException {
String stackFrameName = stackFrame.location().method().name();
LocalVariableProxyImpl selfVisibleVariable = stackFrame.visibleVariableByName(SELF_VAR_NAME);
if (selfVisibleVariable == null) {
return stackFrameName;
}
Value stackFrameValue = stackFrame.getValue(selfVisibleVariable);
if (isService(stackFrameValue)) {
if (stackFrameName.equals(METHOD_INIT)) {
return BVariableType.SERVICE.getString();
} else {
String[] stackFrameNameParts = stackFrameName.split("\\$");
if (!stackFrameNameParts[1].isEmpty() && stackFrameNameParts[1].equals(ACCESSOR_DEFAULT)) {
return ACCESSOR_DEFAULT;
}
return !stackFrameNameParts[2].isEmpty() ? stackFrameNameParts[2] : stackFrameName;
}
}
return stackFrameName;
}

Line under review: LocalVariableProxyImpl selfVisibleVariable = stackFrame.visibleVariableByName(SELF_VAR_NAME);

Code after addressing the review:
private static String getFilteredStackFrame(StackFrameProxyImpl stackFrame) throws JdiProxyException {
String stackFrameName = stackFrame.location().method().name();
LocalVariableProxyImpl selfVariable = stackFrame.visibleVariableByName(SELF_VAR_NAME);
if (selfVariable == null) {
return stackFrameName;
}
Value selfValue = stackFrame.getValue(selfVariable);
if (isService(selfValue)) {
if (stackFrameName.equals(METHOD_INIT)) {
return BVariableType.SERVICE.getString();
} else {
String[] stackFrameNameParts = stackFrameName.split("\\$");
if (stackFrameNameParts.length > 1 && stackFrameNameParts[1].equals(ACCESSOR_DEFAULT)) {
return stackFrameNameParts[1];
}
return stackFrameNameParts.length > 2 ? stackFrameNameParts[2] : stackFrameName;
}
}
return stackFrameName;
}
Code review comment: Why are removing the hyphen? Same for L3599.

Code before review:
public void visit(BLangOnFailClause onFailClause, AnalyzerData data) {
SymbolEnv onFailEnv = SymbolEnv.createBlockEnv(onFailClause.body, data.env);
if (onFailClause.variableDefinitionNode != null) {
handleForeachDefinitionVariables(onFailClause.variableDefinitionNode, symTable.errorType,
onFailClause.isDeclaredWithVar, true, onFailEnv);
BLangVariable onFailVarNode = (BLangVariable) onFailClause.variableDefinitionNode.getVariable();
if (!types.isAssignable(onFailVarNode.getBType(), symTable.errorType)) {
dlog.error(onFailVarNode.pos, DiagnosticErrorCode.INVALID_TYPE_DEFINITION_FOR_ERROR_VAR,
onFailVarNode.getBType());
}
}
data.env = onFailEnv;
analyzeStmt(onFailClause.body, data);
}


Code after addressing the review:
public void visit(BLangOnFailClause onFailClause, AnalyzerData data) {
SymbolEnv onFailEnv = SymbolEnv.createBlockEnv(onFailClause.body, data.env);
VariableDefinitionNode onFailVarDefNode = onFailClause.variableDefinitionNode;
if (onFailVarDefNode != null) {
handleForeachDefinitionVariables(onFailVarDefNode, symTable.errorType,
onFailClause.isDeclaredWithVar, true, onFailEnv);
BLangVariable onFailVarNode = (BLangVariable) onFailVarDefNode.getVariable();
if (!types.isAssignable(onFailVarNode.getBType(), symTable.errorType)) {
dlog.error(onFailVarNode.pos, DiagnosticErrorCode.INVALID_TYPE_DEFINITION_FOR_ERROR_VAR,
onFailVarNode.getBType());
}
}
data.env = onFailEnv;
analyzeStmt(onFailClause.body, data);
}
Code review comment: Should use uppercase, I will modify it.

Code before review:
public void getTablePrivStatus(List<TPrivilegeStatus> tblPrivResult, UserIdentity currentUser) {
readLock();
try {
for (PrivEntry entry : tablePrivTable.getEntries()) {
TablePrivEntry tblPrivEntry = (TablePrivEntry) entry;
String dbName = ClusterNamespace.getNameFromFullName(tblPrivEntry.getOrigDb());
String tblName = tblPrivEntry.getOrigTbl();
if (dbName.equals("information_schema" /* Don't show privileges in information_schema */)
|| !checkTblPriv(currentUser, tblPrivEntry.getOrigDb(), tblName, PrivPredicate.SHOW)) {
continue;
}
String grantee = new String("\'").concat(ClusterNamespace.getNameFromFullName(tblPrivEntry.getOrigUser()))
.concat("\'@\'").concat(tblPrivEntry.getOrigHost()).concat("\'");
String isGrantable = tblPrivEntry.getPrivSet().get(2) ? "yes" : "no";
for (PaloPrivilege paloPriv : tblPrivEntry.getPrivSet().toPrivilegeList()) {
if (paloPriv == PaloPrivilege.GRANT_PRIV) {
continue;
}
TPrivilegeStatus status = new TPrivilegeStatus();
status.setTableName(tblName);
status.setPrivilegeType(privilegesInMysql[paloPriv.getIdx()]);
status.setGrantee(grantee);
status.setSchema(dbName);
status.setIsGrantable(isGrantable);
tblPrivResult.add(status);
}
}
} finally {
readUnlock();
}
}

Line under review: String isGrantable = tblPrivEntry.getPrivSet().get(2) ? "yes" : "no";

Code after addressing the review:
public void getTablePrivStatus(List<TPrivilegeStatus> tblPrivResult, UserIdentity currentUser) {
readLock();
try {
for (PrivEntry entry : tablePrivTable.getEntries()) {
TablePrivEntry tblPrivEntry = (TablePrivEntry) entry;
String dbName = ClusterNamespace.getNameFromFullName(tblPrivEntry.getOrigDb());
String tblName = tblPrivEntry.getOrigTbl();
if (dbName.equals("information_schema" /* Don't show privileges in information_schema */)
|| !checkTblPriv(currentUser, tblPrivEntry.getOrigDb(), tblName, PrivPredicate.SHOW)) {
continue;
}
String grantee = new String("\'").concat(ClusterNamespace.getNameFromFullName(tblPrivEntry.getOrigUser()))
.concat("\'@\'").concat(tblPrivEntry.getOrigHost()).concat("\'");
String isGrantable = tblPrivEntry.getPrivSet().get(2) ? "YES" : "NO";
for (PaloPrivilege paloPriv : tblPrivEntry.getPrivSet().toPrivilegeList()) {
if (!PaloPrivilege.privInPaloToMysql.containsKey(paloPriv)) {
continue;
}
TPrivilegeStatus status = new TPrivilegeStatus();
status.setTableName(tblName);
status.setPrivilegeType(PaloPrivilege.privInPaloToMysql.get(paloPriv));
status.setGrantee(grantee);
status.setSchema(dbName);
status.setIsGrantable(isGrantable);
tblPrivResult.add(status);
}
}
} finally {
readUnlock();
}
}
Code review comment: should not add check here, the fourth child should be string type or varchar type, but maybe not string literal. signature already check the type, so remove this check please. 

Code before review:
public AesDecryptV2 withChildren(List<Expression> children) {
Preconditions.checkArgument(children.size() >= 2 && children.size() <= 4);
if (children.size() == 2) {
return new AesDecryptV2(children.get(0), children.get(1));
} else if (children().size() == 3) {
return new AesDecryptV2(children.get(0), children.get(1), children.get(2));
} else {
if (!(children.get(3) instanceof StringLiteral)) {
throw new AnalysisException("the 4th parameter should be string literal: " + this.toSql());
}
return new AesDecryptV2(children.get(0), children.get(1), children.get(2), (StringLiteral) children.get(3));
}
}

Line under review: }

Code after addressing the review:
public AesDecryptV2 withChildren(List<Expression> children) {
Preconditions.checkArgument(children.size() >= 2 && children.size() <= 4);
if (children.size() == 2) {
return new AesDecryptV2(children.get(0), children.get(1));
} else if (children().size() == 3) {
return new AesDecryptV2(children.get(0), children.get(1), children.get(2));
} else {
return new AesDecryptV2(children.get(0), children.get(1), children.get(2), (StringLiteral) children.get(3));
}
}
Code review comment: Will fix the same with "Adding documentation for the whole document"

Code before review:
private static String getDocumentationAttachment(List<String> attributes, int offset) {
String offsetStr = String.join("", Collections.nCopies(offset, " "));
if (attributes == null || attributes.isEmpty()) {
return String.format("%n%sdocumentation {%n%s\t%n%s}", offsetStr, offsetStr, offsetStr);
} else {
String joinedList = String.join(" \r\n\t", attributes);
return String.format("%n%sdocumentation {%n%s\t%n\t%s%n%s}", offsetStr, offsetStr, joinedList, offsetStr);
}
}

Line under review: } else {

Code after addressing the review:
private static String getDocumentationAttachment(List<String> attributes, int offset) {
String offsetStr = String.join("", Collections.nCopies(offset, " "));
if (attributes == null || attributes.isEmpty()) {
return String.format("%n%sdocumentation {%n%s\t%n%s}", offsetStr, offsetStr, offsetStr);
} else {
String joinedList = String.join(" \r\n\t", attributes);
return String.format("%n%sdocumentation {%n%s\t%n\t%s%n%s}", offsetStr, offsetStr, joinedList, offsetStr);
}
}
Code review comment: Unrelated to this PR - I'm wondering if at some point we shouldn't use something like https://github.com/zalando/problem. 

Code before review:
private void htmlResponse(RoutingContext event, String details, Throwable exception) {
event.response().headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=utf-8");
final TemplateHtmlBuilder htmlBuilder = new TemplateHtmlBuilder("Internal Server Error", details, details);
if (showStack && exception != null) {
htmlBuilder.stack(exception);
}
writeResponse(event, htmlBuilder.toString());
}

Line under review: event.response().headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=utf-8");

Code after addressing the review:
private void htmlResponse(RoutingContext event, String details, Throwable exception) {
event.response().headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=utf-8");
final TemplateHtmlBuilder htmlBuilder = new TemplateHtmlBuilder("Internal Server Error", details, details);
if (showStack && exception != null) {
htmlBuilder.stack(exception);
}
writeResponse(event, htmlBuilder.toString());
}
Code review comment: Why do we need Stack for this?   Would a simple String variable work? It make sense for classes with inner classes to be able to pop() and come back to parent class...  But, can we find a new Method_DEF inside a Method_def?

Code before review:
public void leaveToken(DetailAST token) {
switch (token.getType()) {
case TokenTypes.CLASS_DEF:
if (!classNameStack.isEmpty()) {
classNameStack.pop();
}
break;
case TokenTypes.METHOD_DEF:
if (!methodDefStack.isEmpty()) {
methodDefStack.pop();
}
break;
default:
break;
}
}

Line under review: methodDefStack.pop();

Code after addressing the review:
public void leaveToken(DetailAST token) {
if (token.getType() == TokenTypes.CLASS_DEF && !classNameStack.isEmpty()) {
classNameStack.pop();
}
}
Code review comment: should this be using the CoreUtils method added above?

Code before review:
private HttpPipeline createPipeline() {
if (pipeline != null) {
return pipeline;
}
final Configuration buildConfiguration = configuration == null
? Configuration.getGlobalConfiguration().clone()
: configuration;
final List<HttpPipelinePolicy> httpPolicies = new ArrayList<>();
final String applicationId = CoreUtils.getApplicationId(clientOptions, httpLogOptions);
httpPolicies.add(new UserAgentPolicy(applicationId, CLIENT_NAME, CLIENT_VERSION, buildConfiguration));
httpPolicies.add(new ServiceBusTokenCredentialHttpPolicy(tokenCredential));
httpPolicies.add(new AddHeadersFromContextPolicy());
httpPolicies.addAll(perCallPolicies);
HttpPolicyProviders.addBeforeRetryPolicies(httpPolicies);
httpPolicies.add(retryPolicy == null ? new RetryPolicy() : retryPolicy);
httpPolicies.addAll(perRetryPolicies);
if (clientOptions != null) {
List<HttpHeader> httpHeaderList = new ArrayList<>();
clientOptions.getHeaders().forEach(h -> httpHeaderList.add(new HttpHeader(h.getName(), h.getValue())));
if (!httpHeaderList.isEmpty()) {
httpPolicies.add(new AddHeadersPolicy(new HttpHeaders(httpHeaderList)));
}
}
httpPolicies.add(new HttpLoggingPolicy(httpLogOptions));
HttpPolicyProviders.addAfterRetryPolicies(httpPolicies);
return new HttpPipelineBuilder()
.policies(httpPolicies.toArray(new HttpPipelinePolicy[0]))
.httpClient(httpClient)
.clientOptions(clientOptions)
.build();
}

Line under review: }

Code after addressing the review:
private HttpPipeline createPipeline() {
if (pipeline != null) {
return pipeline;
}
final Configuration buildConfiguration = configuration == null
? Configuration.getGlobalConfiguration().clone()
: configuration;
final List<HttpPipelinePolicy> httpPolicies = new ArrayList<>();
final String applicationId = CoreUtils.getApplicationId(clientOptions, httpLogOptions);
httpPolicies.add(new UserAgentPolicy(applicationId, CLIENT_NAME, CLIENT_VERSION, buildConfiguration));
httpPolicies.add(new ServiceBusTokenCredentialHttpPolicy(tokenCredential));
httpPolicies.add(new AddHeadersFromContextPolicy());
httpPolicies.addAll(perCallPolicies);
HttpPolicyProviders.addBeforeRetryPolicies(httpPolicies);
httpPolicies.add(retryPolicy == null ? new RetryPolicy() : retryPolicy);
httpPolicies.addAll(perRetryPolicies);
if (clientOptions != null) {
List<HttpHeader> httpHeaderList = new ArrayList<>();
clientOptions.getHeaders().forEach(h -> httpHeaderList.add(new HttpHeader(h.getName(), h.getValue())));
if (!httpHeaderList.isEmpty()) {
httpPolicies.add(new AddHeadersPolicy(new HttpHeaders(httpHeaderList)));
}
}
httpPolicies.add(new HttpLoggingPolicy(httpLogOptions));
HttpPolicyProviders.addAfterRetryPolicies(httpPolicies);
return new HttpPipelineBuilder()
.policies(httpPolicies.toArray(new HttpPipelinePolicy[0]))
.httpClient(httpClient)
.clientOptions(clientOptions)
.build();
}
Code review comment: More fuel for the "node states should be immutable" fire... 🔥

Code before review:
NodeState getNodeState(int index) {
NodeState ns = nodeStates.get(index);
if (ns != null) return ns;
return (index >= getMaxIndex() || ! upNodes.get(index))
? new NodeState(type, State.DOWN)
: new NodeState(type, State.UP);
}

Line under review: : new NodeState(type, State.UP);

Code after addressing the review:
NodeState getNodeState(int index) {
NodeState ns = nodeStates.get(index);
if (ns != null) return ns;
return (index >= getLogicalNodeCount() || ! upNodes.get(index))
? new NodeState(type, State.DOWN)
: new NodeState(type, State.UP);
}