Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -1579,16 +1579,6 @@ void updateServicesTopologies(@NotNull final Map<IgniteUuid, Map<UUID, Integer>>

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();
Expand Down
Original file line number Diff line number Diff line change
@@ -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";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
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;
Expand All @@ -30,6 +29,7 @@
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;
Expand Down Expand Up @@ -179,7 +179,7 @@ public void testFailedServiceDescriptorsDynamicConfiguration() throws Exception

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(
Expand Down Expand Up @@ -226,19 +226,27 @@ public void testFailedServiceDescriptorsStaticConfiguration() throws Exception {
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)
);
}

Expand Down Expand Up @@ -308,9 +316,14 @@ private static <T> Map<T, ServiceInfo> getServicesMap(Ignite node, String mapNam
* 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");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
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;
Expand Down Expand Up @@ -101,6 +102,7 @@
IgniteServiceDeploymentClassLoadingDefaultMarshallerTest.class,
IgniteServiceDeployment2ClassLoadersDefaultMarshallerTest.class,
IgniteServiceDeploymentFailureTest.class,
IgniteServiceDeployOnJoinedNodeTest.class,

GridServiceExceptionPropagationTest.class,
ServiceDeploymentProcessingOnCoordinatorLeftTest.class,
Expand Down
Loading