package jnpf.base.service.impl;
|
|
import jnpf.base.service.LoginSessionService;
|
import jnpf.config.ConfigValueUtil;
|
import jnpf.database.util.DynamicDataSourceUtil;
|
import jnpf.database.util.TenantDataSourceUtil;
|
import jnpf.util.DateUtil;
|
import lombok.RequiredArgsConstructor;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.factory.DisposableBean;
|
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.stereotype.Component;
|
|
import java.util.Collections;
|
import java.util.Set;
|
import java.util.concurrent.Executors;
|
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.TimeUnit;
|
|
/**
|
* Closes sessions after their last synchronized token expiry time.
|
*/
|
@Component
|
@Slf4j
|
@RequiredArgsConstructor
|
public class LoginSessionExpirationWorker implements InitializingBean, DisposableBean {
|
|
private static final String TENANT_REGISTRY_KEY = "jnpf:login-session:tenants";
|
|
private final LoginSessionService loginSessionService;
|
private final ConfigValueUtil configValueUtil;
|
private final RedisTemplate<String, Object> redisTemplate;
|
private ScheduledExecutorService executor;
|
|
@Override
|
public void afterPropertiesSet() {
|
ThreadFactory factory = runnable -> {
|
Thread thread = new Thread(runnable, "login-session-expiration");
|
thread.setDaemon(true);
|
return thread;
|
};
|
executor = Executors.newSingleThreadScheduledExecutor(factory);
|
executor.scheduleWithFixedDelay(this::closeExpired, 60, 60, TimeUnit.SECONDS);
|
}
|
|
private void closeExpired() {
|
if (!configValueUtil.isMultiTenancy()) {
|
closeCurrentTenant();
|
return;
|
}
|
Set<Object> tenantIds = redisTemplate.opsForSet().members(TENANT_REGISTRY_KEY);
|
for (Object tenantId : tenantIds == null ? Collections.emptySet() : tenantIds) {
|
try {
|
TenantDataSourceUtil.switchTenant(String.valueOf(tenantId));
|
closeCurrentTenant();
|
} catch (Exception e) {
|
log.warn("登录会话超时回收失败,tenantId: {}", tenantId, e);
|
} finally {
|
DynamicDataSourceUtil.clearSwitchDataSource();
|
}
|
}
|
}
|
|
private void closeCurrentTenant() {
|
try {
|
loginSessionService.closeExpired(DateUtil.dateAddMinutes(DateUtil.getNowDate(), -2), 200);
|
} catch (Exception e) {
|
log.warn("登录会话超时回收失败", e);
|
}
|
}
|
|
@Override
|
public void destroy() {
|
if (executor != null) {
|
executor.shutdownNow();
|
}
|
}
|
}
|