sarankk commented on code in PR #272: URL: https://github.com/apache/cassandra-sidecar/pull/272#discussion_r2669792246
########## adapters/adapters-base/src/main/java/org/apache/cassandra/sidecar/adapters/base/CompactionType.java: ########## @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cassandra.sidecar.adapters.base; + +import java.util.Locale; + +import com.fasterxml.jackson.annotation.JsonCreator; + +/** + * Supported compaction types based on Cassandra's OperationType enum + */ +public enum CompactionType +{ + CLEANUP, + SCRUB, + UPGRADE_SSTABLES, + VERIFY, + RELOCATE, + GARBAGE_COLLECT, + ANTICOMPACTION, + VALIDATION, + INDEX_BUILD, + VIEW_BUILD, + COMPACTION, + TOMBSTONE_COMPACTION, + KEY_CACHE_SAVE, + ROW_CACHE_SAVE, + COUNTER_CACHE_SAVE, + INDEX_SUMMARY; + + @Override + public String toString() + { + return name(); + } + + /** + * Case-insensitive factory method for Jackson deserialization + * @return {@link CompactionType} from string + */ + @JsonCreator + public static CompactionType fromString(String name) + { + if (name == null || name.trim().isEmpty()) + { + return null; + } + try + { + return valueOf(name.trim().toUpperCase(Locale.ROOT)); + } + catch (IllegalArgumentException unknownEnum) + { + String validTypes = String.join(", ", Review Comment: Nit: create this list once ########## adapters/adapters-cassandra41/src/main/java/org/apache/cassandra/sidecar/adapters/cassandra41/Cassandra41Factory.java: ########## @@ -31,9 +31,9 @@ import org.apache.cassandra.sidecar.db.schema.TableSchemaFetcher; /** - * Factory to produce the 4.1 adapter + * Factory to produce the Cassandra 4.x adapter */ -@MinimumVersion("4.1.0") +@MinimumVersion("4.0.0") Review Comment: We should keep the 4.1 factory as is. Can you revert changes here. ########## adapters/adapters-cassandra50/src/main/java/org/apache/cassandra/sidecar/adapters/cassandra50/CompactionType.java: ########## @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cassandra.sidecar.adapters.cassandra50; + +import java.util.Locale; + +import com.fasterxml.jackson.annotation.JsonCreator; + +/** + * Supported compaction types based on Cassandra's OperationType enum + */ +public enum CompactionType +{ + CLEANUP, + SCRUB, + UPGRADE_SSTABLES, + VERIFY, + RELOCATE, + GARBAGE_COLLECT, + ANTICOMPACTION, + VALIDATION, + INDEX_BUILD, + VIEW_BUILD, + COMPACTION, + TOMBSTONE_COMPACTION, + KEY_CACHE_SAVE, + ROW_CACHE_SAVE, + COUNTER_CACHE_SAVE, + INDEX_SUMMARY, + MAJOR_COMPACTION; Review Comment: 👍 ########## adapters/adapters-base/src/main/java/org/apache/cassandra/sidecar/adapters/base/CassandraCompactionManagerOperations.java: ########## @@ -53,4 +55,56 @@ public List<Map<String, String>> getCompactions() return jmxClient.proxy(CompactionManagerJmxOperations.class, COMPACTION_MANAGER_OBJ_NAME) .getCompactions(); } + + /** + * {@inheritDoc} + */ + @Override + public void stopCompactionById(String compactionId) + { + // compactionId takes precedence over type if both are provided + if (compactionId != null && !compactionId.trim().isEmpty()) + { + CompactionManagerJmxOperations proxy = jmxClient.proxy(CompactionManagerJmxOperations.class, + COMPACTION_MANAGER_OBJ_NAME); + proxy.stopCompactionById(compactionId); + } + else + { + throw new IllegalArgumentException("compaction process with compaction ID " + + compactionId + " is null or empty"); + } + } + + @Override + public void stopCompaction(String compactionType) + { + if (compactionType != null && !compactionType.trim().isEmpty()) + { + if (supportedCompactionTypes().contains(compactionType)) + { + CompactionManagerJmxOperations proxy = jmxClient.proxy(CompactionManagerJmxOperations.class, + COMPACTION_MANAGER_OBJ_NAME); + String errMsg + = "compaction process with compaction type " + compactionType + " must not be null when compactionId is not provided"; + proxy.stopCompaction(Objects.requireNonNull(compactionType, errMsg)); + } + else + { + throw new IllegalArgumentException("compaction type " + compactionType + " is not supported"); + } + } + else + { + throw new IllegalArgumentException("compaction type " + compactionType + " is null or empty"); + } + } + + @Override + public List<String> supportedCompactionTypes() + { + return Arrays.stream(CompactionType.values()) Review Comment: Instead of creating a stream of values each time, can you compute it once and return it? ########## client-common/src/main/java/org/apache/cassandra/sidecar/common/response/CompactionStopResponse.java: ########## @@ -0,0 +1,169 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.cassandra.sidecar.common.response; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.apache.cassandra.sidecar.common.DataObjectBuilder; +import org.apache.cassandra.sidecar.common.data.CompactionStopStatus; + +/** + * Response class for the Compaction Stop API + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class CompactionStopResponse +{ + public static final String COMPACTION_TYPE_KEY = "compactionType"; Review Comment: Nit: can you use these String constants in request payload class too? ########## adapters/adapters-base/src/test/java/org/apache/cassandra/sidecar/adapters/base/CassandraCompactionManagerOperationsTest.java: ########## @@ -0,0 +1,115 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.cassandra.sidecar.adapters.base; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import org.apache.cassandra.sidecar.adapters.base.jmx.CompactionManagerJmxOperations; +import org.apache.cassandra.sidecar.common.server.JmxClient; + +import static org.apache.cassandra.sidecar.adapters.base.jmx.CompactionManagerJmxOperations.COMPACTION_MANAGER_OBJ_NAME; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * Tests for {@link CassandraCompactionManagerOperations} class + */ +class CassandraCompactionManagerOperationsTest +{ + private CassandraCompactionManagerOperations compactionManagerOperations; + private JmxClient mockJmxClient; + private CompactionManagerJmxOperations mockJmxOperations; + + @BeforeEach + void setUp() + { + mockJmxClient = mock(JmxClient.class); + mockJmxOperations = mock(CompactionManagerJmxOperations.class); + compactionManagerOperations = new CassandraCompactionManagerOperations(mockJmxClient); + + // Setup JMX proxy mock + when(mockJmxClient.proxy(CompactionManagerJmxOperations.class, COMPACTION_MANAGER_OBJ_NAME)) + .thenReturn(mockJmxOperations); + } + + @Test + void testStopCompactionByIdOnly() + { + // Test stopCompactionById called when providing compactionId + String compactionId = "abc-123"; + compactionManagerOperations.stopCompactionById(compactionId); + + verify(mockJmxOperations, times(1)).stopCompactionById(compactionId); + verify(mockJmxOperations, times(0)).stopCompaction(org.mockito.ArgumentMatchers.anyString()); + } + + @Test + void testStopCompactionByTypeOnly() + { + // Test stopCompaction called when no compactionId provided + String compactionType = "COMPACTION"; + compactionManagerOperations.stopCompaction(compactionType); + + verify(mockJmxOperations, times(1)).stopCompaction(compactionType); + verify(mockJmxOperations, times(0)).stopCompactionById(org.mockito.ArgumentMatchers.anyString()); + } + + @Test + void testStopCompactionByIdWithWhitespace() + { + // Test trim does not result in empty string + String compactionId = " abc-123 "; + compactionManagerOperations.stopCompactionById(compactionId); + + verify(mockJmxOperations, times(1)).stopCompactionById(compactionId); + verify(mockJmxOperations, times(0)).stopCompaction(org.mockito.ArgumentMatchers.anyString()); + } + + @Test + void testStopCompactionAllSupportedTypes() Review Comment: Can you add a test case for unsupported compaction type? ########## adapters/adapters-base/src/main/java/org/apache/cassandra/sidecar/adapters/base/CassandraFactory.java: ########## @@ -31,9 +31,9 @@ import org.apache.cassandra.sidecar.db.schema.TableSchemaFetcher; /** - * Factory to produce the 4.0 adapter + * Factory to produce the Cassandra 5.x adapter */ -@MinimumVersion("4.0.0") +@MinimumVersion("5.0.0") Review Comment: `adapters-base` should still support 4.0.0 version, can you revert changes in this class? We will use the `Cassandra50Factory` you added for 5.0 version ########## adapters/adapters-cassandra50/src/main/java/org/apache/cassandra/sidecar/adapters/cassandra50/CompactionType.java: ########## @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cassandra.sidecar.adapters.cassandra50; + +import java.util.Locale; + +import com.fasterxml.jackson.annotation.JsonCreator; + +/** + * Supported compaction types based on Cassandra's OperationType enum + */ +public enum CompactionType +{ + CLEANUP, + SCRUB, + UPGRADE_SSTABLES, + VERIFY, + RELOCATE, + GARBAGE_COLLECT, + ANTICOMPACTION, + VALIDATION, + INDEX_BUILD, + VIEW_BUILD, + COMPACTION, + TOMBSTONE_COMPACTION, + KEY_CACHE_SAVE, + ROW_CACHE_SAVE, + COUNTER_CACHE_SAVE, + INDEX_SUMMARY, + MAJOR_COMPACTION; + + @Override + public String toString() + { + return name(); + } + + /** + * Case-insensitive factory method for Jackson deserialization + * @return {@link CompactionType} from string + */ + @JsonCreator + public static CompactionType fromString(String name) + { + if (name == null || name.trim().isEmpty()) + { + return null; + } + try + { + return valueOf(name.trim().toUpperCase(Locale.ROOT)); + } + catch (IllegalArgumentException unknownEnum) + { + String validTypes = String.join(", ", Review Comment: Nit: compute this once. ########## adapters/adapters-cassandra41/src/main/java/org/apache/cassandra/sidecar/adapters/cassandra41/Cassandra41CompactionManagerOperations.java: ########## @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.cassandra.sidecar.adapters.cassandra41; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.cassandra.sidecar.adapters.base.CassandraCompactionManagerOperations; +import org.apache.cassandra.sidecar.common.server.JmxClient; + +/** + * Cassandra 4.1 implementation of CompactionManagerOperations that excludes MAJOR_COMPACTION + * which is not supported in Cassandra 4.x versions + */ +public class Cassandra41CompactionManagerOperations extends CassandraCompactionManagerOperations Review Comment: Related to earlier comment, this class is not required. ########## adapters/adapters-cassandra41/src/main/java/org/apache/cassandra/sidecar/adapters/cassandra41/CompactionType.java: ########## @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cassandra.sidecar.adapters.cassandra41; + +import java.util.Locale; + +import com.fasterxml.jackson.annotation.JsonCreator; + +/** + * Supported compaction types based on Cassandra's OperationType enum + */ +public enum CompactionType Review Comment: Supported compaction types seem to be same for 4.1 and 4.0, we can reuse 4.0's types instead of maintaining a separate list. Can you remove changes in 4.1 adpator classes? ########## adapters/adapters-cassandra50/src/main/java/org/apache/cassandra/sidecar/adapters/cassandra50/Cassandra50StorageOperations.java: ########## @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.cassandra.sidecar.adapters.cassandra50; + +import java.util.Map; + +import org.apache.cassandra.sidecar.adapters.base.CassandraStorageOperations; +import org.apache.cassandra.sidecar.adapters.base.RingProvider; +import org.apache.cassandra.sidecar.adapters.base.TokenRangeReplicaProvider; +import org.apache.cassandra.sidecar.adapters.base.jmx.StorageJmxOperations; +import org.apache.cassandra.sidecar.common.server.JmxClient; +import org.apache.cassandra.sidecar.common.server.StorageOperations; +import org.apache.cassandra.sidecar.common.server.dns.DnsResolver; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import static org.apache.cassandra.sidecar.adapters.base.jmx.StorageJmxOperations.STORAGE_SERVICE_OBJ_NAME; + +/** + * An implementation of the {@link StorageOperations} that interfaces with Cassandra 5.0 and later + */ +public class Cassandra50StorageOperations extends CassandraStorageOperations Review Comment: can you extend from `Cassandra41StorageOperations`. You need not override the 2 methods if we extend from 4.1 ########## adapters/adapters-cassandra50/src/main/java/org/apache/cassandra/sidecar/adapters/cassandra50/Cassandra50Adapter.java: ########## @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.cassandra.sidecar.adapters.cassandra50; + +import java.net.InetSocketAddress; + +import org.apache.cassandra.sidecar.adapters.base.CassandraAdapter; +import org.apache.cassandra.sidecar.common.server.CQLSessionProvider; +import org.apache.cassandra.sidecar.common.server.CompactionManagerOperations; +import org.apache.cassandra.sidecar.common.server.ICassandraAdapter; +import org.apache.cassandra.sidecar.common.server.JmxClient; +import org.apache.cassandra.sidecar.common.server.StorageOperations; +import org.apache.cassandra.sidecar.common.server.dns.DnsResolver; +import org.apache.cassandra.sidecar.common.server.utils.DriverUtils; +import org.apache.cassandra.sidecar.db.schema.TableSchemaFetcher; +import org.jetbrains.annotations.NotNull; + +/** + * A {@link ICassandraAdapter} implementation for Cassandra 4.x Review Comment: Can you update comment to say correct version? ########## adapters/adapters-cassandra41/src/main/java/org/apache/cassandra/sidecar/adapters/cassandra41/Cassandra41Adapter.java: ########## @@ -31,7 +32,7 @@ import org.jetbrains.annotations.NotNull; /** - * A {@link ICassandraAdapter} implementation for Cassandra 4.1 and later + * A {@link ICassandraAdapter} implementation for Cassandra 4.x Review Comment: Supported compaction types list seem to be same between 4.0 and 4.1. We need not maintain `CompactionType` separately for 4.1, it can reuse 4.0's types. Can you revert changes in this class too? ########## server-common/src/main/java/org/apache/cassandra/sidecar/common/server/CompactionManagerOperations.java: ########## @@ -32,4 +32,23 @@ public interface CompactionManagerOperations * @return list of compaction info maps */ List<Map<String, String>> getCompactions(); + + /** + * Stops compaction based on compaction ID. + * This method takes precedence over stopCompaction if both type and ID are provided. + * + * @param compactionId the compaction ID to stop (nullable) + * @throws IllegalArgumentException if both parameters are null or empty + */ + void stopCompactionById(String compactionId); + + /** + * Stops compaction based on type if no compaction ID is provided. + * + * @param compactionType the compaction ID to stop (nullable) + * @throws IllegalArgumentException if both parameters are null or empty, or of the provided compactionType is unsupported + */ + void stopCompaction(String compactionType); + + List<String> supportedCompactionTypes(); Review Comment: Can you add java doc for this method too to add a note on how types can differ between versions ########## adapters/adapters-cassandra50/src/main/java/org/apache/cassandra/sidecar/adapters/cassandra50/Cassandra50CompactionManagerOperations.java: ########## @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.cassandra.sidecar.adapters.cassandra50; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.cassandra.sidecar.adapters.base.CassandraCompactionManagerOperations; +import org.apache.cassandra.sidecar.common.server.JmxClient; + +/** + * Cassandra 5.0 implementation of CompactionManagerOperations that supports MAJOR_COMPACTION + * which is only available in Cassandra 5.x versions + */ +public class Cassandra50CompactionManagerOperations extends CassandraCompactionManagerOperations +{ + /** + * Creates a new instance with the provided {@link JmxClient} + * + * @param jmxClient the JMX client used to communicate with the Cassandra instance + */ + public Cassandra50CompactionManagerOperations(JmxClient jmxClient) + { + super(jmxClient); + } + + /** + * {@inheritDoc} + * + * Cassandra 5.x supports MAJOR_COMPACTION operation type + */ + @Override + public List<String> supportedCompactionTypes() + { + return Arrays.stream(CompactionType.values()) Review Comment: Nit: compute this once ########## server/src/main/java/org/apache/cassandra/sidecar/handlers/CompactionStopHandler.java: ########## @@ -0,0 +1,175 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.cassandra.sidecar.handlers; + +import java.util.Collections; +import java.util.Set; + +import com.google.inject.Inject; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.vertx.core.http.HttpServerRequest; +import io.vertx.core.json.DecodeException; +import io.vertx.core.json.Json; +import io.vertx.core.net.SocketAddress; +import io.vertx.ext.auth.authorization.Authorization; +import io.vertx.ext.web.RoutingContext; +import org.apache.cassandra.sidecar.acl.authorization.BasicPermissions; +import org.apache.cassandra.sidecar.common.data.CompactionStopStatus; +import org.apache.cassandra.sidecar.common.request.data.CompactionStopRequestPayload; +import org.apache.cassandra.sidecar.common.response.CompactionStopResponse; +import org.apache.cassandra.sidecar.common.server.CompactionManagerOperations; +import org.apache.cassandra.sidecar.concurrent.ExecutorPools; +import org.apache.cassandra.sidecar.utils.CassandraInputValidator; +import org.apache.cassandra.sidecar.utils.InstanceMetadataFetcher; +import org.jetbrains.annotations.NotNull; + +import static org.apache.cassandra.sidecar.utils.HttpExceptions.wrapHttpException; + +/** + * Handler for stopping compaction operations via the Cassandra Compaction Manager. + * + * <p>Handles {@code PUT /api/v1/cassandra/operations/compaction/stop} requests to stop + * compaction operations. Expects a JSON payload with compactionType and/or compactionId: + * <pre> + * { "compactionType": "COMPACTION", "compactionId": "abc-123" } + * </pre> + */ +public class CompactionStopHandler extends AbstractHandler<CompactionStopRequestPayload> implements AccessProtected +{ + /** + * Constructs a handler with the provided {@code metadataFetcher} + * + * @param metadataFetcher the metadata fetcher + * @param executorPools executor pools for blocking executions + * @param validator validator for Cassandra-specific input + */ + @Inject + protected CompactionStopHandler(final InstanceMetadataFetcher metadataFetcher, + final ExecutorPools executorPools, + final CassandraInputValidator validator) + { + super(metadataFetcher, executorPools, validator); + } + + @Override + public Set<Authorization> requiredAuthorizations() + { + return Collections.singleton(BasicPermissions.MODIFY_COMPACTION.toAuthorization()); + } + + /** + * {@inheritDoc} + */ + @Override + public void handleInternal(RoutingContext context, + HttpServerRequest httpRequest, + @NotNull String host, + SocketAddress remoteAddress, + CompactionStopRequestPayload request) + { + CompactionManagerOperations compactionManagerOps = metadataFetcher.delegate(host).compactionManagerOperations(); + + executorPools.service() + .executeBlocking(() -> stopCompaction(compactionManagerOps, request)) + .onSuccess(context::json) + .onFailure(cause -> processFailure(cause, context, host, remoteAddress, request)); + } + + /** + * Stops the compaction based on the request parameters + * + * @param operations the compaction manager operations + * @param request the request payload containing compactionType and/or compactionId + * @return CompactionStopResponse with the operation result + */ + private CompactionStopResponse stopCompaction(CompactionManagerOperations operations, + CompactionStopRequestPayload request) + { + String compactionType = request.compactionType(); + String compactionId = request.compactionId(); + + // Validate compaction type supported by this Cassandra version + if (compactionType != null && !operations.supportedCompactionTypes().contains(compactionType)) + { + throw new IllegalArgumentException( + String.format("Compaction type '%s' not supported in this Cassandra version. " + + "Supported types: %s", Review Comment: Nit: incorrect alignment ########## adapters/adapters-cassandra50/src/main/java/org/apache/cassandra/sidecar/adapters/cassandra50/Cassandra50CompactionManagerOperations.java: ########## @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.cassandra.sidecar.adapters.cassandra50; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.cassandra.sidecar.adapters.base.CassandraCompactionManagerOperations; +import org.apache.cassandra.sidecar.common.server.JmxClient; + +/** + * Cassandra 5.0 implementation of CompactionManagerOperations that supports MAJOR_COMPACTION + * which is only available in Cassandra 5.x versions + */ +public class Cassandra50CompactionManagerOperations extends CassandraCompactionManagerOperations +{ + /** + * Creates a new instance with the provided {@link JmxClient} + * + * @param jmxClient the JMX client used to communicate with the Cassandra instance + */ + public Cassandra50CompactionManagerOperations(JmxClient jmxClient) + { + super(jmxClient); + } + + /** + * {@inheritDoc} + * + * Cassandra 5.x supports MAJOR_COMPACTION operation type + */ + @Override + public List<String> supportedCompactionTypes() Review Comment: 👍 ########## server/src/main/java/org/apache/cassandra/sidecar/handlers/CompactionStopHandler.java: ########## @@ -0,0 +1,175 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.cassandra.sidecar.handlers; + +import java.util.Collections; +import java.util.Set; + +import com.google.inject.Inject; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.vertx.core.http.HttpServerRequest; +import io.vertx.core.json.DecodeException; +import io.vertx.core.json.Json; +import io.vertx.core.net.SocketAddress; +import io.vertx.ext.auth.authorization.Authorization; +import io.vertx.ext.web.RoutingContext; +import org.apache.cassandra.sidecar.acl.authorization.BasicPermissions; +import org.apache.cassandra.sidecar.common.data.CompactionStopStatus; +import org.apache.cassandra.sidecar.common.request.data.CompactionStopRequestPayload; +import org.apache.cassandra.sidecar.common.response.CompactionStopResponse; +import org.apache.cassandra.sidecar.common.server.CompactionManagerOperations; +import org.apache.cassandra.sidecar.concurrent.ExecutorPools; +import org.apache.cassandra.sidecar.utils.CassandraInputValidator; +import org.apache.cassandra.sidecar.utils.InstanceMetadataFetcher; +import org.jetbrains.annotations.NotNull; + +import static org.apache.cassandra.sidecar.utils.HttpExceptions.wrapHttpException; + +/** + * Handler for stopping compaction operations via the Cassandra Compaction Manager. + * + * <p>Handles {@code PUT /api/v1/cassandra/operations/compaction/stop} requests to stop + * compaction operations. Expects a JSON payload with compactionType and/or compactionId: + * <pre> + * { "compactionType": "COMPACTION", "compactionId": "abc-123" } + * </pre> + */ +public class CompactionStopHandler extends AbstractHandler<CompactionStopRequestPayload> implements AccessProtected +{ + /** + * Constructs a handler with the provided {@code metadataFetcher} + * + * @param metadataFetcher the metadata fetcher + * @param executorPools executor pools for blocking executions + * @param validator validator for Cassandra-specific input + */ + @Inject + protected CompactionStopHandler(final InstanceMetadataFetcher metadataFetcher, + final ExecutorPools executorPools, + final CassandraInputValidator validator) + { + super(metadataFetcher, executorPools, validator); + } + + @Override + public Set<Authorization> requiredAuthorizations() + { + return Collections.singleton(BasicPermissions.MODIFY_COMPACTION.toAuthorization()); + } + + /** + * {@inheritDoc} + */ + @Override + public void handleInternal(RoutingContext context, + HttpServerRequest httpRequest, + @NotNull String host, + SocketAddress remoteAddress, + CompactionStopRequestPayload request) + { + CompactionManagerOperations compactionManagerOps = metadataFetcher.delegate(host).compactionManagerOperations(); + + executorPools.service() + .executeBlocking(() -> stopCompaction(compactionManagerOps, request)) + .onSuccess(context::json) + .onFailure(cause -> processFailure(cause, context, host, remoteAddress, request)); + } + + /** + * Stops the compaction based on the request parameters + * + * @param operations the compaction manager operations + * @param request the request payload containing compactionType and/or compactionId + * @return CompactionStopResponse with the operation result + */ + private CompactionStopResponse stopCompaction(CompactionManagerOperations operations, + CompactionStopRequestPayload request) + { + String compactionType = request.compactionType(); + String compactionId = request.compactionId(); + + // Validate compaction type supported by this Cassandra version + if (compactionType != null && !operations.supportedCompactionTypes().contains(compactionType)) Review Comment: Since we are performing this check in stopCompaction call, we need not repeat it here again ########## server/src/main/java/org/apache/cassandra/sidecar/handlers/CompactionStopHandler.java: ########## @@ -0,0 +1,175 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.cassandra.sidecar.handlers; + +import java.util.Collections; +import java.util.Set; + +import com.google.inject.Inject; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.vertx.core.http.HttpServerRequest; +import io.vertx.core.json.DecodeException; +import io.vertx.core.json.Json; +import io.vertx.core.net.SocketAddress; +import io.vertx.ext.auth.authorization.Authorization; +import io.vertx.ext.web.RoutingContext; +import org.apache.cassandra.sidecar.acl.authorization.BasicPermissions; +import org.apache.cassandra.sidecar.common.data.CompactionStopStatus; +import org.apache.cassandra.sidecar.common.request.data.CompactionStopRequestPayload; +import org.apache.cassandra.sidecar.common.response.CompactionStopResponse; +import org.apache.cassandra.sidecar.common.server.CompactionManagerOperations; +import org.apache.cassandra.sidecar.concurrent.ExecutorPools; +import org.apache.cassandra.sidecar.utils.CassandraInputValidator; +import org.apache.cassandra.sidecar.utils.InstanceMetadataFetcher; +import org.jetbrains.annotations.NotNull; + +import static org.apache.cassandra.sidecar.utils.HttpExceptions.wrapHttpException; + +/** + * Handler for stopping compaction operations via the Cassandra Compaction Manager. + * + * <p>Handles {@code PUT /api/v1/cassandra/operations/compaction/stop} requests to stop + * compaction operations. Expects a JSON payload with compactionType and/or compactionId: + * <pre> + * { "compactionType": "COMPACTION", "compactionId": "abc-123" } + * </pre> + */ +public class CompactionStopHandler extends AbstractHandler<CompactionStopRequestPayload> implements AccessProtected +{ + /** + * Constructs a handler with the provided {@code metadataFetcher} + * + * @param metadataFetcher the metadata fetcher + * @param executorPools executor pools for blocking executions + * @param validator validator for Cassandra-specific input + */ + @Inject + protected CompactionStopHandler(final InstanceMetadataFetcher metadataFetcher, + final ExecutorPools executorPools, + final CassandraInputValidator validator) + { + super(metadataFetcher, executorPools, validator); + } + + @Override + public Set<Authorization> requiredAuthorizations() + { + return Collections.singleton(BasicPermissions.MODIFY_COMPACTION.toAuthorization()); + } + + /** + * {@inheritDoc} + */ + @Override + public void handleInternal(RoutingContext context, + HttpServerRequest httpRequest, + @NotNull String host, + SocketAddress remoteAddress, + CompactionStopRequestPayload request) + { + CompactionManagerOperations compactionManagerOps = metadataFetcher.delegate(host).compactionManagerOperations(); + + executorPools.service() + .executeBlocking(() -> stopCompaction(compactionManagerOps, request)) Review Comment: Nit: incorrect alignment -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]

