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

org.wildfly.clustering.session.cache.CachedSessionManager Maven / Gradle / Ivy

There is a newer version: 4.0.0.Final
Show newest version
/*
 * Copyright The WildFly Authors
 * SPDX-License-Identifier: Apache-2.0
 */

package org.wildfly.clustering.session.cache;

import java.util.Optional;
import java.util.concurrent.CompletionStage;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;

import org.wildfly.clustering.cache.batch.Batch;
import org.wildfly.clustering.server.cache.Cache;
import org.wildfly.clustering.server.cache.CacheFactory;
import org.wildfly.clustering.session.ImmutableSession;
import org.wildfly.clustering.session.Session;
import org.wildfly.clustering.session.SessionManager;
import org.wildfly.clustering.session.SessionStatistics;
import org.wildfly.common.function.Functions;

/**
 * A concurrent session manager, that can share session references across concurrent threads.
 * @param  the session context type
 * @author Paul Ferraro
 */
public class CachedSessionManager implements SessionManager {

	private final SessionManager manager;
	private final Cache>> sessionCache;
	private final BiFunction>> sessionCreator;
	private final BiFunction>> sessionFinder;
	private final UnaryOperator> validator = new UnaryOperator<>() {
		@Override
		public Session apply(Session session) {
			// If session was invalidated by a concurrent thread, return null instead of an invalid session
			// This will reduce the likelihood that a duplicate invalidation request (e.g. from a double-clicked logout) results in an ISE
			if (session != null && !session.isValid()) {
				session.close();
				return null;
			}
			return session;
		}
	};

	public CachedSessionManager(SessionManager manager, CacheFactory cacheFactory) {
		this.manager = manager;
		this.sessionCreator = new BiFunction<>() {
			@Override
			public CompletionStage> apply(String id, Runnable closeTask) {
				return manager.createSessionAsync(id).thenApply(session -> new CachedSession<>(session, closeTask));
			}
		};
		Function> empty = closeTask -> {
			closeTask.run();
			return null;
		};
		this.sessionFinder = new BiFunction<>() {
			@Override
			public CompletionStage> apply(String id, Runnable closeTask) {
				return manager.findSessionAsync(id).thenApply(session -> (session != null) ? new CachedSession<>(session, closeTask) : empty.apply(closeTask));
			}
		};
		this.sessionCache = cacheFactory.createCache(Functions.discardingConsumer(), new Consumer>>() {
			@Override
			public void accept(CompletionStage> future) {
				future.thenAccept(session -> Optional.ofNullable(session).map(Supplier::get).ifPresent(Session::close));
			}
		});
	}

	@Override
	public CompletionStage> createSessionAsync(String id) {
		return this.sessionCache.computeIfAbsent(id, this.sessionCreator).thenApply(Function.identity());
	}

	@Override
	public CompletionStage> findSessionAsync(String id) {
		return this.sessionCache.computeIfAbsent(id, this.sessionFinder).thenApply(this.validator);
	}

	@Override
	public CompletionStage findImmutableSessionAsync(String id) {
		return this.manager.findImmutableSessionAsync(id);
	}

	@Override
	public Session getDetachedSession(String id) {
		return this.manager.getDetachedSession(id);
	}

	@Override
	public Supplier getIdentifierFactory() {
		return this.manager.getIdentifierFactory();
	}

	@Override
	public void start() {
		this.manager.start();
	}

	@Override
	public void stop() {
		this.manager.stop();
	}

	@Override
	public Supplier getBatchFactory() {
		return this.manager.getBatchFactory();
	}

	@Override
	public SessionStatistics getStatistics() {
		return this.manager.getStatistics();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy