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

com.github.kshashov.telegram.TelegramScope Maven / Gradle / Ivy

package com.github.kshashov.telegram;

import com.github.kshashov.telegram.api.TelegramSession;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.Scope;
import org.springframework.lang.NonNull;

import javax.validation.constraints.NotNull;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * Scope store all beans in the cache by chat id (or user id)
 * 

The bean lifetime after the last call can be redefined using the property {@code * TelegramConfigurationProperties.getSessionSeconds()}.

* *

Note: All {@link TelegramSession} instances have this scope by * default. * * @see TelegramScopeException */ @Slf4j public class TelegramScope implements Scope { public static final String SCOPE = "telegramScope"; private static final ThreadLocal USER_THREAD_LOCAL = new ThreadLocal<>(); private final ConfigurableListableBeanFactory beanFactory; private final LoadingCache> conversations; @SuppressWarnings("unchecked") TelegramScope(@NotNull ConfigurableListableBeanFactory beanFactory, long expireSeconds) { this.beanFactory = beanFactory; conversations = CacheBuilder .newBuilder() .expireAfterAccess(expireSeconds, TimeUnit.SECONDS) .removalListener(notification -> { if (notification.wasEvicted()) { log.debug("Evict session for key {}", notification.getKey()); Map userScope = (Map) notification.getValue(); if (userScope != null) { userScope.values().forEach(this::removeBean); } } }) .build(new CacheLoader>() { @Override public ConcurrentHashMap load(@NonNull String key) { log.debug("Create session for key = {}", key); return new ConcurrentHashMap<>(); } }); } static void setIdThreadLocal(Long chatId) { USER_THREAD_LOCAL.set(chatId); } static void removeId() { USER_THREAD_LOCAL.remove(); } private void removeBean(Object bean) { beanFactory.destroyBean(bean); } @NonNull @Override public Object get(@NonNull String name, @NonNull ObjectFactory objectFactory) throws TelegramScopeException { final String sessionId = getConversationId(); if (sessionId == null) { throw new TelegramScopeException("There is no current session"); } ConcurrentHashMap beans; try { beans = conversations.get(sessionId); } catch (ExecutionException e) { throw new TelegramScopeException(e); } return beans.computeIfAbsent(name, (k) -> objectFactory.getObject()); } @Override public Object remove(@NonNull String name) { final String sessionId = getConversationId(); if (sessionId != null) { final Map userBeans = conversations.getIfPresent(sessionId); if (userBeans != null) { return userBeans.remove(name); } } return null; } @Override public void registerDestructionCallback(@NonNull String name, @NonNull Runnable callback) { } @Override public Object resolveContextualObject(@NonNull String key) { return null; } @Override public String getConversationId() { Long id = USER_THREAD_LOCAL.get(); if (id == null) { return null; } return Long.toString(id); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy