diff --git a/src/main/java/com/webgame/webgamebackend/common/event/SseEventPublisher.java b/src/main/java/com/webgame/webgamebackend/common/event/SseEventPublisher.java new file mode 100644 index 0000000..ca1c27f --- /dev/null +++ b/src/main/java/com/webgame/webgamebackend/common/event/SseEventPublisher.java @@ -0,0 +1,57 @@ +package com.webgame.webgamebackend.common.event; + +import com.alibaba.fastjson2.JSON; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; + +/** + * SSE 事件发布器 + * + * 统一入口,将业务事件序列化后发送到 Redis Pub/Sub 频道, + * 由所有实例的 RedisSseListener 接收并推送到各自连接的客户端。 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class SseEventPublisher { + + /** Redis Pub/Sub 频道名 */ + public static final String CHANNEL = "sse:events"; + + private final RedisTemplate redisTemplate; + + /** + * 发布广播事件(推送给所有在线用户) + * + * @param type 事件类型 + * @param data 事件数据对象(将被序列化为 JSON) + */ + public void broadcast(SseEventType type, Object data) { + SseEvent event = SseEvent.broadcast(type, JSON.toJSONString(data)); + publish(event); + } + + /** + * 发布定向事件(只推送给指定用户) + * + * @param userId 目标用户 accountId + * @param type 事件类型 + * @param data 事件数据对象(将被序列化为 JSON) + */ + public void sendTo(String userId, SseEventType type, Object data) { + SseEvent event = SseEvent.targeted(type, userId, JSON.toJSONString(data)); + publish(event); + } + + /** + * 将事件序列化为 JSON 并发布到 Redis Pub/Sub 频道 + */ + private void publish(SseEvent event) { + String json = JSON.toJSONString(event); + log.debug("[SSE] 发布事件到 Redis, channel={}, eventType={}, targetId={}", + CHANNEL, event.type(), event.targetId()); + redisTemplate.convertAndSend(CHANNEL, json); + } +}