From 0ddc7c9df577baf145c630ccf27576b8c22d22c4 Mon Sep 17 00:00:00 2001 From: sancar Date: Thu, 20 Sep 2018 16:30:41 +0300 Subject: [PATCH] Local cache configs are recreated when client connect to cluster fixes https://github.com/hazelcast/hazelcast/issues/12128 (cherry picked from commit 075b27e9cea1f82889690e5e758e95effe382106) --- .../cache/impl/ClientCacheProxyFactory.java | 6 ++ .../hazelcast/client/spi/ProxyManager.java | 14 +-- .../client/cache/ClientCacheProxyTest.java | 99 +++++++++++++++++++ 3 files changed, 113 insertions(+), 6 deletions(-) create mode 100644 hazelcast-client/src/test/java/com/hazelcast/client/cache/ClientCacheProxyTest.java diff --git a/hazelcast-client/src/main/java/com/hazelcast/client/cache/impl/ClientCacheProxyFactory.java b/hazelcast-client/src/main/java/com/hazelcast/client/cache/impl/ClientCacheProxyFactory.java index 54fbd94403e1..6b28cf01223a 100644 --- a/hazelcast-client/src/main/java/com/hazelcast/client/cache/impl/ClientCacheProxyFactory.java +++ b/hazelcast-client/src/main/java/com/hazelcast/client/cache/impl/ClientCacheProxyFactory.java @@ -53,6 +53,12 @@ public ClientProxy create(String id, ClientContext context) { return new ClientCacheProxy(cacheConfig, context); } + public void recreateCachesOnCluster() { + for (CacheConfig cacheConfig : configs.values()) { + ClientCacheHelper.createCacheConfig(client, cacheConfig); + } + } + @SuppressFBWarnings("RV_RETURN_VALUE_OF_PUTIFABSENT_IGNORED") void addCacheConfig(String cacheName, CacheConfig cacheConfig) { configs.putIfAbsent(cacheName, cacheConfig); diff --git a/hazelcast-client/src/main/java/com/hazelcast/client/spi/ProxyManager.java b/hazelcast-client/src/main/java/com/hazelcast/client/spi/ProxyManager.java index 6b81854458f0..5db71eddf85e 100644 --- a/hazelcast-client/src/main/java/com/hazelcast/client/spi/ProxyManager.java +++ b/hazelcast-client/src/main/java/com/hazelcast/client/spi/ProxyManager.java @@ -395,10 +395,10 @@ private void initializeWithRetry(ClientProxy clientProxy) throws Exception { initialize(clientProxy); return; } catch (Exception e) { - boolean retryable = isRetryable(e); + boolean retryable = ClientInvocation.isRetrySafeException(e); if (!retryable && e instanceof ExecutionException) { - retryable = isRetryable(e.getCause()); + retryable = ClientInvocation.isRetrySafeException(e.getCause()); } if (retryable) { @@ -414,10 +414,6 @@ private void initializeWithRetry(ClientProxy clientProxy) throws Exception { + " ms. Configured invocation timeout is " + invocationTimeoutMillis + " ms"); } - private boolean isRetryable(final Throwable t) { - return ClientInvocation.isRetrySafeException(t); - } - private void sleepForProxyInitRetry() { try { Thread.sleep(invocationRetryPauseMillis); @@ -489,6 +485,12 @@ public void createDistributedObjectsOnCluster(Connection ownerConnection) { } ClientMessage clientMessage = ClientCreateProxiesCodec.encodeRequest(proxyEntries); new ClientInvocation(client, clientMessage, null, ownerConnection).invokeUrgent(); + createCachesOnCluster(); + } + + private void createCachesOnCluster() { + ClientCacheProxyFactory proxyFactory = (ClientCacheProxyFactory) getClientProxyFactory(ICacheService.SERVICE_NAME); + proxyFactory.recreateCachesOnCluster(); } private final class DistributedObjectEventHandler extends ClientAddDistributedObjectListenerCodec.AbstractEventHandler diff --git a/hazelcast-client/src/test/java/com/hazelcast/client/cache/ClientCacheProxyTest.java b/hazelcast-client/src/test/java/com/hazelcast/client/cache/ClientCacheProxyTest.java new file mode 100644 index 000000000000..8cd6254dc178 --- /dev/null +++ b/hazelcast-client/src/test/java/com/hazelcast/client/cache/ClientCacheProxyTest.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2008-2018, Hazelcast, Inc. All Rights Reserved. + * + * Licensed 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 com.hazelcast.client.cache; + +import com.hazelcast.client.cache.impl.HazelcastClientCachingProvider; +import com.hazelcast.client.config.ClientConfig; +import com.hazelcast.client.test.ClientTestSupport; +import com.hazelcast.client.test.TestHazelcastFactory; +import com.hazelcast.core.HazelcastInstance; +import com.hazelcast.test.HazelcastParallelClassRunner; +import com.hazelcast.test.annotation.ParallelTest; +import com.hazelcast.test.annotation.QuickTest; +import org.junit.After; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; + +import javax.cache.CacheManager; +import javax.cache.configuration.CompleteConfiguration; +import javax.cache.configuration.MutableConfiguration; +import javax.cache.spi.CachingProvider; + +import static org.junit.Assert.assertNull; + +@RunWith(HazelcastParallelClassRunner.class) +@Category({QuickTest.class, ParallelTest.class}) +public class ClientCacheProxyTest extends ClientTestSupport { + + private TestHazelcastFactory factory = new TestHazelcastFactory(); + + @After + public void tearDown() { + factory.shutdownAll(); + } + + @Test + public void clusterRestart_proxyRemainsUsableOnClient() { + HazelcastInstance instance = factory.newHazelcastInstance(); + ClientConfig clientConfig = new ClientConfig(); + clientConfig.getNetworkConfig().setConnectionAttemptLimit(Integer.MAX_VALUE); + HazelcastInstance client = factory.newHazelcastClient(clientConfig); + + CachingProvider cachingProvider = HazelcastClientCachingProvider.createCachingProvider(client); + + CacheManager cacheManager = cachingProvider.getCacheManager(); + + CompleteConfiguration config = + new MutableConfiguration() + .setTypes(String.class, String.class); + + javax.cache.Cache cache = cacheManager.createCache("example", config); + //restarting cluster + instance.shutdown(); + factory.newHazelcastInstance(); + + //expected to work without throwing exception + assertNull(cache.get("key")); + + } + + @Test + public void clientRestart_proxyRemainsUsableOnClient() { + factory.newHazelcastInstance(); + + HazelcastInstance client = factory.newHazelcastClient(); + CachingProvider cachingProvider = HazelcastClientCachingProvider.createCachingProvider(client); + CacheManager cacheManager = cachingProvider.getCacheManager(); + CompleteConfiguration config = + new MutableConfiguration() + .setTypes(String.class, String.class); + String cacheName = "example"; + cacheManager.createCache(cacheName, config); + + //restarting client and getting already created cache + client.shutdown(); + client = factory.newHazelcastClient(); + cachingProvider = HazelcastClientCachingProvider.createCachingProvider(client); + cacheManager = cachingProvider.getCacheManager(); + javax.cache.Cache cache = cacheManager.getCache(cacheName); + + //expected to work without throwing exception + assertNull(cache.get("key")); + } +} +