This is an automated email from the ASF dual-hosted git repository.
nizhikov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new ef685f5c312 IGNITE-28243 Keep service descriptor even if no
deployments (#12910)
ef685f5c312 is described below
commit ef685f5c3121701c21fd4f8023c48b2417ad5f52
Author: Nikolay <[email protected]>
AuthorDate: Thu Mar 19 14:35:35 2026 +0300
IGNITE-28243 Keep service descriptor even if no deployments (#12910)
Some users implements the following scenario:
1. Starts sever node (configuration node), first, with the service
configuration. NodeFilter like `n -> n.isClient()`.
2. Starts client nodes that hosts service. Count of the clients depends
on the expected workload.
This case was broken in the 66a4a2d876aad528ee1be35d8711441ecdfdf97b
This PR fix regression.
---
.../processors/service/IgniteServiceProcessor.java | 10 ---
.../IgniteServiceDeployOnJoinedNodeTest.java | 94 ++++++++++++++++++++++
.../IgniteServiceDeploymentFailureTest.java | 31 ++++---
.../testsuites/IgniteServiceGridTestSuite.java | 2 +
4 files changed, 118 insertions(+), 19 deletions(-)
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/IgniteServiceProcessor.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/IgniteServiceProcessor.java
index 287f36c1262..4cf6bd74c26 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/IgniteServiceProcessor.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/IgniteServiceProcessor.java
@@ -1579,16 +1579,6 @@ public class IgniteServiceProcessor extends
GridProcessorAdapter implements Igni
try {
updateServicesMap(deployedServices, fullTops);
-
- for (Map.Entry<IgniteUuid, Map<UUID, Integer>> e :
fullTops.entrySet()) {
- // Checking if there are successful deployments.
- // If none, service not deployed and must be removed from
descriptors.
- if (e.getValue().entrySet().stream().allMatch(nodeTop ->
nodeTop.getValue() == 0)) {
- removeFromServicesMap(registeredServices,
registeredServicesByName, e.getKey());
-
- removeFromServicesMap(deployedServices,
deployedServicesByName, e.getKey());
- }
- }
}
finally {
leaveBusy();
diff --git
a/modules/core/src/test/java/org/apache/ignite/internal/processors/service/IgniteServiceDeployOnJoinedNodeTest.java
b/modules/core/src/test/java/org/apache/ignite/internal/processors/service/IgniteServiceDeployOnJoinedNodeTest.java
new file mode 100644
index 00000000000..80b604c40da
--- /dev/null
+++
b/modules/core/src/test/java/org/apache/ignite/internal/processors/service/IgniteServiceDeployOnJoinedNodeTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.ignite.internal.processors.service;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.function.Supplier;
+import org.apache.ignite.cluster.ClusterGroup;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.services.Service;
+import org.apache.ignite.services.ServiceConfiguration;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/**
+ * Tests check the following case:
+ * 1. Node "A" starts with the service configuration. But, NodeFilter filters
out node "A".
+ * 2. Node "B" starts and NodeFilter conforms it.
+ * 3. It is expected that service will be deployed on node "B".
+ */
+@RunWith(Parameterized.class)
+public class IgniteServiceDeployOnJoinedNodeTest extends
GridCommonAbstractTest {
+ /** */
+ @Parameterized.Parameter
+ public boolean nodeBClient;
+
+ /** @return Test parameters. */
+ @Parameterized.Parameters(name = "nodeBClient={0}")
+ public static Collection<?> parameters() {
+ return List.of(false, true);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String
igniteInstanceName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName)
+ .setConsistentId(igniteInstanceName)
+ .setClientMode("B".equals(igniteInstanceName) && nodeBClient);
+
+ if (cfg.getConsistentId().equals("A")) {
+ // Server node stores service config.
+ cfg = cfg.setServiceConfiguration(new ServiceConfiguration()
+ .setName("service")
+ .setService(new GreeterService())
+ .setMaxPerNodeCount(1)
+ // Service deployed on node "B", only.
+ .setNodeFilter(n -> n.consistentId().equals("B"))
+ );
+ }
+
+ return cfg;
+ }
+
+ /** */
+ @Test
+ public void test() throws Exception {
+ // Node A only stores service config.
+ try (IgniteEx a = startGrid("A")) {
+ // Service must be deployed on node B.
+ try (IgniteEx b = startGrid("B")) {
+ assertEquals(b.configuration().isClientMode(),
(Boolean)nodeBClient);
+
+ ClusterGroup grp = nodeBClient ? b.cluster().forClients() :
b.cluster().forServers();
+
+ assertEquals("Hello", b.services(grp).serviceProxy("service",
Supplier.class, false).get());
+ }
+ }
+ }
+
+ /** */
+ private static class GreeterService implements Supplier<String>, Service {
+ /** {@inheritDoc} */
+ @Override public String get() {
+ return "Hello";
+ }
+ }
+}
diff --git
a/modules/core/src/test/java/org/apache/ignite/internal/processors/service/IgniteServiceDeploymentFailureTest.java
b/modules/core/src/test/java/org/apache/ignite/internal/processors/service/IgniteServiceDeploymentFailureTest.java
index 1263cac4f1c..da9cc76b7d8 100644
---
a/modules/core/src/test/java/org/apache/ignite/internal/processors/service/IgniteServiceDeploymentFailureTest.java
+++
b/modules/core/src/test/java/org/apache/ignite/internal/processors/service/IgniteServiceDeploymentFailureTest.java
@@ -20,7 +20,6 @@ import java.util.Collection;
import java.util.Map;
import java.util.UUID;
import java.util.function.Predicate;
-
import org.apache.ignite.Ignite;
import org.apache.ignite.Ignition;
import org.apache.ignite.cluster.ClusterNode;
@@ -30,6 +29,7 @@ import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.internal.IgniteServicesImpl;
import org.apache.ignite.lang.IgnitePredicate;
+import org.apache.ignite.resources.IgniteInstanceResource;
import org.apache.ignite.services.Service;
import org.apache.ignite.services.ServiceConfiguration;
import org.apache.ignite.services.ServiceDeploymentException;
@@ -179,7 +179,7 @@ public class IgniteServiceDeploymentFailureTest extends
GridCommonAbstractTest {
assertTrue(
FAILED_SERVICE_SHOULD_NOT_BE_PRESENT_IN_THE_CLUSTER,
- waitForCondition(() ->
noDescriptorInClusterForService(INIT_THROWING_SERVICE_NAME), TIMEOUT)
+ waitForCondition(() -> totalInstancesCount(client,
INIT_THROWING_SERVICE_NAME) == 0, TIMEOUT)
);
assertEquals(
@@ -226,19 +226,27 @@ public class IgniteServiceDeploymentFailureTest extends
GridCommonAbstractTest {
new ServiceConfiguration()
.setName(INIT_THROWING_SERVICE_NAME)
.setService(new InitThrowingService())
+ .setMaxPerNodeCount(2)
.setTotalCount(20)
)
);
assertTrue(
- FAILED_SERVICE_SHOULD_NOT_BE_PRESENT_IN_THE_CLUSTER,
- waitForCondition(() ->
noDescriptorInClusterForService(INIT_THROWING_SERVICE_NAME), TIMEOUT)
+ DEPLOYED_SERVICE_MUST_BE_PRESENTED_IN_CLUSTER,
+ waitForCondition(() -> noopSrvcTotalCnt ==
totalInstancesCount(ign, NOOP_SERVICE_NAME), TIMEOUT)
);
- assertEquals(
- DEPLOYED_SERVICE_MUST_BE_PRESENTED_IN_CLUSTER,
- noopSrvcTotalCnt,
- totalInstancesCount(ign, NOOP_SERVICE_NAME)
+ assertTrue(
+ "Service must fail to init on all nodes",
+ totalInstancesCount(ign, INIT_THROWING_SERVICE_NAME) == 0
+ );
+
+ // Must start one instance of InitThrowingService
+ startGrid(getConfiguration("deploy-node"));
+
+ assertTrue(
+ "Service must be deployed on new deploy-node",
+ waitForCondition(() -> totalInstancesCount(ign,
INIT_THROWING_SERVICE_NAME) == 2, TIMEOUT)
);
}
@@ -308,9 +316,14 @@ public class IgniteServiceDeploymentFailureTest extends
GridCommonAbstractTest {
* Service that throws an exception in init.
*/
private static class InitThrowingService implements Service {
+ /** */
+ @IgniteInstanceResource
+ private IgniteEx ignite;
+
/** {@inheritDoc} */
@Override public void init() throws Exception {
- throw new Exception("Service init exception");
+ if
(!"deploy-node".equals(ignite.configuration().getIgniteInstanceName()))
+ throw new Exception("Service init exception");
}
}
diff --git
a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteServiceGridTestSuite.java
b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteServiceGridTestSuite.java
index 373182884d9..514efaa7681 100644
---
a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteServiceGridTestSuite.java
+++
b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteServiceGridTestSuite.java
@@ -40,6 +40,7 @@ import
org.apache.ignite.internal.processors.service.GridServiceReassignmentSelf
import
org.apache.ignite.internal.processors.service.GridServiceSerializationSelfTest;
import
org.apache.ignite.internal.processors.service.IgniteServiceCallContextTest;
import
org.apache.ignite.internal.processors.service.IgniteServiceCallInterceptorTest;
+import
org.apache.ignite.internal.processors.service.IgniteServiceDeployOnJoinedNodeTest;
import
org.apache.ignite.internal.processors.service.IgniteServiceDeployment2ClassLoadersDefaultMarshallerTest;
import
org.apache.ignite.internal.processors.service.IgniteServiceDeploymentClassLoadingDefaultMarshallerTest;
import
org.apache.ignite.internal.processors.service.IgniteServiceDeploymentFailureTest;
@@ -101,6 +102,7 @@ import org.junit.runners.Suite;
IgniteServiceDeploymentClassLoadingDefaultMarshallerTest.class,
IgniteServiceDeployment2ClassLoadersDefaultMarshallerTest.class,
IgniteServiceDeploymentFailureTest.class,
+ IgniteServiceDeployOnJoinedNodeTest.class,
GridServiceExceptionPropagationTest.class,
ServiceDeploymentProcessingOnCoordinatorLeftTest.class,