customer/internal/interface/sse/dispatcher.go
2025-06-25 17:06:25 +03:00

82 lines
2.4 KiB
Go

package sse
import (
"fmt"
)
type ConnectionDispatcher struct {
buffer *SSEConnectionRingBuffer
}
// bufferSize размер кольца минимум 2
func NewConnectionDispatcher(bufferSize int) *ConnectionDispatcher {
return &ConnectionDispatcher{
buffer: NewSSEConnectionRingBuffer(bufferSize),
}
}
func (r *ConnectionDispatcher) AddConnection(userID, deviceID string) *SSEConnection {
conn := NewSSEConnection(userID, deviceID)
currentMap := r.buffer.GetCurrent() // тут текущие данные откуда читают воркеры
nextMap := r.buffer.GetNext() // следующая поидее должна быть пустой
for key, value := range currentMap {
nextMap[key] = value
}
// покомментарию Миши копируем слайсы отдельно
existingConnections := nextMap[userID]
newConnections := make([]*SSEConnection, len(existingConnections)+1)
copy(newConnections, existingConnections)
newConnections[len(existingConnections)] = conn
nextMap[userID] = newConnections
r.buffer.Rotate()
return conn
}
func (r *ConnectionDispatcher) RemoveConnection(userID, deviceID string) {
currentMap := r.buffer.GetCurrent() // тут текущие данные откуда читают воркеры
nextMap := r.buffer.GetNext() // следующая на которую переключимся
for key, value := range currentMap {
nextMap[key] = value
}
existingConnections := nextMap[userID]
afterDropConnections := make([]*SSEConnection, 0, len(existingConnections))
for _, conn := range existingConnections {
if conn.DeviceID != deviceID {
afterDropConnections = append(afterDropConnections, conn)
} else {
close(conn.Channel)
}
}
// если есть коннекты то складываем оставшиеся после удаления, если == 0 то дропаем этого пользователя из мэпки
if len(afterDropConnections) > 0 {
nextMap[userID] = afterDropConnections
} else {
delete(nextMap, userID)
}
r.buffer.Rotate()
}
func (r *ConnectionDispatcher) SendToUser(userID string, event SSEEvent) error {
currentMap := r.buffer.GetCurrent()
connections := currentMap[userID]
if len(connections) == 0 {
return fmt.Errorf("no active connections for user %s", userID)
}
for _, conn := range connections {
conn.Channel <- event
}
return nil
}