package core.framework.impl.web.session; import core.framework.api.util.Maps; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.time.Duration; import java.time.Instant; import java.util.Map; import java.util.Set; /** * @author neo */ public class LocalSessionStore implements SessionStore { private final Logger logger = LoggerFactory.getLogger(LocalSessionStore.class); private final Map<String, SessionValue> values = Maps.newConcurrentHashMap(); @Override public Map<String, String> getAndRefresh(String sessionId, Duration sessionTimeout) { SessionValue sessionValue = values.get(sessionId); if (sessionValue == null) return null; if (Instant.now().isAfter(sessionValue.expiredTime)) { values.remove(sessionId); return null; } Map<String, String> sessionValues = sessionValue.values; values.put(sessionId, new SessionValue(expirationTime(sessionTimeout), sessionValues)); return sessionValues; } @Override public void save(String sessionId, Map<String, String> values, Set<String> changedFields, Duration sessionTimeout) { Map<String, String> updatedValues = Maps.newHashMapWithExpectedSize(values.size()); values.forEach((field, value) -> { if (value != null) updatedValues.put(field, value); }); this.values.put(sessionId, new SessionValue(expirationTime(sessionTimeout), updatedValues)); } @Override public void invalidate(String sessionId) { values.remove(sessionId); } private Instant expirationTime(Duration sessionTimeout) { return Instant.now().plus(sessionTimeout); } public void cleanup() { logger.info("cleanup local session store"); Instant now = Instant.now(); values.forEach((id, session) -> { if (now.isAfter(session.expiredTime)) { values.remove(id); } }); } private static class SessionValue { final Instant expiredTime; final Map<String, String> values; SessionValue(Instant expiredTime, Map<String, String> values) { this.expiredTime = expiredTime; this.values = values; } } }