All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.infinispan.manager.impl.FailOverClusterExecutor Maven / Gradle / Ivy

There is a newer version: 9.1.7.Final
Show newest version
package org.infinispan.manager.impl;

import java.util.Collection;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.function.Predicate;

import org.infinispan.manager.ClusterExecutionPolicy;
import org.infinispan.manager.ClusterExecutor;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.remoting.transport.Address;
import org.infinispan.util.concurrent.TimeoutException;
import org.infinispan.util.function.TriConsumer;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;

/**
 * Cluster Executor that submits to a single node at a time, but allows for automatic failover up to a certain number
 * of times. The subsequent node where the retry is chosen at random.
 * 

* This executor currently only functions properly when using a single submission cluster executor such as * {@link LocalClusterExecutor} and {@link SingleClusterExecutor} * @author wburns * @since 9.1 */ class FailOverClusterExecutor implements ClusterExecutor { private static final Log log = LogFactory.getLog(FailOverClusterExecutor.class); private static final boolean isTrace = log.isTraceEnabled(); private final ClusterExecutor executor; private final int failOverCount; FailOverClusterExecutor(ClusterExecutor executor, int failOverCount) { this.executor = executor; this.failOverCount = failOverCount; } @Override public CompletableFuture submit(Runnable command) { CompletableFuture future = new CompletableFuture<>(); submit(command, future, failOverCount); return future; } private void submit(Runnable command, CompletableFuture future, int retriesLeft) { if (isTrace) { log.tracef("Submitting runnable %d retries left %d", command, retriesLeft); } executor.submit(command).whenComplete((v, t) -> { if (t != null) { if (t instanceof TimeoutException) { log.tracef("Command %s was met with timeout", command); future.completeExceptionally(t); } else if (retriesLeft > 0) { log.tracef("Retrying command %s - retries left %d", command, retriesLeft); submit(command, future, retriesLeft - 1); } else { log.tracef("No retries left for command %s, passing last exception to user", command); future.completeExceptionally(t); } } else { log.tracef("Command %s completed successfully", command); future.complete(null); } }); } @Override public CompletableFuture submitConsumer(Function callable, TriConsumer triConsumer) { CompletableFuture future = new CompletableFuture<>(); submitConsumer(callable, triConsumer, future, failOverCount); return future; } private void submitConsumer(Function function, TriConsumer triConsumer, CompletableFuture future, int retriesLeft) { if (isTrace) { log.tracef("Submitting function %d retries left %d", function, retriesLeft); } executor.submitConsumer(function, triConsumer).whenComplete((v, t) -> { if (t != null) { if (t instanceof TimeoutException) { log.tracef("Function %s was met with timeout", function); future.completeExceptionally(t); } else if (retriesLeft > 0) { log.tracef("Retrying function %s - retries left %d", function, retriesLeft); submitConsumer(function, triConsumer, future, retriesLeft - 1); } else { log.tracef("No retries left for function %s, passing last exception to user", function); future.completeExceptionally(t); } } else { log.tracef("Function %s completed successfully", function); future.complete(null); } }); } @Override public ClusterExecutor timeout(long time, TimeUnit unit) { ClusterExecutor newExecutor = executor.timeout(time, unit); if (newExecutor == executor) { return this; } return new FailOverClusterExecutor(newExecutor, failOverCount); } @Override public ClusterExecutor singleNodeSubmission() { return executor; } @Override public ClusterExecutor singleNodeSubmission(int failOverCount) { if (failOverCount == this.failOverCount) { return this; } return new FailOverClusterExecutor(executor, failOverCount); } @Override public ClusterExecutor allNodeSubmission() { return executor.allNodeSubmission(); } @Override public ClusterExecutor filterTargets(Predicate predicate) { ClusterExecutor newExecutor = executor.filterTargets(predicate); if (newExecutor == executor) { return this; } return new FailOverClusterExecutor(newExecutor, failOverCount); } @Override public ClusterExecutor filterTargets(ClusterExecutionPolicy policy) throws IllegalStateException { ClusterExecutor newExecutor = executor.filterTargets(policy); if (newExecutor == executor) { return this; } return new FailOverClusterExecutor(newExecutor, failOverCount); } @Override public ClusterExecutor filterTargets(ClusterExecutionPolicy policy, Predicate predicate) throws IllegalStateException { ClusterExecutor newExecutor = executor.filterTargets(policy, predicate); if (newExecutor == executor) { return this; } return new FailOverClusterExecutor(newExecutor, failOverCount); } @Override public ClusterExecutor filterTargets(Collection

addresses) { ClusterExecutor newExecutor = executor.filterTargets(addresses); if (newExecutor == executor) { return this; } return new FailOverClusterExecutor(newExecutor, failOverCount); } @Override public ClusterExecutor noFilter() { ClusterExecutor newExecutor = executor.noFilter(); if (newExecutor == executor) { return this; } return new FailOverClusterExecutor(newExecutor, failOverCount); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy