refactor(push): normalize notification payload and avoid reconnection replay
All checks were successful
Build Backend / build (push) Successful in 3m30s
Build Backend / build-docker (push) Successful in 1m19s

- Change type field to always be "notification" and add system_type field
- Rename "extra" and "data" fields to "extra_data" for consistency
- Add "is_read" field to notification payload
- Use PublishToUserOnline instead of PublishToUser to prevent system
  messages from being stored in reconnection history replay
- System notifications are already persisted to database, clients can
  fetch via REST API on reconnect
This commit is contained in:
lafay
2026-04-25 15:59:36 +08:00
parent 3215039ff6
commit 52f62ef230

View File

@@ -149,16 +149,18 @@ func (s *pushServiceImpl) pushViaWebSocket(ctx context.Context, userID string, m
content := dto.ExtractTextContentFromModel(message.Segments)
notification := map[string]any{
"id": fmt.Sprintf("%s", message.ID),
"type": string(message.SystemType),
"content": content,
"extra": map[string]any{},
"created_at": message.CreatedAt.Format("2006-01-02T15:04:05Z07:00"),
"id": fmt.Sprintf("%s", message.ID),
"type": "notification",
"system_type": string(message.SystemType),
"content": content,
"is_read": false,
"extra_data": map[string]any{},
"created_at": message.CreatedAt.Format("2006-01-02T15:04:05Z07:00"),
}
// 填充额外数据
if message.ExtraData != nil {
extra := notification["extra"].(map[string]any)
extra := notification["extra_data"].(map[string]any)
extra["actor_id"] = message.ExtraData.ActorID
extra["actor_name"] = message.ExtraData.ActorName
extra["avatar_url"] = message.ExtraData.AvatarURL
@@ -174,7 +176,7 @@ func (s *pushServiceImpl) pushViaWebSocket(ctx context.Context, userID string, m
}
}
}
s.wsHub.PublishToUser(userID, "system_notification", notification)
s.wsHub.PublishToUserOnline(userID, "system_notification", notification)
return true
}
@@ -444,19 +446,22 @@ func (s *pushServiceImpl) PushSystemMessage(ctx context.Context, userID string,
}
// pushSystemViaWebSocket 通过WebSocket推送系统消息
// 使用 PublishToUserOnline 而非 PublishToUser避免将系统消息存入断线重连历史回放
func (s *pushServiceImpl) pushSystemViaWebSocket(ctx context.Context, userID string, msgType, title, content string, data map[string]any) bool {
if s.wsHub == nil || !s.wsHub.HasClients(userID) {
return false
}
sysMsg := map[string]any{
"type": msgType,
"type": "notification",
"system_type": msgType,
"title": title,
"content": content,
"data": data,
"is_read": false,
"extra_data": data,
"created_at": time.Now().Format("2006-01-02T15:04:05Z07:00"),
}
s.wsHub.PublishToUser(userID, "system_notification", sysMsg)
s.wsHub.PublishToUserOnline(userID, "system_notification", sysMsg)
return true
}
@@ -472,24 +477,27 @@ func (s *pushServiceImpl) PushSystemNotification(ctx context.Context, userID str
}
// pushSystemNotificationViaWebSocket 通过WebSocket推送系统通知
// 使用 PublishToUserOnline 而非 PublishToUser避免将通知存入断线重连历史回放
// 系统通知已持久化到数据库,客户端可通过 REST API 拉取,无需在重连时回放
func (s *pushServiceImpl) pushSystemNotificationViaWebSocket(ctx context.Context, userID string, notification *model.SystemNotification) bool {
if s.wsHub == nil || !s.wsHub.HasClients(userID) {
return false
}
wsNotification := map[string]any{
"id": fmt.Sprintf("%d", notification.ID),
"type": string(notification.Type),
"title": notification.Title,
"content": notification.Content,
"is_read": notification.IsRead,
"extra": map[string]any{},
"created_at": notification.CreatedAt.Format("2006-01-02T15:04:05Z07:00"),
"id": fmt.Sprintf("%d", notification.ID),
"type": "notification",
"system_type": string(notification.Type),
"title": notification.Title,
"content": notification.Content,
"is_read": notification.IsRead,
"extra_data": map[string]any{},
"created_at": notification.CreatedAt.Format("2006-01-02T15:04:05Z07:00"),
}
// 填充额外数据
if notification.ExtraData != nil {
extra := wsNotification["extra"].(map[string]any)
extra := wsNotification["extra_data"].(map[string]any)
extra["actor_id_str"] = notification.ExtraData.ActorIDStr
extra["actor_name"] = notification.ExtraData.ActorName
extra["avatar_url"] = notification.ExtraData.AvatarURL
@@ -508,6 +516,6 @@ func (s *pushServiceImpl) pushSystemNotificationViaWebSocket(ctx context.Context
}
}
s.wsHub.PublishToUser(userID, "system_notification", wsNotification)
s.wsHub.PublishToUserOnline(userID, "system_notification", wsNotification)
return true
}