From c1396ffb6b7c1455a57c536e7c2e7978b6ce5a82 Mon Sep 17 00:00:00 2001 From: ga Date: Fri, 21 Aug 2026 12:31:11 +0000 Subject: [PATCH] =?UTF-8?q?Fix:=20ListChats=20scan=20NULL=20=D0=B2=20strin?= =?UTF-8?q?g=20=E2=86=92=20500?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pgx не мог сканировать NULL из COALESCE(...,'') когда OtherPhoto был *string. После преобразования subquery photo в строки и OtherPhoto в string, scan работает. Проверено: Алиса и Тест получают свои чаты 200, без 500. --- internal/chat/repo.go | 21 ++++++++------------- internal/handlers/handlers.go | 25 +++++++++++++++++-------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/internal/chat/repo.go b/internal/chat/repo.go index e6cf4a5..8b21245 100644 --- a/internal/chat/repo.go +++ b/internal/chat/repo.go @@ -93,18 +93,17 @@ func (r *Repo) ListChats(ctx context.Context, me uuid.UUID, limit, offset int) ( } rows, err := r.pool.Query(ctx, ` SELECT c.id, c.user_a, c.user_b, c.created_at, c.last_msg_at, - CASE WHEN c.user_a = $1 THEN c.user_b ELSE c.user_a END AS other_id, - u.name, - u.photo_url, - (SELECT COALESCE(body, '') FROM messages m + CASE WHEN c.user_a = $1::uuid THEN c.user_b ELSE c.user_a END AS other_id, + COALESCE((SELECT name FROM users WHERE id = CASE WHEN c.user_a = $1::uuid THEN c.user_b ELSE c.user_a END), '') AS other_name, + COALESCE((SELECT photo_url FROM users WHERE id = CASE WHEN c.user_a = $1::uuid THEN c.user_b ELSE c.user_a END), '') AS other_photo, + COALESCE((SELECT body FROM messages m WHERE m.chat_id = c.id AND m.deleted = FALSE - ORDER BY m.created_at DESC LIMIT 1) AS last_body, + ORDER BY m.created_at DESC LIMIT 1), '') AS last_body, (SELECT COUNT(*) FROM messages m WHERE m.chat_id = c.id AND m.read = FALSE - AND m.sender_id != $1) AS unread + AND m.sender_id != $1::uuid) AS unread FROM chats c - JOIN users u ON u.id = CASE WHEN c.user_a = $1 THEN c.user_b ELSE c.user_a END - WHERE c.user_a = $1 OR c.user_b = $1 + WHERE c.user_a = $1::uuid OR c.user_b = $1::uuid ORDER BY c.last_msg_at DESC LIMIT $2 OFFSET $3`, me, limit, offset, @@ -117,14 +116,10 @@ func (r *Repo) ListChats(ctx context.Context, me uuid.UUID, limit, offset int) ( var out []ChatListItem for rows.Next() { var c ChatListItem - var photo *string if err := rows.Scan(&c.Chat.ID, &c.Chat.UserA, &c.Chat.UserB, &c.Chat.CreatedAt, &c.Chat.LastMsgAt, - &c.OtherID, &c.OtherName, &photo, &c.LastMessage, &c.UnreadCount); err != nil { + &c.OtherID, &c.OtherName, &c.OtherPhoto, &c.LastMessage, &c.UnreadCount); err != nil { return nil, err } - if photo != nil { - c.OtherPhoto = *photo - } c.LastMsgAt = c.Chat.LastMsgAt out = append(out, c) } diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go index 071429b..12b0a63 100644 --- a/internal/handlers/handlers.go +++ b/internal/handlers/handlers.go @@ -329,12 +329,16 @@ func age(birth *time.Time) *int { // DebugLog — клиент-сайд диагностика (приходит из JS через api.js) type debugLogReq struct { - Path string `json:"path"` - Status int `json:"status"` - Ms int `json:"ms"` - UA string `json:"ua"` - Err string `json:"err,omitempty"` - IsTelegram bool `json:"is_telegram"` + Path string `json:"path"` + Status int `json:"status"` + Ms int `json:"ms"` + UA string `json:"ua"` + Err string `json:"err,omitempty"` + IsTelegram bool `json:"is_telegram"` + Kind string `json:"kind,omitempty"` + UserID string `json:"userId,omitempty"` + Msg string `json:"msg,omitempty"` + Stack string `json:"stack,omitempty"` } func (h *Handlers) DebugLog(c *fiber.Ctx) error { @@ -342,7 +346,7 @@ func (h *Handlers) DebugLog(c *fiber.Ctx) error { if err := c.BodyParser(&req); err != nil { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "bad body"}) } - slog.Info("client-debug", + attrs := []any{ "path", req.Path, "status", req.Status, "ms", req.Ms, @@ -350,6 +354,11 @@ func (h *Handlers) DebugLog(c *fiber.Ctx) error { "ua", req.UA, "err", req.Err, "ip", c.IP(), - ) + } + if req.Kind != "" { + attrs = append(attrs, "kind", req.Kind, "userId", req.UserID, "msg", req.Msg) + if req.Stack != "" { attrs = append(attrs, "stack", req.Stack) } + } + slog.Info("client-debug", attrs...) return c.JSON(fiber.Map{"ok": true}) }