package org.infinispan.manager;
import static org.infinispan.test.TestingUtil.withCacheManagers;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertNotNull;
import static org.testng.AssertJUnit.assertTrue;
import static org.testng.AssertJUnit.fail;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.remoting.transport.Address;
import org.infinispan.test.AbstractInfinispanTest;
import org.infinispan.test.Exceptions;
import org.infinispan.test.MultiCacheManagerCallable;
import org.infinispan.test.TestException;
import org.infinispan.test.TestingUtil;
import org.infinispan.test.fwk.TestCacheManagerFactory;
import org.infinispan.util.function.SerializableSupplier;
import org.testng.annotations.Test;
/**
* @author Will Burns
* @since 8.2
*/
@Test(groups = {"functional", "smoke"}, testName = "manager.AllClusterExecutorTest")
public class AllClusterExecutorTest extends AbstractInfinispanTest {
static AtomicInteger atomicInteger = new AtomicInteger();
ClusterExecutor executor(EmbeddedCacheManager cm) {
return cm.executor();
}
void assertSize(EmbeddedCacheManager[] cms, int receivedSize) {
assertEquals(cms.length, receivedSize);
}
void eventuallyAssertSize(EmbeddedCacheManager[] cms, Supplier<Integer> supplier) {
eventuallyEquals(cms.length, supplier);
}
void assertContains(EmbeddedCacheManager[] managers, Collection<Address> results) {
for (EmbeddedCacheManager manager : managers) {
assertTrue(results.contains(manager.getAddress()));
}
}
SerializableSupplier<AtomicInteger> atomicIntegerSupplier = () -> atomicInteger;
public void testExecutorRunnable() {
withCacheManagers(new MultiCacheManagerCallable(
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false),
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false)) {
@Override
public void call() throws InterruptedException, ExecutionException, TimeoutException {
EmbeddedCacheManager cm1 = cms[0];
atomicIntegerSupplier.get().set(0);
SerializableSupplier<AtomicInteger> supplier = atomicIntegerSupplier;
executor(cm1).submit(() -> supplier.get().getAndIncrement()).get(10, TimeUnit.SECONDS);
assertSize(cms, atomicIntegerSupplier.get().get());
}
});
}
public void testExecutorLocalRunnable() {
withCacheManagers(new MultiCacheManagerCallable(
TestCacheManagerFactory.createCacheManager(CacheMode.LOCAL, false)) {
@Override
public void call() throws InterruptedException, ExecutionException, TimeoutException {
EmbeddedCacheManager cm1 = cms[0];
atomicIntegerSupplier.get().set(0);
SerializableSupplier<AtomicInteger> supplier = atomicIntegerSupplier;
executor(cm1).submit(() -> supplier.get().getAndIncrement()).get(10, TimeUnit.SECONDS);
assertSize(cms, atomicIntegerSupplier.get().get());
}
});
}
public void testExecutor3NodesRunnable() {
withCacheManagers(new MultiCacheManagerCallable(
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false),
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false),
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false)) {
@Override
public void call() throws InterruptedException, ExecutionException, TimeoutException {
EmbeddedCacheManager cm1 = cms[0];
atomicIntegerSupplier.get().set(0);
SerializableSupplier<AtomicInteger> supplier = atomicIntegerSupplier;
executor(cm1).submit(() -> supplier.get().getAndIncrement()).get(10, TimeUnit.SECONDS);
assertSize(cms, atomicIntegerSupplier.get().get());
}
});
}
public void testExecutorRunnablePredicateFilter() {
withCacheManagers(new MultiCacheManagerCallable(
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false),
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false)) {
@Override
public void call() throws InterruptedException, ExecutionException, TimeoutException {
EmbeddedCacheManager cm1 = cms[0];
atomicIntegerSupplier.get().set(0);
SerializableSupplier<AtomicInteger> supplier = atomicIntegerSupplier;
executor(cm1).filterTargets(a -> a.equals(cm1.getAddress()))
.submit(() -> supplier.get().getAndIncrement()).get(10, TimeUnit.SECONDS);
assertEquals(1, atomicIntegerSupplier.get().get());
}
});
}
public void testExecutorRunnableCollectionFilter() {
withCacheManagers(new MultiCacheManagerCallable(
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false),
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false)) {
@Override
public void call() throws InterruptedException, ExecutionException, TimeoutException {
EmbeddedCacheManager cm1 = cms[0];
EmbeddedCacheManager cm2 = cms[1];
atomicIntegerSupplier.get().set(0);
SerializableSupplier<AtomicInteger> supplier = atomicIntegerSupplier;
executor(cm1).filterTargets(Collections.singleton(cm2.getAddress()))
.submit(() -> supplier.get().getAndIncrement()).get(10, TimeUnit.SECONDS);
assertEquals(1, atomicIntegerSupplier.get().get());
}
});
}
public void testExecutorRunnableException() {
withCacheManagers(new MultiCacheManagerCallable(
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false),
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false)) {
@Override
public void call() throws InterruptedException, ExecutionException, TimeoutException {
EmbeddedCacheManager cm1 = cms[0];
CompletableFuture<Void> future = executor(cm1).submit(() -> {
throw new TestException();
});
Exceptions.expectExecutionException(TestException.class, future);
}
});
}
public void testExecutorRunnableExceptionWhenComplete() {
withCacheManagers(new MultiCacheManagerCallable(
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false),
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false)) {
@Override
public void call() throws InterruptedException, ExecutionException, TimeoutException {
EmbeddedCacheManager cm1 = cms[0];
CompletableFuture<Void> future = executor(cm1).submit(() -> {
throw new TestException();
});
Exchanger<Throwable> exchanger = new Exchanger<>();
future.whenCompleteAsync((v, t) -> {
try {
exchanger.exchange(t, 10, TimeUnit.SECONDS);
} catch (InterruptedException | TimeoutException e) {
throw new RuntimeException(e);
}
});
Throwable t = exchanger.exchange(null, 10, TimeUnit.SECONDS);
assertNotNull(t);
assertEquals(TestException.class, t.getClass());
}
});
}
public void testExecutorRunnable3NodesException() {
withCacheManagers(new MultiCacheManagerCallable(
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false),
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false),
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false)) {
@Override
public void call() throws InterruptedException, ExecutionException, TimeoutException {
EmbeddedCacheManager cm1 = cms[0];
CompletableFuture<Void> future = executor(cm1).submit(() -> {
throw new TestException();
});
Exceptions.expectExecutionException(TestException.class, future);
}
});
}
public void testExecutorRunnable3NodesExceptionExcludeLocal() {
withCacheManagers(new MultiCacheManagerCallable(
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false),
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false),
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false)) {
@Override
public void call() throws InterruptedException, ExecutionException, TimeoutException {
EmbeddedCacheManager cm1 = cms[0];
CompletableFuture<Void> future = executor(cm1).filterTargets(a -> !a.equals(cm1.getAddress())).submit(() -> {
throw new TestException();
});
Exceptions.expectExecutionException(TestException.class, future);
}
});
}
public void testExecutorTimeoutException() {
withCacheManagers(new MultiCacheManagerCallable(
TestCacheManagerFactory.createCacheManager(CacheMode.DIST_SYNC, false),
TestCacheManagerFactory.createCacheManager(CacheMode.DIST_SYNC, false)) {
@Override
public void call() throws InterruptedException, ExecutionException, TimeoutException {
EmbeddedCacheManager cm1 = cms[0];
CompletableFuture<Void> future = executor(cm1).timeout(10, TimeUnit.MILLISECONDS).submit(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
fail("Unexpected interrupt: " + e);
}
});
// This fails when local node is invoked since timeout is not adhered to
Exceptions
.expectExecutionException(org.infinispan.util.concurrent.TimeoutException.class, future);
}
});
}
public void testExecutorExecuteRunnable() {
withCacheManagers(new MultiCacheManagerCallable(
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false),
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false)) {
@Override
public void call() throws InterruptedException, ExecutionException, TimeoutException {
EmbeddedCacheManager cm1 = cms[0];
atomicIntegerSupplier.get().set(0);
SerializableSupplier<AtomicInteger> supplier = atomicIntegerSupplier;
executor(cm1).execute(() -> supplier.get().getAndIncrement());
eventuallyAssertSize(cms, () -> atomicIntegerSupplier.get().get());
}
});
}
public void testExecutorLocalExecuteRunnable() {
withCacheManagers(new MultiCacheManagerCallable(
TestCacheManagerFactory.createCacheManager(CacheMode.LOCAL, false)) {
@Override
public void call() throws InterruptedException, ExecutionException, TimeoutException {
EmbeddedCacheManager cm1 = cms[0];
atomicIntegerSupplier.get().set(0);
executor(cm1).execute(() -> atomicIntegerSupplier.get().getAndIncrement());
eventuallyEquals(1, () -> atomicIntegerSupplier.get().get());
}
});
}
public void testExecutorTriConsumer() {
withCacheManagers(new MultiCacheManagerCallable(
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false),
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false)) {
@Override
public void call() throws InterruptedException, ExecutionException, TimeoutException {
EmbeddedCacheManager cm1 = cms[0];
EmbeddedCacheManager cm2 = cms[1];
AtomicReference<Throwable> throwable = new AtomicReference<>();
List<Address> addresses = Collections.synchronizedList(new ArrayList<>(2));
executor(cm1).submitConsumer(EmbeddedCacheManager::getAddress, (a, i, t) -> {
if (t != null) {
throwable.set(t);
} else {
addresses.add(i);
}
}).get(10, TimeUnit.SECONDS);
Throwable t = throwable.get();
if (t != null) {
throw new RuntimeException(t);
}
assertContains(cms, addresses);
}
});
}
public void testExecutorLocalTriConsumer() {
withCacheManagers(new MultiCacheManagerCallable(
TestCacheManagerFactory.createCacheManager(CacheMode.LOCAL, false)) {
@Override
public void call() throws InterruptedException, ExecutionException, TimeoutException {
EmbeddedCacheManager cm1 = cms[0];
AtomicReference<Throwable> throwable = new AtomicReference<>();
List<Address> addresses = Collections.synchronizedList(new ArrayList<>(2));
executor(cm1).submitConsumer(m -> m.getAddress(), (a, i, t) -> {
if (t != null) {
throwable.set(t);
} else {
addresses.add(i);
}
}).get(10, TimeUnit.SECONDS);
Throwable t = throwable.get();
if (t != null) {
throw new RuntimeException(t);
}
assertEquals(1, addresses.size());
assertTrue(addresses.contains(cm1.getAddress()));
}
});
}
public void testExecutor3NodeTriConsumer() {
withCacheManagers(new MultiCacheManagerCallable(
TestCacheManagerFactory.createCacheManager(CacheMode.DIST_SYNC, false),
TestCacheManagerFactory.createCacheManager(CacheMode.DIST_SYNC, false),
TestCacheManagerFactory.createCacheManager(CacheMode.DIST_SYNC, false)) {
@Override
public void call() throws InterruptedException, ExecutionException, TimeoutException {
EmbeddedCacheManager cm1 = cms[0];
AtomicReference<Throwable> throwable = new AtomicReference<>();
List<Address> addresses = Collections.synchronizedList(new ArrayList<>(2));
executor(cm1).submitConsumer(m -> m.getAddress(), (a, i, t) -> {
if (t != null) {
throwable.set(t);
} else {
addresses.add(i);
}
}).get(10, TimeUnit.SECONDS);
Throwable t = throwable.get();
if (t != null) {
throw new RuntimeException(t);
}
assertContains(cms, addresses);
}
});
}
public void testExecutorTriConsumerException() {
withCacheManagers(new MultiCacheManagerCallable(
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false),
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false)) {
@Override
public void call() throws InterruptedException, ExecutionException, TimeoutException {
EmbeddedCacheManager cm1 = cms[0];
AtomicInteger exceptionCount = new AtomicInteger();
CompletableFuture<Void> future = executor(cm1).submitConsumer(m -> {
throw new TestException();
}, (a, i, t) -> {
Exceptions.assertException(TestException.class, t);
exceptionCount.incrementAndGet();
});
future.get(10, TimeUnit.SECONDS);
assertSize(cms, exceptionCount.get());
}
});
}
public void testExecutorTriConsumerTimeoutException() {
withCacheManagers(new MultiCacheManagerCallable(
TestCacheManagerFactory.createCacheManager(CacheMode.DIST_SYNC, false),
TestCacheManagerFactory.createCacheManager(CacheMode.DIST_SYNC, false)) {
@Override
public void call() throws InterruptedException, ExecutionException, TimeoutException {
EmbeddedCacheManager cm1 = cms[0];
CompletableFuture<Void> future =
executor(cm1).timeout(10, TimeUnit.MILLISECONDS).submitConsumer(m -> {
TestingUtil.sleepThread(100);
return null;
}, (a, i, t) -> { });
Exceptions.expectExecutionException(org.infinispan.util.concurrent.TimeoutException.class, future);
}
});
}
public void testExecutorTriConsumerExceptionFromConsumer() {
withCacheManagers(new MultiCacheManagerCallable(
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false),
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false)) {
@Override
public void call() throws InterruptedException, ExecutionException, TimeoutException {
EmbeddedCacheManager cm1 = cms[0];
CompletableFuture<Void> future =
executor(cm1).submitConsumer(m -> null,
(a, i, t) -> {
throw new NullPointerException();
});
Exceptions.expectExecutionException(NullPointerException.class, future);
}
});
}
public void testExecutorTriConsumerExceptionWhenComplete() {
withCacheManagers(new MultiCacheManagerCallable(
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false),
TestCacheManagerFactory.createCacheManager(CacheMode.REPL_SYNC, false)) {
@Override
public void call() throws InterruptedException, ExecutionException, TimeoutException {
EmbeddedCacheManager cm1 = cms[0];
CompletableFuture<Void> future =
executor(cm1).filterTargets(cm1.getAddress()::equals).submitConsumer(m -> null,
(a, i, t) -> {
throw new NullPointerException();
});
Exchanger<Throwable> exchanger = new Exchanger<>();
future.whenCompleteAsync((v, t) -> {
try {
exchanger.exchange(t, 10, TimeUnit.SECONDS);
} catch (InterruptedException | TimeoutException e) {
throw new RuntimeException(e);
}
});
Throwable t = exchanger.exchange(null, 10, TimeUnit.SECONDS);
assertNotNull(t);
assertEquals(NullPointerException.class, t.getClass());
}
});
}
}