Files
JChargePointProtocol/jcpp-protocol-api/src/main/java/sanbing/jcpp/protocol/domain/ProtocolSession.java

161 lines
5.3 KiB
Java
Raw Normal View History

2024-10-08 09:38:54 +08:00
/**
2025-03-04 10:42:17 +08:00
* 开源代码仅供学习和交流研究使用商用请联系三丙
* 微信mohan_88888
* 抖音程序员三丙
* 付费课程知识星球https://t.zsxq.com/aKtXo
2024-10-08 09:38:54 +08:00
*/
package sanbing.jcpp.protocol.domain;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
2025-09-12 14:40:18 +08:00
import sanbing.jcpp.proto.gen.DownlinkProto.DownlinkRequestMessage;
import sanbing.jcpp.proto.gen.UplinkProto.SessionCloseEventProto;
import sanbing.jcpp.proto.gen.UplinkProto.SessionCloseReason;
import sanbing.jcpp.proto.gen.UplinkProto.UplinkQueueMessage;
2024-10-08 09:38:54 +08:00
import sanbing.jcpp.protocol.forwarder.Forwarder;
import java.io.Closeable;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
2024-10-08 09:38:54 +08:00
import java.util.function.Function;
/**
* @author 九筒
2024-10-08 09:38:54 +08:00
*/
@Getter
@Slf4j
public abstract class ProtocolSession implements Closeable {
private static final int REQUEST_CACHE_LIMIT = 1000;
protected final String protocolName;
protected final UUID id;
@Setter
protected LocalDateTime lastActivityTime;
protected final Set<String> pileCodeSet;
private final Map<String, ScheduledFuture<?>> scheduledFutures = new ConcurrentHashMap<>();
private final Cache<String, Object> requestCache = Caffeine.newBuilder()
.initialCapacity(REQUEST_CACHE_LIMIT)
.maximumSize(REQUEST_CACHE_LIMIT)
.expireAfterAccess(Duration.ofMinutes(1))
.build();
@Setter
private Forwarder forwarder;
/**
* 会话关闭回调用于通知注册中心清除缓存
*/
@Setter
private Consumer<UUID> closeCallback;
/**
* 防止重复关闭
*/
private final AtomicBoolean closed = new AtomicBoolean(false);
2024-10-22 17:11:05 +08:00
protected ProtocolSession(String protocolName) {
2024-10-08 09:38:54 +08:00
this.protocolName = protocolName;
this.pileCodeSet = new LinkedHashSet<>();
this.id = UUID.randomUUID();
this.lastActivityTime = LocalDateTime.now();
}
2024-10-22 17:11:05 +08:00
public abstract void onDownlink(DownlinkRequestMessage downlinkMsg);
2024-10-08 09:38:54 +08:00
2025-02-13 10:03:59 +08:00
@Override
2024-10-08 09:38:54 +08:00
public void close() {
2025-09-12 14:40:18 +08:00
close(SessionCloseReason.SESSION_CLOSE_DESTRUCTION);
2024-10-08 09:38:54 +08:00
}
2025-09-12 14:40:18 +08:00
public void close(SessionCloseReason reason) {
// 防止重复关闭
if (!closed.compareAndSet(false, true)) {
log.debug("[{}] Protocol会话已关闭忽略重复关闭请求", this);
return;
}
2024-10-08 09:38:54 +08:00
log.info("[{}] Protocol会话关闭原因: {}", this, reason);
// 1. 取消所有定时任务
2024-10-08 09:38:54 +08:00
scheduledFutures.values().forEach(scheduledFuture -> scheduledFuture.cancel(true));
scheduledFutures.clear();
// 2. 通知注册中心清除缓存
if (closeCallback != null) {
try {
closeCallback.accept(id);
log.debug("[{}] 会话关闭回调执行成功", this);
} catch (Exception e) {
log.error("[{}] 会话关闭回调执行失败", this, e);
}
}
// 3. 转发会话关闭事件到后端
if (forwarder != null && !pileCodeSet.isEmpty()) {
for (String pileCode : pileCodeSet) {
2025-09-12 14:40:18 +08:00
SessionCloseEventProto sessionCloseEvent = SessionCloseEventProto.newBuilder()
.setPileCode(pileCode)
.setReason(reason)
.setAdditionalInfo("Session closed: " + reason)
.build();
2025-09-12 14:40:18 +08:00
UplinkQueueMessage uplinkQueueMessage = UplinkQueueMessage.newBuilder()
.setMessageIdMSB(UUID.randomUUID().getMostSignificantBits())
.setMessageIdLSB(UUID.randomUUID().getLeastSignificantBits())
.setSessionIdMSB(id.getMostSignificantBits())
.setSessionIdLSB(id.getLeastSignificantBits())
.setMessageKey(pileCode + "_session_close")
.setProtocolName(protocolName)
.setSessionCloseEventProto(sessionCloseEvent)
.build();
try {
forwarder.sendMessage(uplinkQueueMessage);
log.debug("[{}] 会话关闭事件已转发,桩编码: {}, 原因: {}", this, pileCode, reason);
} catch (Exception e) {
log.error("[{}] 转发会话关闭事件失败,桩编码: {}", this, pileCode, e);
}
}
}
2024-10-08 09:38:54 +08:00
}
/**
* 检查会话是否已关闭
*/
public boolean isClosed() {
return closed.get();
}
2024-10-08 09:38:54 +08:00
@Override
public String toString() {
return "[" + id + "]" + pileCodeSet;
}
public void addPileCode(String pileCode) {
this.pileCodeSet.add(pileCode);
}
public void addSchedule(String name, Function<String, ScheduledFuture<?>> scheduledFutureFunction) {
scheduledFutures.computeIfAbsent(name, scheduledFutureFunction);
}
}