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

net.anotheria.anoprise.sessiondistributor.SessionDistributorServiceMethodCallsRouter Maven / Gradle / Ivy

Go to download

Collection of utils for different enterprise class projects. Among other stuff contains Caches, Mocking, DualCrud, MetaFactory and SessionDistributorService. Visit https://opensource.anotheria.net for details.

There is a newer version: 4.0.0
Show newest version
package net.anotheria.anoprise.sessiondistributor;

import org.distributeme.core.ClientSideCallContext;
import org.distributeme.core.failing.FailDecision;
import org.distributeme.core.failing.FailingStrategy;
import org.distributeme.core.routing.Router;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Complex call-router for SessionDistributorService.
 *
 * @author h3ll
 */
public class SessionDistributorServiceMethodCallsRouter implements Router, FailingStrategy {

	/**
	 * {@link Logger} instance.
	 */
	private static final Logger LOG = LoggerFactory.getLogger(SessionDistributorServiceMethodCallsRouter.class);

	/**
	 * Routing parameter position in method definition.
	 * For current router - SessionId (hashCode) will be used as main parameter for mod-routing,
	 * please {@see SessionDistributorService} interface.
	 * 

If interface will be changed - please review current router.

*/ private static final int PARAMETER_POSITION = 0; /** * MethodNames to route. * Should contains only SDS interface methods names - which has some incoming parameters - and should be * routed by MOD. */ private final static Set routeModMethods = new HashSet(); /** * Under line constant. */ private static final String UNDER_LINE = "_"; /** * Delegation counter. */ private AtomicInteger delegateCallCounter; /** * {@link SessionDistributorServiceConfig} instance. */ private SessionDistributorServiceConfig configuration; /** * Static init block. * Initializing methods which should be routed by mod. */ static { routeModMethods.add("createDistributedSession"); routeModMethods.add("deleteDistributedSession"); routeModMethods.add("restoreDistributedSession"); routeModMethods.add("updateSessionUserId"); routeModMethods.add("updateSessionEditorId"); routeModMethods.add("addDistributedAttribute"); routeModMethods.add("removeDistributedAttribute"); routeModMethods.add("keepDistributedSessionAlive"); } /** * Constructor. */ public SessionDistributorServiceMethodCallsRouter() { this.configuration = SessionDistributorServiceConfig.getInstance(); this.delegateCallCounter = new AtomicInteger(0); } @Override public FailDecision callFailed(ClientSideCallContext clientSideCallContext) { //check that failing strategy is enabled! if (!configuration.isFailingStrategyEnabled()) return FailDecision.fail(); if (clientSideCallContext.getCallCount() <= configuration.getSessionDistributorServersAmount()) return FailDecision.retry(); return FailDecision.fail(); } @Override public String getServiceIdForCall(ClientSideCallContext callContext) { //Checking if MOD routing is possible for current call! if (routeModMethods.contains(callContext.getMethodName()) && callContext.isFirstCall()) return getModBasedServiceId(callContext); return getRoundRobinBasedServiceId(callContext); } /** * Returns service id - based on mod routing. * * @param callContext {@link ClientSideCallContext} * @return service id which should be called */ @SuppressWarnings({"PointlessArithmeticExpression"}) private String getModBasedServiceId(ClientSideCallContext callContext) { List parameters = callContext.getParameters(); if (parameters.size() < PARAMETER_POSITION + 1) throw new AssertionError("Not properly configured router, parameter count is less than expected - actual: " + parameters.size() + ", expected: " + PARAMETER_POSITION); Object parameter = parameters.get(PARAMETER_POSITION); long parameterValue = getModableValue(parameter); //reading mod from config int mod = configuration.getSessionDistributorServersAmount(); String result = (mod - 1) <= 0 ? callContext.getServiceId() : callContext.getServiceId() + UNDER_LINE + (parameterValue % mod); if (LOG.isDebugEnabled()) LOG.debug("Returning mod based result : " + result + " for " + callContext); return result; } /** * Returns service id - based on mod RoundRobin routing. Actually for failing strategy and not mod-routed methods.. * * @param callContext {@link ClientSideCallContext} * @return service id which should be called */ private String getRoundRobinBasedServiceId(ClientSideCallContext callContext) { //RoundRobin - for delegate Call! int callCounter = delegateCallCounter.get(); int mod = configuration.getSessionDistributorServersAmount(); if (delegateCallCounter.incrementAndGet() > (mod - 1)) delegateCallCounter.set(0); String serviceId = callContext.getServiceId(); //for failing strategy! if (!callContext.isFirstCall()) { //find last index of "_" cause after failing serviceId will contains smth like "_{mod}" int instanceNumberPosition = serviceId.lastIndexOf(UNDER_LINE); serviceId = instanceNumberPosition > 0 ? serviceId.substring(0, instanceNumberPosition) : serviceId; } String result = (mod - 1) <= 0 ? serviceId : serviceId + UNDER_LINE + callCounter; if (LOG.isDebugEnabled()) LOG.debug("Returning roundRobin based result : " + result + " for " + callContext); return result; } /** * Returns parameter value converted to Long actually. * For further mod operation. * * @param o object to convert * @return long value */ private long getModableValue(Object o) { if (o instanceof String) return Math.abs(String.class.cast(o).hashCode()); if (o == null) throw new AssertionError("Null objects are not supported"); throw new AssertionError("Object " + o + " of type " + o.getClass() + " is not supported. Please use String"); } @Override public void customize(String serviceId, String parameter) { //in current implementation it's not required! at all :) } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy