This is an automated email from the ASF dual-hosted git repository.
sanpwc pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new 938e09d0306 IGNITE-25987 Add public CLI API for partition restart with
cleanup functionality (#6513)
938e09d0306 is described below
commit 938e09d0306be3f0d87d88f1714f55102e102840
Author: Cyrill <[email protected]>
AuthorDate: Tue Sep 2 10:00:36 2025 +0300
IGNITE-25987 Add public CLI API for partition restart with cleanup
functionality (#6513)
---
.../restart/ItRestartPartitionsTest.java | 71 +++++++++++++++++++++-
.../recovery/restart/RestartPartitionsCall.java | 12 +++-
.../restart/RestartPartitionsCallInput.java | 22 ++++++-
.../ignite/internal/cli/commands/Options.java | 5 ++
.../partitions/restart/RestartPartitionsMixin.java | 10 +++
.../partitions/restart/RestartPartitionsTest.java | 64 +++++++++++++++++++
6 files changed, 179 insertions(+), 5 deletions(-)
diff --git
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/recovery/partitions/restart/ItRestartPartitionsTest.java
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/recovery/partitions/restart/ItRestartPartitionsTest.java
index 487abd5975f..f795455d85d 100644
---
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/recovery/partitions/restart/ItRestartPartitionsTest.java
+++
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/recovery/partitions/restart/ItRestartPartitionsTest.java
@@ -23,12 +23,14 @@ import static
org.apache.ignite.internal.cli.commands.Options.Constants.CLUSTER_
import static
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_NODE_NAMES_OPTION;
import static
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_PARTITION_IDS_OPTION;
import static
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_TABLE_NAME_OPTION;
+import static
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_WITH_CLEANUP_OPTION;
import static
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_ZONE_NAME_OPTION;
import static org.apache.ignite.lang.util.IgniteNameUtils.canonicalName;
import org.apache.ignite.Ignite;
import org.apache.ignite.internal.cli.CliIntegrationTest;
import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIf;
@@ -44,10 +46,11 @@ public abstract class ItRestartPartitionsTest extends
CliIntegrationTest {
@BeforeAll
public void createTables() {
- sql(String.format("CREATE ZONE \"%s\" storage profiles ['%s']", ZONE,
DEFAULT_AIPERSIST_PROFILE_NAME));
+ sql(String.format("CREATE ZONE \"%s\" (REPLICAS %s) storage profiles
['%s']", ZONE, 3, DEFAULT_AIPERSIST_PROFILE_NAME));
sql(String.format("CREATE TABLE PUBLIC.\"%s\" (id INT PRIMARY KEY, val
INT) ZONE \"%s\"", TABLE_NAME, ZONE));
}
+ @Disabled("https://issues.apache.org/jira/browse/IGNITE-26337")
@Test
public void testRestartAllPartitions() {
execute(CLUSTER_URL_OPTION, NODE_URL,
@@ -161,4 +164,70 @@ public abstract class ItRestartPartitionsTest extends
CliIntegrationTest {
DEFAULT_PARTITION_COUNT
));
}
+
+ @Disabled("https://issues.apache.org/jira/browse/IGNITE-26337")
+ @Test
+ public void testRestartAllPartitionsWithCleanup() {
+ execute(CLUSTER_URL_OPTION, NODE_URL,
+ RECOVERY_TABLE_NAME_OPTION, QUALIFIED_TABLE_NAME,
+ RECOVERY_ZONE_NAME_OPTION, ZONE,
+ RECOVERY_WITH_CLEANUP_OPTION
+ );
+
+ assertErrOutputIsEmpty();
+ assertOutputContains("Successfully restarted partitions.");
+ }
+
+ @Disabled("https://issues.apache.org/jira/browse/IGNITE-26337")
+ @Test
+ public void testRestartSpecifiedPartitionsWithCleanup() {
+ execute(CLUSTER_URL_OPTION, NODE_URL,
+ RECOVERY_TABLE_NAME_OPTION, QUALIFIED_TABLE_NAME,
+ RECOVERY_ZONE_NAME_OPTION, ZONE,
+ RECOVERY_PARTITION_IDS_OPTION, "1,2",
+ RECOVERY_WITH_CLEANUP_OPTION
+ );
+
+ assertErrOutputIsEmpty();
+ assertOutputContains("Successfully restarted partitions.");
+ }
+
+ @Disabled("https://issues.apache.org/jira/browse/IGNITE-26337")
+ @Test
+ public void testRestartPartitionsByNodesWithCleanup() {
+ String nodeNames = CLUSTER.runningNodes()
+ .limit(initialNodes() - 1)
+ .map(Ignite::name)
+ .collect(joining(","));
+
+ execute(CLUSTER_URL_OPTION, NODE_URL,
+ RECOVERY_TABLE_NAME_OPTION, QUALIFIED_TABLE_NAME,
+ RECOVERY_ZONE_NAME_OPTION, ZONE,
+ RECOVERY_PARTITION_IDS_OPTION, "1,2",
+ RECOVERY_NODE_NAMES_OPTION, nodeNames,
+ RECOVERY_WITH_CLEANUP_OPTION
+ );
+
+ assertErrOutputIsEmpty();
+ assertOutputContains("Successfully restarted partitions.");
+ }
+
+ @Test
+ public void testRestartPartitionsByNodesWithCleanupNoExecutorInNodes() {
+ String nodeNames = CLUSTER.runningNodes()
+ .skip(1)
+ .map(Ignite::name)
+ .collect(joining(","));
+
+ execute(CLUSTER_URL_OPTION, NODE_URL,
+ RECOVERY_TABLE_NAME_OPTION, QUALIFIED_TABLE_NAME,
+ RECOVERY_ZONE_NAME_OPTION, ZONE,
+ RECOVERY_PARTITION_IDS_OPTION, "1,2",
+ RECOVERY_NODE_NAMES_OPTION, nodeNames,
+ RECOVERY_WITH_CLEANUP_OPTION
+ );
+
+ assertErrOutputIsEmpty();
+ assertOutputContains("Successfully restarted partitions.");
+ }
}
diff --git
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/recovery/restart/RestartPartitionsCall.java
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/recovery/restart/RestartPartitionsCall.java
index 5c0b1f82b23..c45b98a5016 100644
---
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/recovery/restart/RestartPartitionsCall.java
+++
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/recovery/restart/RestartPartitionsCall.java
@@ -50,7 +50,11 @@ public class RestartPartitionsCall implements
Call<RestartPartitionsCallInput, S
command.setNodeNames(input.nodeNames());
command.setZoneName(input.zoneName());
- client.restartZonePartitions(command);
+ if (input.withCleanup()) {
+ client.restartZonePartitionsWithCleanup(command);
+ } else {
+ client.restartZonePartitions(command);
+ }
} else {
RestartPartitionsRequest command = new
RestartPartitionsRequest();
@@ -59,7 +63,11 @@ public class RestartPartitionsCall implements
Call<RestartPartitionsCallInput, S
command.setTableName(input.tableName());
command.setZoneName(input.zoneName());
- client.restartPartitions(command);
+ if (input.withCleanup()) {
+ client.restartPartitionsWithCleanup(command);
+ } else {
+ client.restartPartitions(command);
+ }
}
return DefaultCallOutput.success(
diff --git
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/recovery/restart/RestartPartitionsCallInput.java
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/recovery/restart/RestartPartitionsCallInput.java
index e541bef10c5..495a87fad70 100644
---
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/recovery/restart/RestartPartitionsCallInput.java
+++
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/recovery/restart/RestartPartitionsCallInput.java
@@ -34,6 +34,8 @@ public class RestartPartitionsCallInput implements CallInput {
private final List<Integer> partitionIds;
+ private final boolean withCleanup;
+
/** Cluster url. */
public String clusterUrl() {
return clusterUrl;
@@ -59,18 +61,25 @@ public class RestartPartitionsCallInput implements
CallInput {
return nodeNames;
}
+ /** Whether to restart partitions with cleanup. */
+ public boolean withCleanup() {
+ return withCleanup;
+ }
+
private RestartPartitionsCallInput(
String clusterUrl,
String zoneName,
String tableName,
@Nullable List<Integer> partitionIds,
- @Nullable List<String> nodeNames
+ @Nullable List<String> nodeNames,
+ boolean withCleanup
) {
this.clusterUrl = clusterUrl;
this.zoneName = zoneName;
this.tableName = tableName;
this.partitionIds = partitionIds == null ? List.of() :
List.copyOf(partitionIds);
this.nodeNames = nodeNames == null ? List.of() :
List.copyOf(nodeNames);
+ this.withCleanup = withCleanup;
}
/** Returns {@link RestartPartitionsCallInput} with specified arguments. */
@@ -80,6 +89,7 @@ public class RestartPartitionsCallInput implements CallInput {
.tableName(restartArgs.tableName())
.partitionIds(restartArgs.partitionIds())
.nodeNames(restartArgs.nodeNames())
+ .withCleanup(restartArgs.withCleanup())
.clusterUrl(clusterUrl)
.build();
}
@@ -107,6 +117,8 @@ public class RestartPartitionsCallInput implements
CallInput {
@Nullable
private List<String> nodeNames;
+ private boolean withCleanup;
+
/** Set cluster URL. */
RestartPartitionsCallInputBuilder clusterUrl(String clusterUrl) {
this.clusterUrl = clusterUrl;
@@ -137,9 +149,15 @@ public class RestartPartitionsCallInput implements
CallInput {
return this;
}
+ /** Set whether to restart partitions with cleanup. */
+ RestartPartitionsCallInputBuilder withCleanup(boolean withCleanup) {
+ this.withCleanup = withCleanup;
+ return this;
+ }
+
/** Build {@link RestartPartitionsCallInput}. */
RestartPartitionsCallInput build() {
- return new RestartPartitionsCallInput(clusterUrl, zoneName,
tableName, partitionIds, nodeNames);
+ return new RestartPartitionsCallInput(clusterUrl, zoneName,
tableName, partitionIds, nodeNames, withCleanup);
}
}
}
diff --git
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/Options.java
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/Options.java
index e225a3e536c..a64ebf215fc 100644
---
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/Options.java
+++
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/Options.java
@@ -307,6 +307,11 @@ public enum Options {
+ "'--cluster-management-group node1, node2' "
+ "to specify more than one node) that will host the Cluster
Management Group.";
+ public static final String RECOVERY_WITH_CLEANUP_OPTION =
"--with-cleanup";
+
+ public static final String RECOVERY_WITH_CLEANUP_OPTION_DESC =
"Restarts partitions, preceded by a storage cleanup. "
+ + "This will remove all data from the partition storages
before restart.";
+
/** Old cluster endpoint URL option long name. */
public static final String RECOVERY_OLD_CLUSTER_URL_OPTION =
"--old-cluster-url";
diff --git
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/recovery/partitions/restart/RestartPartitionsMixin.java
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/recovery/partitions/restart/RestartPartitionsMixin.java
index 6527418d881..5ec51ebc23f 100644
---
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/recovery/partitions/restart/RestartPartitionsMixin.java
+++
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/recovery/partitions/restart/RestartPartitionsMixin.java
@@ -23,6 +23,8 @@ import static
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY
import static
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_PARTITION_IDS_OPTION_DESC;
import static
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_TABLE_NAME_OPTION;
import static
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_TABLE_NAME_OPTION_DESC;
+import static
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_WITH_CLEANUP_OPTION;
+import static
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_WITH_CLEANUP_OPTION_DESC;
import static
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_ZONE_NAME_OPTION;
import static
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_ZONE_NAME_OPTION_DESC;
@@ -44,6 +46,9 @@ public class RestartPartitionsMixin {
@Option(names = RECOVERY_TABLE_NAME_OPTION, description =
RECOVERY_TABLE_NAME_OPTION_DESC, required = true)
private String tableName;
+ @Option(names = RECOVERY_WITH_CLEANUP_OPTION, description =
RECOVERY_WITH_CLEANUP_OPTION_DESC)
+ private boolean withCleanup;
+
/** Returns name of the zone to restart partitions of. */
public String zoneName() {
return zoneName;
@@ -65,4 +70,9 @@ public class RestartPartitionsMixin {
public List<String> nodeNames() {
return nodeNames;
}
+
+ /** Returns whether to restart partitions with cleanup. */
+ public boolean withCleanup() {
+ return withCleanup;
+ }
}
diff --git
a/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/recovery/partitions/restart/RestartPartitionsTest.java
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/recovery/partitions/restart/RestartPartitionsTest.java
index bf69f75af2c..cc5a9f2d689 100644
---
a/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/recovery/partitions/restart/RestartPartitionsTest.java
+++
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/recovery/partitions/restart/RestartPartitionsTest.java
@@ -21,6 +21,7 @@ import static
org.apache.ignite.internal.cli.commands.Options.Constants.CLUSTER_
import static
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_NODE_NAMES_OPTION;
import static
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_PARTITION_IDS_OPTION;
import static
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_TABLE_NAME_OPTION;
+import static
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_WITH_CLEANUP_OPTION;
import static
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_ZONE_NAME_OPTION;
import static
org.apache.ignite.internal.lang.IgniteSystemProperties.colocationEnabled;
import static org.mockserver.matchers.MatchType.ONLY_MATCHING_FIELDS;
@@ -38,10 +39,12 @@ import org.mockserver.model.MediaType;
/** Unit tests for {@link RestartPartitionsCommand}. */
public class RestartPartitionsTest extends IgniteCliInterfaceTestBase {
private static String PARTITIONS_RESTART_ENDPOINT;
+ private static String PARTITIONS_RESTART_ENDPOINT_WITH_CLEANUP;
@BeforeAll
public static void beforeAll() {
PARTITIONS_RESTART_ENDPOINT = "partitions/restart";
+ PARTITIONS_RESTART_ENDPOINT_WITH_CLEANUP =
"partitions/restartWithCleanup";
}
@Test
@@ -127,6 +130,67 @@ public class RestartPartitionsTest extends
IgniteCliInterfaceTestBase {
assertOutputIs("Successfully restarted partitions.");
}
+ @Test
+ @DisplayName("Restart all partitions with cleanup")
+ void restartAllPartitionsWithCleanup() {
+ String expectedSentContent;
+
+ if (colocationEnabled()) {
+ expectedSentContent = "{"
+ + " \"zoneName\" : \"zone_NAME\""
+ + "}";
+
+ } else {
+ expectedSentContent = "{"
+ + " \"tableName\" : \"table_NAME\","
+ + " \"zoneName\" : \"zone_NAME\""
+ + "}";
+ }
+
+ clientAndServer
+ .when(request()
+ .withMethod("POST")
+ .withPath("/management/v1/recovery/" +
PARTITIONS_RESTART_ENDPOINT_WITH_CLEANUP)
+ .withBody(json(expectedSentContent))
+ .withContentType(MediaType.APPLICATION_JSON_UTF_8)
+ )
+ .respond(response(null));
+
+ execute(CLUSTER_URL_OPTION, mockUrl,
+ RECOVERY_TABLE_NAME_OPTION, "table_NAME",
+ RECOVERY_ZONE_NAME_OPTION, "zone_NAME",
+ RECOVERY_WITH_CLEANUP_OPTION
+ );
+
+ assertErrOutputIsEmpty();
+ assertOutputIs("Successfully restarted partitions.");
+ }
+
+ @Test
+ @DisplayName("Restart specified partitions with cleanup")
+ void restartSpecifiedPartitionsWithCleanup() {
+ String expectedSentContent = "{\"partitionIds\" : [1,2]}";
+
+ clientAndServer
+ .when(request()
+ .withMethod("POST")
+ .withPath("/management/v1/recovery/" +
PARTITIONS_RESTART_ENDPOINT_WITH_CLEANUP)
+ .withBody(json(expectedSentContent,
ONLY_MATCHING_FIELDS))
+ .withContentType(MediaType.APPLICATION_JSON_UTF_8)
+ )
+ .respond(response(null));
+
+ execute(CLUSTER_URL_OPTION, mockUrl,
+ RECOVERY_TABLE_NAME_OPTION, "table_NAME",
+ RECOVERY_ZONE_NAME_OPTION, "zone_NAME",
+ RECOVERY_PARTITION_IDS_OPTION, "1,2",
+ RECOVERY_WITH_CLEANUP_OPTION
+ );
+
+ assertErrOutputIsEmpty();
+ assertOutputIs("Successfully restarted partitions.");
+ }
+
@Override
protected void execute(String... args) {
String[] fullArgs = ArrayUtils.concat(new String[] {"recovery",
"partitions", "restart"}, args);