muttakin2301/ccr_train_1000 huggingface dataset:
Code review comment: I'm not sure why this change can fix database lost, could you please add some comment to explain it?

Code before review:
public long loadCluster(DataInputStream dis, long checksum) throws IOException, DdlException {
if (Catalog.getCurrentCatalogJournalVersion() >= FeMetaVersion.VERSION_30) {
int clusterCount = dis.readInt();
checksum ^= clusterCount;
for (long i = 0; i < clusterCount; ++i) {
final Cluster cluster = Cluster.read(dis);
checksum ^= cluster.getId();
List<Long> latestBackendIds = systemInfo.getClusterBackendIds(cluster.getName());
if (latestBackendIds.size() != cluster.getBackendIdList().size()) {
LOG.warn("Cluster:" + cluster.getName() + ", backends in Cluster is "
+ cluster.getBackendIdList().size() + ", backends in SystemInfoService is "
+ cluster.getBackendIdList().size());
}
cluster.setBackendIdList(latestBackendIds);
String dbName = ClusterNamespace.getFullName(cluster.getName(), InfoSchemaDb.DATABASE_NAME);
if (!fullNameToDb.containsKey(dbName)) {
final InfoSchemaDb db = new InfoSchemaDb(cluster.getName());
db.setClusterName(cluster.getName());
String errMsg = "InfoSchemaDb id shouldn't larger than 10000, please restart your FE server";
Preconditions.checkState(db.getId() < NEXT_ID_INIT_VALUE, errMsg);
idToDb.put(db.getId(), db);
fullNameToDb.put(db.getFullName(), db);
}
cluster.addDb(dbName, fullNameToDb.get(dbName).getId());
idToCluster.put(cluster.getId(), cluster);
nameToCluster.put(cluster.getName(), cluster);
}
}
return checksum;
}

Line under review: cluster.addDb(dbName, fullNameToDb.get(dbName).getId());

Code after addressing the review:
public long loadCluster(DataInputStream dis, long checksum) throws IOException, DdlException {
if (Catalog.getCurrentCatalogJournalVersion() >= FeMetaVersion.VERSION_30) {
int clusterCount = dis.readInt();
checksum ^= clusterCount;
for (long i = 0; i < clusterCount; ++i) {
final Cluster cluster = Cluster.read(dis);
checksum ^= cluster.getId();
List<Long> latestBackendIds = systemInfo.getClusterBackendIds(cluster.getName());
if (latestBackendIds.size() != cluster.getBackendIdList().size()) {
LOG.warn("Cluster:" + cluster.getName() + ", backends in Cluster is "
+ cluster.getBackendIdList().size() + ", backends in SystemInfoService is "
+ cluster.getBackendIdList().size());
}
cluster.setBackendIdList(latestBackendIds);
String dbName = ClusterNamespace.getFullName(cluster.getName(), InfoSchemaDb.DATABASE_NAME);
if (!fullNameToDb.containsKey(dbName)) {
final InfoSchemaDb db = new InfoSchemaDb(cluster.getName());
db.setClusterName(cluster.getName());
String errMsg = "InfoSchemaDb id shouldn't larger than 10000, please restart your FE server";
Preconditions.checkState(db.getId() < NEXT_ID_INIT_VALUE, errMsg);
idToDb.put(db.getId(), db);
fullNameToDb.put(db.getFullName(), db);
}
cluster.addDb(dbName, fullNameToDb.get(dbName).getId());
idToCluster.put(cluster.getId(), cluster);
nameToCluster.put(cluster.getName(), cluster);
}
}
return checksum;
}
Code review comment: Do we add a UT to cover the branch of `!containsInTableContainedRule(tableName, materials)` ?

Code before review:
private void refresh(final CreateTableStatement createTableStatement) throws SQLException {
createTableStatement.setTable(new SimpleTableSegment(new TableNameSegment(1, 3, new IdentifierValue("t_order_0"))));
Map<String, DataSource> dataSourceMap = mock(HashMap.class);
when(materials.getDataSourceMap()).thenReturn(dataSourceMap);
DataSource dataSource = mock(DataSource.class);
when(dataSourceMap.get(eq("ds"))).thenReturn(dataSource);
Connection connection = mock(Connection.class);
when(dataSource.getConnection()).thenReturn(connection);
DatabaseMetaData metaData = mock(DatabaseMetaData.class);
when(connection.getMetaData()).thenReturn(metaData);
ResultSet resultSet = mock(ResultSet.class);
when(metaData.getTables(any(), any(), any(), any())).thenReturn(resultSet);
when(resultSet.next()).thenReturn(false);
ShardingSphereSchema schema = ShardingSphereSchemaBuildUtil.buildSchema();
SchemaRefresher<CreateTableStatement> schemaRefresher = new CreateTableStatementSchemaRefresher();
schemaRefresher.refresh(schema, Collections.singleton("ds"), createTableStatement, materials);
assertTrue(schema.containsTable("t_order_0"));
}

Line under review: schemaRefresher.refresh(schema, Collections.singleton("ds"), createTableStatement, materials);

Code after addressing the review:
private void refresh(final CreateTableStatement createTableStatement) throws SQLException {
createTableStatement.setTable(new SimpleTableSegment(new TableNameSegment(1, 3, new IdentifierValue("t_order_0"))));
Map<String, DataSource> dataSourceMap = mock(HashMap.class);
when(materials.getDataSourceMap()).thenReturn(dataSourceMap);
DataSource dataSource = mock(DataSource.class);
when(dataSourceMap.get(eq("ds"))).thenReturn(dataSource);
Connection connection = mock(Connection.class);
when(dataSource.getConnection()).thenReturn(connection);
DatabaseMetaData metaData = mock(DatabaseMetaData.class);
when(connection.getMetaData()).thenReturn(metaData);
ResultSet resultSet = mock(ResultSet.class);
when(metaData.getTables(any(), any(), any(), any())).thenReturn(resultSet);
when(resultSet.next()).thenReturn(false);
ShardingSphereSchema schema = ShardingSphereSchemaBuildUtil.buildSchema();
SchemaRefresher<CreateTableStatement> schemaRefresher = new CreateTableStatementSchemaRefresher();
schemaRefresher.refresh(schema, Collections.singleton("ds"), createTableStatement, materials);
assertTrue(schema.containsTable("t_order_0"));
}
Code review comment: jfyi we could also do:   ``` headerMapper  = simpleMapper     .copy()     .configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true); ``` https://static.javadoc.io/com.fasterxml.jackson.core/jackson-databind/2.9.8/com/fasterxml/jackson/databind/ObjectMapper.html#copy--

Code before review:
public JacksonAdapter() {
simpleMapper = initializeObjectMapper(new ObjectMapper());
xmlMapper = initializeObjectMapper(new XmlMapper());
xmlMapper.configure(ToXmlGenerator.Feature.WRITE_XML_DECLARATION, true);
xmlMapper.setDefaultUseWrapper(false);
ObjectMapper flatteningMapper = initializeObjectMapper(new ObjectMapper())
.registerModule(FlatteningSerializer.getModule(simpleMapper()))
.registerModule(FlatteningDeserializer.getModule(simpleMapper()));
mapper = initializeObjectMapper(new ObjectMapper())
.registerModule(AdditionalPropertiesSerializer.getModule(flatteningMapper))
.registerModule(AdditionalPropertiesDeserializer.getModule(flatteningMapper))
.registerModule(FlatteningSerializer.getModule(simpleMapper()))
.registerModule(FlatteningDeserializer.getModule(simpleMapper()));
headerMapper = initializeHeaderMapper(new ObjectMapper());
}

Line under review: headerMapper = initializeHeaderMapper(new ObjectMapper());

Code after addressing the review:
public JacksonAdapter() {
simpleMapper = initializeObjectMapper(new ObjectMapper());
xmlMapper = initializeObjectMapper(new XmlMapper());
xmlMapper.configure(ToXmlGenerator.Feature.WRITE_XML_DECLARATION, true);
xmlMapper.setDefaultUseWrapper(false);
ObjectMapper flatteningMapper = initializeObjectMapper(new ObjectMapper())
.registerModule(FlatteningSerializer.getModule(simpleMapper()))
.registerModule(FlatteningDeserializer.getModule(simpleMapper()));
mapper = initializeObjectMapper(new ObjectMapper())
.registerModule(AdditionalPropertiesSerializer.getModule(flatteningMapper))
.registerModule(AdditionalPropertiesDeserializer.getModule(flatteningMapper))
.registerModule(FlatteningSerializer.getModule(simpleMapper()))
.registerModule(FlatteningDeserializer.getModule(simpleMapper()));
headerMapper = simpleMapper
.copy()
.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
}
Code review comment: it is better to return 0 directly. Objects.hash() will return 0.

Code before review:
public int hashCode() {
return Objects.hash();
}

Line under review: return Objects.hash();

Code after addressing the review:
public int hashCode() {
return 0;
}
Code review comment: nit: this can be replaced by a method reference `.map(DigitalTwinsResponse::getValue)`.

Code before review:
public Mono<String> getComponent(String digitalTwinId, String componentPath) {
return getComponentWithResponse(digitalTwinId, componentPath)
.map(response -> response.getValue());
}

Line under review: .map(response -> response.getValue());

Code after addressing the review:
public Mono<String> getComponent(String digitalTwinId, String componentPath) {
return getComponentWithResponse(digitalTwinId, componentPath)
.map(DigitalTwinsResponse::getValue);
}
Code review comment: Using synchronized block on isReady works here. I don't see there is a deadlock.  (1) If it runs the first synchronized block first, then it will call notify() and isReady is set to true. Then when the second synchronized block is executed, it will not reach the wait() call because isReady is true.  (2) If it runs the second synchronized block first, then it will wait() and give up the lock. Then in the first synchronized block, it will pick up the lock, set isReady to true, and then call notify(). 

Code before review:
public void testCloseVisibleToAwaitCompletionCallerAndProducer() throws Exception {
BeamFnDataInboundObserver observer =
BeamFnDataInboundObserver.forConsumers(
Arrays.asList(DataEndpoint.create(TRANSFORM_ID, CODER, (value) -> {})),
Collections.emptyList());
AtomicBoolean isReady = new AtomicBoolean(false);
Future<?> future =
executor.submit(
() -> {
observer.accept(dataWith("ABC"));
synchronized (isReady) {
isReady.set(true);
isReady.notify();
}
assertThrows(
BeamFnDataInboundObserver.CloseException.class,
() -> {
while (true) {
observer.accept(dataWith("ABC"));
}
});
return null;
});
Future<?> future2 =
executor.submit(
() -> {
synchronized (isReady) {
while (!isReady.get()) {
isReady.wait();
}
}
observer.close();
return null;
});
assertThrows(BeamFnDataInboundObserver.CloseException.class, () -> observer.awaitCompletion());
future.get();
future2.get();
}

Line under review: synchronized (isReady) {

Code after addressing the review:
public void testCloseVisibleToAwaitCompletionCallerAndProducer() throws Exception {
BeamFnDataInboundObserver observer =
BeamFnDataInboundObserver.forConsumers(
Arrays.asList(DataEndpoint.create(TRANSFORM_ID, CODER, (value) -> {})),
Collections.emptyList());
AtomicBoolean isReady = new AtomicBoolean(false);
Future<?> future =
executor.submit(
() -> {
observer.accept(dataWith("ABC"));
synchronized (isReady) {
isReady.set(true);
isReady.notify();
}
assertThrows(
BeamFnDataInboundObserver.CloseException.class,
() -> {
while (true) {
observer.accept(dataWith("ABC"));
}
});
return null;
});
Future<?> future2 =
executor.submit(
() -> {
synchronized (isReady) {
while (!isReady.get()) {
isReady.wait();
}
}
observer.close();
return null;
});
assertThrows(BeamFnDataInboundObserver.CloseException.class, () -> observer.awaitCompletion());
future.get();
future2.get();
}
Code review comment: `IOException`? (`org.apache.flink.runtime.checkpoint.channel.ChannelStateChunkReader#readChunk` already can handle `IOException`).

Code before review:
public void recover(ResultSubpartitionInfo subpartitionInfo, Tuple2<BufferBuilder, BufferConsumer> bufferBuilderAndConsumer) {
bufferBuilderAndConsumer.f0.finish();
if (bufferBuilderAndConsumer.f1.isDataAvailable()) {
boolean added = getSubpartition(subpartitionInfo).add(bufferBuilderAndConsumer.f1);
if (!added) {
throw new RuntimeException("Buffer consumer couldn't be added to ResultSubpartition");
}
} else {
bufferBuilderAndConsumer.f1.close();
}
}

Line under review: throw new RuntimeException("Buffer consumer couldn't be added to ResultSubpartition");

Code after addressing the review:
public void recover(ResultSubpartitionInfo subpartitionInfo, Tuple2<BufferBuilder, BufferConsumer> bufferBuilderAndConsumer) throws IOException {
bufferBuilderAndConsumer.f0.finish();
if (bufferBuilderAndConsumer.f1.isDataAvailable()) {
boolean added = getSubpartition(subpartitionInfo).add(bufferBuilderAndConsumer.f1);
if (!added) {
throw new IOException("Buffer consumer couldn't be added to ResultSubpartition");
}
} else {
bufferBuilderAndConsumer.f1.close();
}
}
Code review comment: ATM the `close` actually did nothing, but the proposed semantic from `Collector#close` would flush buffered data. If so I wonder it might have potential risk to call `close` before return if the `close` implementation is changed to clear the list future.

Code before review:
static List<StreamElement> popCompleted(StreamElementQueue<Integer> queue) {
final List<StreamElement> completed = new ArrayList<>();
TimestampedCollector<Integer> collector = new TimestampedCollector<>(new CollectorOutput<>(completed));
while (queue.hasCompletedElements()) {
queue.emitCompletedElement(collector);
}
collector.close();
return completed;
}

Line under review: collector.close();

Code after addressing the review:
static List<StreamElement> popCompleted(StreamElementQueue<Integer> queue) {
final List<StreamElement> completed = new ArrayList<>();
TimestampedCollector<Integer> collector = new TimestampedCollector<>(new CollectorOutput<>(completed));
while (queue.hasCompletedElements()) {
queue.emitCompletedElement(collector);
}
collector.close();
return completed;
}
Code review comment: Should RegistryClientMixin be checking/handling this config file property for all cases (not just Gradle?)

Code before review:
void setGradleProperties(ArrayDeque<String> args, boolean batchMode) {
if (output.isShowErrors()) {
args.add("--full-stacktrace");
}
if (batchMode) {
args.add("--console=plain");
} else if (output.isAnsiEnabled()) {
args.add("--console=rich");
}
if (output.isCliTest()) {
args.add("--project-dir=" + projectRoot.toAbsolutePath());
}
args.add(registryClient.getRegistryClientProperty());
final String configFile = registryClient.getConfigArg() == null
? System.getProperty(RegistriesConfigLocator.CONFIG_FILE_PATH_PROPERTY)
: registryClient.getConfigArg();
if (configFile != null) {
args.add("-D" + RegistriesConfigLocator.CONFIG_FILE_PATH_PROPERTY + "=" + configFile);
}
args.addAll(flattenMappedProperties(propertiesOptions.properties));
}

Line under review: final String configFile = registryClient.getConfigArg() == null

Code after addressing the review:
void setGradleProperties(ArrayDeque<String> args, boolean batchMode) {
if (output.isShowErrors()) {
args.add("--full-stacktrace");
}
if (batchMode) {
args.add("--console=plain");
} else if (output.isAnsiEnabled()) {
args.add("--console=rich");
}
if (output.isCliTest()) {
args.add("--project-dir=" + projectRoot.toAbsolutePath());
}
args.add(registryClient.getRegistryClientProperty());
final String configFile = registryClient.getConfigArg() == null
? System.getProperty(RegistriesConfigLocator.CONFIG_FILE_PATH_PROPERTY)
: registryClient.getConfigArg();
if (configFile != null) {
args.add("-D" + RegistriesConfigLocator.CONFIG_FILE_PATH_PROPERTY + "=" + configFile);
}
args.addAll(flattenMappedProperties(propertiesOptions.properties));
}
Code review comment: Shall we create an issue? Error unions are also effectively immutable. We need to check and sync the behaviour with compile-time behaviour if there are any differences, IMO.

Code before review:
private static Type getImmutableType(Type type, Set<Type> unresolvedTypes) {
if (TypeChecker.isInherentlyImmutableType(type) || (SymbolFlags.isFlagOn(type.getFlags(),
SymbolFlags.READONLY))) {
return type;
}
if (!unresolvedTypes.add(type)) {
return type;
}
return setImmutableIntersectionType(type, unresolvedTypes);
}

Line under review: if (TypeChecker.isInherentlyImmutableType(type) || (SymbolFlags.isFlagOn(type.getFlags(),

Code after addressing the review:
private static Type getImmutableType(Type type, Set<Type> unresolvedTypes) {
if (TypeChecker.isInherentlyImmutableType(type) || (SymbolFlags.isFlagOn(type.getFlags(),
SymbolFlags.READONLY))) {
return type;
}
if (!unresolvedTypes.add(type)) {
return type;
}
return setImmutableIntersectionType(type, unresolvedTypes);
}
Code review comment: Does it mean we run the same tests for `HEAP` backend twice? (twice for native, and twice for canonical) Shall we skip one execution?

Code before review:
private static StateBackendConfig heap(boolean incremental, boolean changelogEnabled) {
return new StateBackendConfig(changelogEnabled, incremental /* ignored for now */) {
@Override
public String getName() {
return "HEAP";
}
@Override
public Configuration getConfiguration() {
Configuration stateBackendConfig = super.getConfiguration();
stateBackendConfig.set(
CheckpointingOptions.FS_SMALL_FILE_THRESHOLD, MemorySize.ZERO);
return stateBackendConfig;
}
@Override
protected String getConfigName() {
return "filesystem";
}
@Override
public boolean isIncremental() {
return false;
}
};
}

Line under review: return new StateBackendConfig(changelogEnabled, incremental /* ignored for now */) {

Code after addressing the review:
private static StateBackendConfig heap(boolean incremental, boolean changelogEnabled) {
return new StateBackendConfig(changelogEnabled, incremental /* ignored for now */) {
@Override
public String getName() {
return "HEAP";
}
@Override
public Configuration getConfiguration() {
Configuration stateBackendConfig = super.getConfiguration();
stateBackendConfig.set(
CheckpointingOptions.FS_SMALL_FILE_THRESHOLD, MemorySize.ZERO);
return stateBackendConfig;
}
@Override
protected String getConfigName() {
return "filesystem";
}
@Override
public boolean isIncremental() {
return false;
}
};
}
Code review comment: I think in this case we should setError() on the rpc request and return it?

Code before review:
public void run() {
try {
byte compressionType = rpcRequest.parameters().get(0).asInt8();
if (compressionType != 0) {
rpcRequest.setError(0, "Invalid compression type: " + compressionType);
rpcRequest.returnRequest();
return;
}
int uncompressedSize = rpcRequest.parameters().get(1).asInt32();
byte[] logRequestPayload = rpcRequest.parameters().get(2).asData();
if (uncompressedSize != logRequestPayload.length) {
rpcRequest.setError(1, String.format("Invalid uncompressed size: got %d while data is of size %d ", uncompressedSize, logRequestPayload.length));
rpcRequest.returnRequest();
return;
}
logDispatcher.handle(ProtobufSerialization.fromLogRequest(logRequestPayload));
rpcRequest.returnValues().add(new Int8Value((byte)0));
byte[] responsePayload = ProtobufSerialization.toLogResponse();
rpcRequest.returnValues().add(new Int32Value(responsePayload.length));
rpcRequest.returnValues().add(new DataValue(responsePayload));
rpcRequest.returnRequest();
} catch (Exception e) {
log.log(Level.WARNING, e, () -> "Failed to handle log request: " + e.getMessage());
}
}

Line under review: log.log(Level.WARNING, e, () -> "Failed to handle log request: " + e.getMessage());

Code after addressing the review:
public void run() {
try {
byte compressionType = rpcRequest.parameters().get(0).asInt8();
if (compressionType != 0) {
rpcRequest.setError(ErrorCode.METHOD_FAILED, "Invalid compression type: " + compressionType);
rpcRequest.returnRequest();
return;
}
int uncompressedSize = rpcRequest.parameters().get(1).asInt32();
byte[] logRequestPayload = rpcRequest.parameters().get(2).asData();
if (uncompressedSize != logRequestPayload.length) {
rpcRequest.setError(ErrorCode.METHOD_FAILED, String.format("Invalid uncompressed size: got %d while data is of size %d ", uncompressedSize, logRequestPayload.length));
rpcRequest.returnRequest();
return;
}
logDispatcher.handle(ProtobufSerialization.fromLogRequest(logRequestPayload));
rpcRequest.returnValues().add(new Int8Value((byte)0));
byte[] responsePayload = ProtobufSerialization.toLogResponse();
rpcRequest.returnValues().add(new Int32Value(responsePayload.length));
rpcRequest.returnValues().add(new DataValue(responsePayload));
rpcRequest.returnRequest();
} catch (Exception e) {
String errorMessage = "Failed to handle log request: " + e.getMessage();
log.log(Level.WARNING, e, () -> errorMessage);
rpcRequest.setError(ErrorCode.METHOD_FAILED, errorMessage);
rpcRequest.returnRequest();
}
}
Code review comment: I will try to add a new `MultipleParameterTool extends ParameterTool` instead. It is an enhanced class with multiple parameters support. And it will be marked as `PublicEvolving`. It should be compatible with `ParameterTool`, all the tests of `ParameterToolTest` should pass.

Code before review:
public static ParameterTool fromArgs(String[] args) {
final Map<String, Collection<String>> map = new HashMap<>(args.length / 2);
int i = 0;
while (i < args.length) {
final String key;
if (args[i].startsWith("--")) {
key = args[i].substring(2);
} else if (args[i].startsWith("-")) {
key = args[i].substring(1);
} else {
throw new IllegalArgumentException(
String.format("Error parsing arguments '%s' on '%s'. Please prefix keys with -- or -.",
Arrays.toString(args), args[i]));
}
if (key.isEmpty()) {
throw new IllegalArgumentException(
"The input " + Arrays.toString(args) + " contains an empty argument");
}
i += 1;
map.putIfAbsent(key, new ArrayList<>());
if (i >= args.length) {
map.get(key).add(NO_VALUE_KEY);
} else if (NumberUtils.isNumber(args[i])) {
map.get(key).add(args[i]);
i += 1;
} else if (args[i].startsWith("--") || args[i].startsWith("-")) {
map.get(key).add(NO_VALUE_KEY);
} else {
map.get(key).add(args[i]);
i += 1;
}
}
return fromMultiMap(map);
}

Line under review: map.putIfAbsent(key, new ArrayList<>());

Code after addressing the review:
public static ParameterTool fromArgs(String[] args) {
final Map<String, String> map = new HashMap<>(args.length / 2);
int i = 0;
while (i < args.length) {
final String key = Utils.getKeyFromArgs(args, i);
if (key.isEmpty()) {
throw new IllegalArgumentException(
"The input " + Arrays.toString(args) + " contains an empty argument");
}
i += 1;
if (i >= args.length) {
map.put(key, NO_VALUE_KEY);
} else if (NumberUtils.isNumber(args[i])) {
map.put(key, args[i]);
i += 1;
} else if (args[i].startsWith("--") || args[i].startsWith("-")) {
map.put(key, NO_VALUE_KEY);
} else {
map.put(key, args[i]);
i += 1;
}
}
return fromMap(map);
}
Code review comment: I think this todo could be removed, since the proxy is inside http client now.

Code before review:
public Mono<HttpResponse> process(HttpPipelineCallContext context, HttpPipelineNextPolicy next) {
final HttpRequest request = context.getHttpRequest();
return next.process().flatMap(
response -> {
if (!isResponseSuccessful(response)) {
HttpResponse bufferedResponse = response.buffer();
return FluxUtil.collectBytesInByteBufferStream(bufferedResponse.getBody()).flatMap(
body -> {
String bodyStr = new String(body, StandardCharsets.UTF_8);
AzureJacksonAdapter jacksonAdapter = new AzureJacksonAdapter();
CloudError cloudError;
try {
cloudError = jacksonAdapter.deserialize(
bodyStr, CloudError.class, SerializerEncoding.JSON);
} catch (IOException e) {
return Mono.just(bufferedResponse);
}
if (cloudError != null && MISSING_SUBSCRIPTION_REGISTRATION.equals(cloudError.getCode())) {
String subscriptionId = ResourceUtils.extractFromResourceId(
request.getUrl().getPath(), "subscriptions");
ResourceManager resourceManager = ResourceManager.authenticate(credential)
.withSubscription(subscriptionId);
Pattern providerPattern = Pattern.compile(".*'(.*)'");
Matcher providerMatcher = providerPattern.matcher(cloudError.getMessage());
providerMatcher.find();
return registerProviderUntilSuccess(providerMatcher.group(1), resourceManager)
.flatMap(afterRegistered -> next.process());
}
return Mono.just(bufferedResponse);
}
);
}
return Mono.just(response);
}
);
}


Code after addressing the review:
public Mono<HttpResponse> process(HttpPipelineCallContext context, HttpPipelineNextPolicy next) {
return next.process().flatMap(
response -> {
if (!isResponseSuccessful(response)) {
HttpResponse bufferedResponse = response.buffer();
return FluxUtil.collectBytesInByteBufferStream(bufferedResponse.getBody()).flatMap(
body -> {
String bodyStr = new String(body, StandardCharsets.UTF_8);
AzureJacksonAdapter jacksonAdapter = new AzureJacksonAdapter();
CloudError cloudError;
try {
cloudError = jacksonAdapter.deserialize(
bodyStr, CloudError.class, SerializerEncoding.JSON);
} catch (IOException e) {
return Mono.just(bufferedResponse);
}
if (cloudError != null && MISSING_SUBSCRIPTION_REGISTRATION.equals(cloudError.getCode())) {
ResourceManager resourceManager = ResourceManager.authenticate(credential, profile)
.withDefaultSubscription();
Pattern providerPattern = Pattern.compile(".*'(.*)'");
Matcher providerMatcher = providerPattern.matcher(cloudError.getMessage());
providerMatcher.find();
return registerProviderUntilSuccess(providerMatcher.group(1), resourceManager)
.flatMap(afterRegistered -> next.process());
}
return Mono.just(bufferedResponse);
}
);
}
return Mono.just(response);
}
);
}
Code review comment: ```suggestion                 ComputeNode  node = GlobalStateMgr.getCurrentSystemInfo().getBackendOrComputeNodeWithBePort(host, port); ```

Code before review:
public Status releaseMetadataLocks() {
for (TScanRangeLocations tablet : tabletLocations) {
TScanRange scanRange = tablet.getScan_range();
if (!scanRange.isSetInternal_scan_range()) {
continue;
}
TInternalScanRange internalScanRange = scanRange.getInternal_scan_range();
List<TScanRangeLocation> locations = tablet.getLocations();
for (TScanRangeLocation location : locations) {
TNetworkAddress address = location.getServer();
String host = address.getHostname();
int port = address.getPort();
ComputeNode node = GlobalStateMgr.getCurrentSystemInfo().getBackendWithBePort(host, port);
if (RunMode.getCurrentRunMode() == RunMode.SHARED_DATA) {
node = GlobalStateMgr.getCurrentSystemInfo().getBackendOrComputeNodeWithBePort(host, port);
}
if (node == null) {
continue;
}
try {
LakeService lakeService = BrpcProxy.getLakeService(host, port);
UnlockTabletMetadataRequest request = new UnlockTabletMetadataRequest();
request.tabletId = internalScanRange.getTablet_id();
request.version = Long.parseLong(internalScanRange.getVersion());
request.expireTime = (getCreateTimeMs() / 1000) + getTimeoutSecond();
lakeService.unlockTabletMetadata(request);
} catch (Throwable e) {
LOG.error("Fail to release metadata lock, job id {}, tablet id {}, version {}", id,
tableId, internalScanRange.getVersion());
}
}
}
return Status.OK;
}

Line under review: }

Code after addressing the review:
public Status releaseMetadataLocks() {
for (TScanRangeLocations tablet : tabletLocations) {
TScanRange scanRange = tablet.getScan_range();
if (!scanRange.isSetInternal_scan_range()) {
continue;
}
TInternalScanRange internalScanRange = scanRange.getInternal_scan_range();
List<TScanRangeLocation> locations = tablet.getLocations();
for (TScanRangeLocation location : locations) {
TNetworkAddress address = location.getServer();
String host = address.getHostname();
int port = address.getPort();
ComputeNode node = GlobalStateMgr.getCurrentSystemInfo().getBackendOrComputeNodeWithBePort(host, port);
if (!GlobalStateMgr.getCurrentSystemInfo().checkNodeAvailable(node)) {
continue;
}
try {
LakeService lakeService = BrpcProxy.getLakeService(host, port);
UnlockTabletMetadataRequest request = new UnlockTabletMetadataRequest();
request.tabletId = internalScanRange.getTablet_id();
request.version = Long.parseLong(internalScanRange.getVersion());
request.expireTime = (getCreateTimeMs() / 1000) + getTimeoutSecond();
lakeService.unlockTabletMetadata(request);
} catch (Throwable e) {
LOG.error("Fail to release metadata lock, job id {}, tablet id {}, version {}", id,
tableId, internalScanRange.getVersion());
}
}
}
return Status.OK;
}
Code review comment: we can call it directly `this(className);` 

Code before review:
public HiveFunctionWrapper(String className, UDFType serializableInstance) {
this.className = className;
Preconditions.checkArgument(
serializableInstance instanceof Serializable,
String.format(
"The UDF %s should be an instance of Serializable.",
serializableInstance.getClass().getName()));
this.udfSerializedString =
SerializationUtilities.serializeObject((Serializable) serializableInstance);
}

Line under review: this.className = className;

Code after addressing the review:
public HiveFunctionWrapper(String className, UDFType serializableInstance) {
this(className);
Preconditions.checkArgument(
serializableInstance.getClass().getName().equals(className),
String.format(
"Expect the UDF is instance of %s, but is instance of %s.",
className, serializableInstance.getClass().getName()));
Preconditions.checkArgument(
serializableInstance instanceof Serializable,
String.format(
"The UDF %s should be an instance of Serializable.",
serializableInstance.getClass().getName()));
this.udfSerializedString =
SerializationUtilities.serializeObject((Serializable) serializableInstance);
}
Code review comment: I believe 404 statusCode is enough and the core tracer will populate all the info needed.   https://github.com/Azure/azure-sdk-for-java/blob/main/sdk/core/azure-core-tracing-opentelemetry/src/main/java/com/azure/core/tracing/opentelemetry/implementation/HttpTraceUtil.java#L179  Can we avoid populating custom error codes?

Code before review:
private void end(int statusCode, Throwable throwable, Context context) {
if (throwable != null) {
if (statusCode == HttpConstants.StatusCodes.NOTFOUND) {
tracer.setAttribute(TracerProvider.ERROR_MSG, "Not found exception", context);
tracer.setAttribute(TracerProvider.ERROR_TYPE, throwable.getClass().getName(), context);
tracer.end(statusCode, null, context);
} else {
tracer.setAttribute(TracerProvider.ERROR_MSG, throwable.getMessage(), context);
tracer.setAttribute(TracerProvider.ERROR_TYPE, throwable.getClass().getName(), context);
tracer.end(statusCode, throwable, context);
}
} else {
tracer.end(statusCode, null, context);
}
}

Line under review: tracer.setAttribute(TracerProvider.ERROR_MSG, "Not found exception", context);

Code after addressing the review:
private void end(int statusCode, Throwable throwable, Context context) {
if (throwable != null) {
if (throwable instanceof CosmosException) {
CosmosException cosmosException = (CosmosException) throwable;
if (statusCode == HttpConstants.StatusCodes.NOTFOUND && cosmosException.getSubStatusCode() == 0) {
tracer.end(statusCode, null, context);
return;
}
}
}
tracer.end(statusCode, throwable, context);
}
Code review comment: Yeah I perfectly agree the cost is very small but small costs pile up and when there is absolutely no reason to pay this cost, I think we should avoid it.  Certainly not worth blocking the PR thus why I approved anyway and let you decide what to do :).  (I wouldn't have asked if it made the code worse or more complex)

Code before review:
String replacePathParameters(String path) {
if (path.isEmpty()) {
return "";
}
StringBuilder sb = new StringBuilder();
Matcher m = PATH_PARAM_PATTERN.matcher(path);
while (m.find()) {
String match = m.group();
String paramName = match.substring(1, match.length() - 1);
String val = pathParams.get(paramName);
if (val == null) {
throw new WebSocketClientException("Unable to obtain the path param for: " + paramName);
}
m.appendReplacement(sb, URLEncoder.encode(val, StandardCharsets.UTF_8));
}
m.appendTail(sb);
return path.startsWith("/") ? sb.toString() : "/" + sb.toString();
}

Line under review: return "";

Code after addressing the review:
String replacePathParameters(String path) {
if (path.isEmpty()) {
return path;
}
StringBuilder sb = new StringBuilder();
Matcher m = PATH_PARAM_PATTERN.matcher(path);
while (m.find()) {
String match = m.group();
String paramName = match.substring(1, match.length() - 1);
String val = pathParams.get(paramName);
if (val == null) {
throw new WebSocketClientException("Unable to obtain the path param for: " + paramName);
}
m.appendReplacement(sb, URLEncoder.encode(val, StandardCharsets.UTF_8));
}
m.appendTail(sb);
return path.startsWith("/") ? sb.toString() : "/" + sb.toString();
}
Code review comment: How about no `deployment.xml` at all?

Code before review:
void testDevDeployment() {
ApplicationPackage applicationPackage = ApplicationPackageBuilder.fromDeploymentXml(DeploymentSpec.empty.xmlForm());
var context = tester.newDeploymentContext();
ZoneId zone = ZoneId.from("dev", "us-east-1");
tester.controllerTester().zoneRegistry()
.setRoutingMethod(ZoneApiMock.from(zone), RoutingMethod.sharedLayer4);
context.runJob(zone, applicationPackage);
assertTrue(tester.configServer().application(context.instanceId(), zone).get().activated(),
"Application deployed and activated");
assertTrue(context.instanceJobs().isEmpty(),
"No job status added");
assertEquals(DeploymentSpec.empty, context.application().deploymentSpec(), "DeploymentSpec is not stored");
Set<RoutingMethod> routingMethods = tester.controller().routing().readEndpointsOf(context.deploymentIdIn(zone))
.asList()
.stream()
.map(Endpoint::routingMethod)
.collect(Collectors.toSet());
assertEquals(routingMethods, Set.of(RoutingMethod.sharedLayer4));
assertNotNull(tester.controllerTester().serviceRegistry().applicationStore()
.getMeta(new DeploymentId(context.instanceId(), zone))
.get(tester.clock().instant()));
tester.clock().advance(Duration.ofSeconds(1));
tester.controller().applications().deactivate(context.instanceId(), zone);
assertArrayEquals(new byte[0],
tester.controllerTester().serviceRegistry().applicationStore()
.getMeta(new DeploymentId(context.instanceId(), zone))
.get(tester.clock().instant()));
}

Line under review: ApplicationPackage applicationPackage = ApplicationPackageBuilder.fromDeploymentXml(DeploymentSpec.empty.xmlForm());

Code after addressing the review:
void testDevDeployment() {
ApplicationPackage applicationPackage = new ApplicationPackage(new byte[0]);
var context = tester.newDeploymentContext();
ZoneId zone = ZoneId.from("dev", "us-east-1");
tester.controllerTester().zoneRegistry()
.setRoutingMethod(ZoneApiMock.from(zone), RoutingMethod.sharedLayer4);
context.runJob(zone, applicationPackage);
assertTrue(tester.configServer().application(context.instanceId(), zone).get().activated(),
"Application deployed and activated");
assertTrue(context.instanceJobs().isEmpty(),
"No job status added");
assertEquals(DeploymentSpec.empty, context.application().deploymentSpec(), "DeploymentSpec is not stored");
Set<RoutingMethod> routingMethods = tester.controller().routing().readEndpointsOf(context.deploymentIdIn(zone))
.asList()
.stream()
.map(Endpoint::routingMethod)
.collect(Collectors.toSet());
assertEquals(routingMethods, Set.of(RoutingMethod.sharedLayer4));
assertNotNull(tester.controllerTester().serviceRegistry().applicationStore()
.getMeta(new DeploymentId(context.instanceId(), zone))
.get(tester.clock().instant()));
tester.clock().advance(Duration.ofSeconds(1));
tester.controller().applications().deactivate(context.instanceId(), zone);
assertArrayEquals(new byte[0],
tester.controllerTester().serviceRegistry().applicationStore()
.getMeta(new DeploymentId(context.instanceId(), zone))
.get(tester.clock().instant()));
}
Code review comment: This is an ancillary performance question, does the Java proxy interface pass the Object[] in a consistent order? I'm wondering if there could be an optimization for this.

Code before review:
public RequestOptions setRequestOptions(Object[] swaggerMethodArguments) {
return CoreUtils.findFirstOfType(swaggerMethodArguments, RequestOptions.class);
}

Line under review: return CoreUtils.findFirstOfType(swaggerMethodArguments, RequestOptions.class);

Code after addressing the review:
public RequestOptions setRequestOptions(Object[] swaggerMethodArguments) {
return CoreUtils.findFirstOfType(swaggerMethodArguments, RequestOptions.class);
}
Code review comment: Why we need to update limit in *last* segment for each write?

Code before review:
public boolean write(BaseRow row) throws IOException {
try {
this.serializer.serializeToPages(row, this.recordCollector);
currentDataBufferOffset = this.recordCollector.getCurrentOffset();
numBytesInLastBuffer = this.recordCollector.getCurrentPositionInSegment();
recordCount++;
for (BufferIterator iterator : iterators) {
iterator.recordBuffer.updateLimitInLastSegment(numBytesInLastBuffer);
}
return true;
} catch (EOFException e) {
return false;
}
}

Line under review: iterator.recordBuffer.updateLimitInLastSegment(numBytesInLastBuffer);

Code after addressing the review:
public boolean write(BaseRow row) throws IOException {
try {
this.serializer.serializeToPages(row, this.recordCollector);
currentDataBufferOffset = this.recordCollector.getCurrentOffset();
numBytesInLastBuffer = this.recordCollector.getCurrentPositionInSegment();
recordCount++;
return true;
} catch (EOFException e) {
return false;
}
}
Code review comment: why do we access the parent like this? Is this capture all the possible scenarios?

Code before review:
private Optional<NonTerminalNode> getVariableOrObjectFieldNode(NonTerminalNode sNode) {
if (isVariableNode(sNode) || sNode.kind() == SyntaxKind.OBJECT_FIELD) {
return Optional.of(sNode);
} else if (isVariableNode(sNode.parent()) || sNode.parent().kind() == SyntaxKind.OBJECT_FIELD) {
return Optional.of(sNode.parent());
} else if (sNode.kind() == SyntaxKind.LIST_CONSTRUCTOR && sNode.parent().kind() == SyntaxKind.COLLECT_CLAUSE
&& sNode.parent().parent().kind() == SyntaxKind.QUERY_EXPRESSION
&& isVariableNode(sNode.parent().parent().parent())) {
return Optional.of(sNode.parent().parent().parent());
}
return Optional.empty();
}

Line under review: } else if (sNode.kind() == SyntaxKind.LIST_CONSTRUCTOR && sNode.parent().kind() == SyntaxKind.COLLECT_CLAUSE

Code after addressing the review:
private Optional<NonTerminalNode> getVariableOrObjectFieldNode(NonTerminalNode sNode) {
if (isVariableNode(sNode) || sNode.kind() == SyntaxKind.OBJECT_FIELD) {
return Optional.of(sNode);
} else if (isVariableNode(sNode.parent()) || sNode.parent().kind() == SyntaxKind.OBJECT_FIELD) {
return Optional.of(sNode.parent());
} else if (sNode.parent().kind() == SyntaxKind.COLLECT_CLAUSE
&& sNode.parent().parent().kind() == SyntaxKind.QUERY_EXPRESSION
&& isVariableNode(sNode.parent().parent().parent())) {
return Optional.of(sNode.parent().parent().parent());
}
return Optional.empty();
}
Code review comment: out of curiosity, what was the issue here?

Code before review:
public void emitRecord(StreamRecord<E> streamRecord) throws Exception {
events.add(streamRecord.copy(streamRecord.getValue()));
}

Line under review: events.add(streamRecord.copy(streamRecord.getValue()));

Code after addressing the review:
public void emitRecord(StreamRecord<E> streamRecord) throws Exception {
events.add(streamRecord.copy(streamRecord.getValue()));
}
Code review comment: OK, keep it for now.

Code before review:
public void assertHasUncompletedJob() throws IOException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
final JobConfiguration jobConfiguration = JobConfigurationBuilder.createJobConfiguration();
RuleAlteredJobContext jobContext = new RuleAlteredJobContext(jobConfiguration);
JobProgress finishProcess = new JobProgress();
finishProcess.setStatus(JobStatus.FINISHED);
jobContext.setInitProgress(finishProcess);
GovernanceRepositoryAPI repositoryAPI = PipelineAPIFactory.getGovernanceRepositoryAPI();
repositoryAPI.persistJobProgress(jobContext);
URL jobConfigUrl = getClass().getClassLoader().getResource("scaling/rule_alter/scaling_job_config.yaml");
assertNotNull(jobConfigUrl);
repositoryAPI.persist(PipelineMetaDataNode.getJobConfigPath("0130317c30317c3054317c6c6f6769635f6462"), FileUtils.readFileToString(new File(jobConfigUrl.getFile())));
Object result = ReflectionUtil.invokeMethod(new RuleAlteredJobWorker(), "isUncompletedJobOfSameSchemaInJobList", new Class[]{String.class},
new String[]{jobConfiguration.getWorkflowConfig().getSchemaName()});
assertTrue((Boolean) result);
}

Line under review: assertNotNull(jobConfigUrl);

Code after addressing the review:
public void assertHasUncompletedJob() throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException {
final JobConfiguration jobConfiguration = JobConfigurationBuilder.createJobConfiguration();
RuleAlteredJobContext jobContext = new RuleAlteredJobContext(jobConfiguration);
jobContext.setStatus(JobStatus.PREPARING);
GovernanceRepositoryAPI repositoryAPI = PipelineAPIFactory.getGovernanceRepositoryAPI();
repositoryAPI.persistJobProgress(jobContext);
URL jobConfigUrl = getClass().getClassLoader().getResource("scaling/rule_alter/scaling_job_config.yaml");
assertNotNull(jobConfigUrl);
repositoryAPI.persist(PipelineMetaDataNode.getJobConfigPath(jobContext.getJobId()), FileUtils.readFileToString(new File(jobConfigUrl.getFile())));
Object result = ReflectionUtil.invokeMethod(new RuleAlteredJobWorker(), "isUncompletedJobOfSameSchemaInJobList", new Class[]{String.class},
new String[]{jobConfiguration.getWorkflowConfig().getSchemaName()});
assertFalse((Boolean) result);
}
Code review comment: Awaiting changes: https://github.com/ballerina-platform/ballerina-lang/pull/39509/commits/973652b34a52057d12e7ff7d57cf32da8b7fb56f from #39509.

Code before review:
public void testRegexpTemplateLiteralExpr(int sLine, int sCol, int eLine, int eCol) {
TypeSymbol type = getExprType(sLine, sCol, eLine, eCol);
assertEquals(type.typeKind(), TYPE_REFERENCE);
assertEquals(((TypeReferenceTypeSymbol) type).typeDescriptor().typeKind(), REGEXP);
}

Line under review: assertEquals(type.typeKind(), TYPE_REFERENCE);

Code after addressing the review:
public void testRegexpTemplateLiteralExpr(int sLine, int sCol, int eLine, int eCol) {
TypeSymbol type = getExprType(sLine, sCol, eLine, eCol);
assertEquals(type.typeKind(), TYPE_REFERENCE);
assertEquals(((TypeReferenceTypeSymbol) type).typeDescriptor().typeKind(), REGEXP);
}
Code review comment: The ```TaskExecutorStateChangelogStoragesManager``` behaves like ```TaskExecutorLocalStateStoresManager```. It depends on the ```releaseStateChangelogStorageForJob``` to clean up, which will be triggered in ```TaskExecutor::closeJobManagerConnectionIfNoAllocatedResources``` when the last slot of a job is released.

Code before review:
public TaskExecutorStateChangelogStoragesManager() {
this.changelogStoragesByJobId = new HashMap<>();
this.lock = new Object();
this.closed = false;
this.shutdownHook =
ShutdownHookUtil.addShutdownHook(this::shutdown, getClass().getSimpleName(), LOG);
}

Line under review: ShutdownHookUtil.addShutdownHook(this::shutdown, getClass().getSimpleName(), LOG);

Code after addressing the review:
public TaskExecutorStateChangelogStoragesManager() {
this.changelogStoragesByJobId = new HashMap<>();
this.closed = false;
this.shutdownHook =
ShutdownHookUtil.addShutdownHook(this::shutdown, getClass().getSimpleName(), LOG);
}
Code review comment: It is quite confusing,  in such cases, I think merging Limit into such an AggregationOperator seems a mistake instead of intention. 

Code before review:
public boolean check(OptExpression input, OptimizerContext context) {
LogicalLimitOperator limit = (LogicalLimitOperator) input.getOp();
Operator op = input.inputAt(0).getOp();
if (op instanceof LogicalAggregationOperator) {
LogicalAggregationOperator aggOp = op.cast();
List<CallOperator> distinctAggOperatorList = aggOp.getAggregations().values().stream()
.filter(CallOperator::isDistinct).collect(Collectors.toList());
boolean hasMultiColumns = distinctAggOperatorList.stream().anyMatch(f -> f.getChildren().size() > 1);
return (!hasMultiColumns || distinctAggOperatorList.size() > 1) && limit.isLocal();
} else {
return limit.isLocal();
}
}

Line under review: }

Code after addressing the review:
public boolean check(OptExpression input, OptimizerContext context) {
LogicalLimitOperator limit = (LogicalLimitOperator) input.getOp();
Operator op = input.inputAt(0).getOp();
if (op instanceof LogicalAggregationOperator) {
LogicalAggregationOperator aggOp = op.cast();
List<CallOperator> distinctAggOperatorList = aggOp.getAggregations().values().stream()
.filter(CallOperator::isDistinct).collect(Collectors.toList());
boolean hasMultiColumns = distinctAggOperatorList.stream().anyMatch(f -> f.getChildren().size() > 1);
return (!hasMultiColumns || distinctAggOperatorList.size() > 1) && limit.isLocal();
} else {
return limit.isLocal();
}
}
Code review comment: nit: Will LOG.error make it easier to be discovered?

Code before review:
public void waitForSuccess(Duration duration) throws IOException {
SubscriptionPath resultSubscriptionPath =
PubsubClient.subscriptionPathFromName(
pipelineOptions.getProject(),
"result-subscription-" + String.valueOf(ThreadLocalRandom.current().nextLong()));
pubsub.createSubscription(
resultTopicPath, resultSubscriptionPath, (int) duration.getStandardSeconds());
String result = pollForResultForDuration(resultSubscriptionPath, duration);
try {
pubsub.deleteSubscription(resultSubscriptionPath);
} catch (IOException e) {
LOG.warn(String.format("Leaked PubSub subscription '%s'", resultSubscriptionPath));
}
if (!RESULT_SUCCESS_MESSAGE.equals(result)) {
throw new AssertionError(result);
}
}

Line under review: LOG.warn(String.format("Leaked PubSub subscription '%s'", resultSubscriptionPath));

Code after addressing the review:
public void waitForSuccess(Duration duration) throws IOException {
SubscriptionPath resultSubscriptionPath =
PubsubClient.subscriptionPathFromName(
pipelineOptions.getProject(),
"result-subscription-" + String.valueOf(ThreadLocalRandom.current().nextLong()));
pubsub.createSubscription(
resultTopicPath, resultSubscriptionPath, (int) duration.getStandardSeconds());
String result = pollForResultForDuration(resultSubscriptionPath, duration);
try {
pubsub.deleteSubscription(resultSubscriptionPath);
} catch (IOException e) {
LOG.error(String.format("Leaked PubSub subscription '%s'", resultSubscriptionPath));
}
if (!RESULT_SUCCESS_MESSAGE.equals(result)) {
throw new AssertionError(result);
}
}
Code review comment: What's the reason for this?

Code before review:
public String getServiceProperty(TaskContext context, String unit, String property) {
return newCommandLine(context)
.add("systemctl", "show", "--property", property, "--value", unit + ".service")
.ignoreExitCode()
.execute()
.getOutput();
}

Line under review: .ignoreExitCode()

Code after addressing the review:
public String getServiceProperty(TaskContext context, String unit, String property) {
return newCommandLine(context)
.add("systemctl", "show", "--property", property, "--value", unit + ".service")
.execute()
.getOutput();
}
Code review comment: > I would prefer the cancellation mechanism to stay clean and `canceled` being set to `true` only in one place, without using exceptions for that.  Understood and I'd ideally would do that, but we already have the situation that the gates are closed before `#cancel()` has been called (or else the exception would have been swallowed by your commit). Then, the whole cleanup of Task#invoke may happen without canceled being set at all and I wouldn't be surprised to see the next issue arising.  To further emphasize, if you check `StreamTask#invoke` you'd see that if `canceled` is set, we'd skip `afterInvoke` and also take the exceptional code path. If we just swallow the exception and do not set canceled, we'd go a whole other code path.

Code before review:
private void runMailboxLoop() throws Exception {
try {
try {
mailboxProcessor.runMailboxLoop();
}
catch (WrappingRuntimeException wrappingException) {
Throwable unwrapped = wrappingException.unwrap();
if (unwrapped instanceof Exception) {
throw (Exception) unwrapped;
}
else {
throw wrappingException;
}
}
}
catch (InterruptedException e) {
if (!canceled) {
Thread.currentThread().interrupt();
throw e;
}
}
catch (CancelTaskException e) {
canceled = true;
}
catch (Exception e) {
if (canceled) {
LOG.warn("Error while canceling task.", e);
}
else {
throw e;
}
}
}

Line under review: canceled = true;

Code after addressing the review:
private void runMailboxLoop() throws Exception {
try {
try {
mailboxProcessor.runMailboxLoop();
}
catch (WrappingRuntimeException wrappingException) {
Throwable unwrapped = wrappingException.unwrap();
if (unwrapped instanceof Exception) {
throw (Exception) unwrapped;
}
else {
throw wrappingException;
}
}
}
catch (InterruptedException e) {
if (!canceled) {
Thread.currentThread().interrupt();
throw e;
}
}
catch (CancelTaskException e) {
if (!canceled) {
LOG.error("Received CancelTaskException while we are not canceled. This is a bug and should be reported", e);
}
}
catch (Exception e) {
if (canceled) {
LOG.warn("Error while canceling task.", e);
}
else {
throw e;
}
}
}