From beb04196ca6140e607271ef0d1617cf1825d450b Mon Sep 17 00:00:00 2001 From: hobokenchicken Date: Mon, 27 Jul 2026 09:12:35 -0400 Subject: [PATCH] fix(gateway): direct DB query and normalized UserID matching in BroadcastToServer --- internal/gateway/hub.go | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/internal/gateway/hub.go b/internal/gateway/hub.go index e169cd6..d00cdca 100644 --- a/internal/gateway/hub.go +++ b/internal/gateway/hub.go @@ -5,6 +5,7 @@ import ( "database/sql" "encoding/json" "log/slog" + "strings" "sync" "time" ) @@ -285,15 +286,30 @@ func (h *Hub) BroadcastToServer(serverID string, event Event) { return } + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + rows, err := h.db.QueryContext(ctx, `SELECT user_id FROM members WHERE server_id = $1`, serverID) + if err != nil { + h.logger.Error("failed to load server members", "server_id", serverID, "error", err) + return + } + defer rows.Close() + + members := make(map[string]bool) + for rows.Next() { + var uid string + if err := rows.Scan(&uid); err == nil { + members[strings.ToLower(strings.TrimSpace(uid))] = true + } + } + h.mu.RLock() defer h.mu.RUnlock() for client := range h.clients { - servers, ok := h.userServers[client.UserID] - if !ok { - continue - } - if _, member := servers[serverID]; member { + cID := strings.ToLower(strings.TrimSpace(client.UserID)) + if members[cID] { select { case client.send <- data: default: @@ -322,18 +338,19 @@ func (h *Hub) BroadcastToConversation(convID string, event Event) { } defer rows.Close() - members := make(map[string]struct{}) + members := make(map[string]bool) for rows.Next() { var uid string if err := rows.Scan(&uid); err == nil { - members[uid] = struct{}{} + members[strings.ToLower(strings.TrimSpace(uid))] = true } } h.mu.RLock() defer h.mu.RUnlock() for client := range h.clients { - if _, ok := members[client.UserID]; ok { + cID := strings.ToLower(strings.TrimSpace(client.UserID)) + if members[cID] { select { case client.send <- data: default: