feat(im): Task 4 - WS 事件处理器 + 离线消息推送

EventHandler:
- im.message.send: 发送消息(解析→业务→ACK+推送)
- im.message.recall: 撤回消息
- im.conversation.read: 标记已读
- im.typing: 正在输入通知(转发对方)
- 所有事件通过 Hub.RegisterEvent 注册到路由表

OfflinePusher:
- PushOfflineMessages: 推送未读会话摘要 + 全局未读总数
- 通过 OfflineMessagePusher 接口注入 WS Handler
- WebSocket 连接建立后自动触发离线推送

Made-with: Cursor
This commit is contained in:
bujinyuan
2026-03-03 10:48:36 +08:00
parent 334d3d860b
commit 1e0c061e9d
4 changed files with 265 additions and 5 deletions

View File

@@ -21,6 +21,12 @@ type TokenValidator interface {
ValidateAccessToken(ctx context.Context, userID int64, clientType, token string) bool
}
// OfflineMessagePusher 离线消息推送接口
// 由 im.handler.OfflinePusher 实现WebSocket 连接建立后触发推送
type OfflineMessagePusher interface {
PushOfflineMessages(ctx context.Context, userID int64)
}
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
@@ -31,11 +37,12 @@ var upgrader = websocket.Upgrader{
// Handler WebSocket 连接处理器
type Handler struct {
hub *ws.Hub
pubsub *ws.PubSub
jwtCfg *config.JWTConfig
onlineService *OnlineService
tokenValidator TokenValidator
hub *ws.Hub
pubsub *ws.PubSub
jwtCfg *config.JWTConfig
onlineService *OnlineService
tokenValidator TokenValidator
offlinePusher OfflineMessagePusher
}
// NewHandler 创建 WebSocket Handler 实例
@@ -49,6 +56,11 @@ func NewHandler(hub *ws.Hub, pubsub *ws.PubSub, jwtCfg *config.JWTConfig, online
}
}
// SetOfflinePusher 设置离线消息推送器(由 IM 模块在初始化时注入)
func (h *Handler) SetOfflinePusher(pusher OfflineMessagePusher) {
h.offlinePusher = pusher
}
// Upgrade 处理 WebSocket 升级请求
// GET /ws?token=xxx → JWT 认证 → 升级连接 → 注册 Hub → 订阅 Redis 频道
func (h *Handler) Upgrade(c *gin.Context) {
@@ -105,6 +117,10 @@ func (h *Handler) Upgrade(c *gin.Context) {
go client.WritePump()
go client.ReadPump(h.createReadHandler(claims.UserID))
if h.offlinePusher != nil {
go h.offlinePusher.PushOfflineMessages(context.Background(), claims.UserID)
}
}
// createReadHandler 创建带生命周期管理的消息处理函数