v0.0.17.3 Переработан websocket, добавлена обработка ping/pong
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
039c8447a7
commit
db667f224b
@ -159,17 +159,22 @@ func (r *mutationResolver) SendMessage(ctx context.Context, receiverID int, cont
|
||||
return nil, errors.New("не авторизован")
|
||||
}
|
||||
|
||||
// Проверяем, что не отправляем сообщение себе
|
||||
if senderID == receiverID {
|
||||
return nil, errors.New("cannot send message to yourself")
|
||||
}
|
||||
|
||||
chat, err := r.Services.Chat.GetOrCreateChat(ctx, senderID, receiverID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ошибка создания чата: %v", err)
|
||||
}
|
||||
|
||||
return r.Services.Chat.SendMessage(ctx, senderID, chat.ID, content)
|
||||
message, err := r.Services.Chat.SendMessage(ctx, senderID, chat.ID, content)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Рассылаем сообщение через WebSocket
|
||||
if r.Services.ChatHub != nil {
|
||||
r.Services.ChatHub.Broadcast(message)
|
||||
}
|
||||
|
||||
return message, nil
|
||||
}
|
||||
|
||||
// MarkAsRead - помечает сообщение как прочитанное
|
||||
|
||||
@ -9,6 +9,7 @@ import (
|
||||
"tailly_back_v2/internal/service"
|
||||
"tailly_back_v2/internal/ws"
|
||||
"tailly_back_v2/pkg/auth"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
@ -105,13 +106,17 @@ func (h *ChatHandler) HandleWebSocket(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (h *ChatHandler) readPump(ctx context.Context, conn *websocket.Conn, client *ws.Client, userID int) {
|
||||
defer func() {
|
||||
h.hub.UnregisterClient(client)
|
||||
conn.Close()
|
||||
}()
|
||||
ticker := time.NewTicker(30 * time.Second)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
// Отправляем ping
|
||||
if err := conn.WriteJSON(map[string]string{"type": "ping"}); err != nil {
|
||||
log.Printf("Ping error: %v", err)
|
||||
return
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return
|
||||
default:
|
||||
@ -125,11 +130,15 @@ func (h *ChatHandler) readPump(ctx context.Context, conn *websocket.Conn, client
|
||||
|
||||
if err := conn.ReadJSON(&msg); err != nil {
|
||||
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
|
||||
log.Printf("WebSocket read error: %v", err)
|
||||
log.Printf("WebSocket error: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if msg.Type == "pong" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Обработка ping/pong
|
||||
if msg.Type == "ping" {
|
||||
conn.WriteJSON(map[string]string{"type": "pong"})
|
||||
|
||||
@ -39,30 +39,38 @@ func (s *chatService) SendMessage(ctx context.Context, senderID, chatID int, con
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Проверяем, что отправитель является участником чата
|
||||
if senderID != chat.User1ID && senderID != chat.User2ID {
|
||||
return nil, errors.New("user is not a participant of this chat")
|
||||
}
|
||||
|
||||
// Определяем получателя
|
||||
receiverID := chat.User1ID
|
||||
if senderID == chat.User1ID {
|
||||
receiverID = chat.User2ID
|
||||
}
|
||||
|
||||
// Создаем сообщение
|
||||
message := &domain.Message{
|
||||
ChatID: chatID,
|
||||
SenderID: senderID,
|
||||
ReceiverID: receiverID,
|
||||
ReceiverID: receiverID, // Гарантируем что receiverID всегда установлен
|
||||
Content: content,
|
||||
Status: "sent",
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
|
||||
// Сохраняем в БД
|
||||
if err := s.chatRepo.SaveMessage(ctx, message); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Отправляем сообщение через WebSocket
|
||||
// Отправляем через WebSocket только один раз
|
||||
if s.hub != nil {
|
||||
// Добавляем проверку перед рассылкой
|
||||
if message.ReceiverID == 0 {
|
||||
return nil, errors.New("receiver ID is required")
|
||||
}
|
||||
s.hub.Broadcast(message)
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package ws
|
||||
|
||||
import (
|
||||
"log"
|
||||
"sync"
|
||||
"tailly_back_v2/internal/domain"
|
||||
)
|
||||
@ -36,6 +37,16 @@ func (h *Hub) UnregisterClient(client *Client) {
|
||||
}
|
||||
|
||||
func (h *Hub) Broadcast(message *domain.Message) {
|
||||
if message == nil || message.SenderID == 0 {
|
||||
log.Println("Attempt to broadcast invalid message")
|
||||
return
|
||||
}
|
||||
|
||||
if message.ReceiverID == 0 {
|
||||
log.Printf("Message %d has no receiver", message.ID)
|
||||
return
|
||||
}
|
||||
|
||||
h.broadcast <- message
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user