Go · 1382 bytes Raw Blame History
1 // SPDX-License-Identifier: AGPL-3.0-or-later
2
3 package notif
4
5 import (
6 "context"
7
8 "github.com/jackc/pgx/v5/pgxpool"
9
10 "github.com/tenseleyFlow/shithub/internal/markdown"
11 usersdb "github.com/tenseleyFlow/shithub/internal/users/sqlc"
12 )
13
14 // ResolveMentionUserIDs maps a slice of (possibly duplicate)
15 // `markdown.Mention` records to deduplicated user IDs. Unknown,
16 // suspended, and soft-deleted accounts are silently dropped — the
17 // fan-out worker should never produce notifications for accounts
18 // that wouldn't have read access. Result is stable-ordered by
19 // first-occurrence in the input.
20 //
21 // The lookup is one-by-one rather than batched: typical mention
22 // counts are in the single digits and the per-username GetUserByUsername
23 // is index-backed. Batching becomes worth it only above ~50 distinct
24 // mentions per body.
25 func ResolveMentionUserIDs(ctx context.Context, pool *pgxpool.Pool, ms []markdown.Mention) []int64 {
26 if len(ms) == 0 {
27 return nil
28 }
29 q := usersdb.New()
30 seen := map[int64]struct{}{}
31 out := make([]int64, 0, len(ms))
32 for _, m := range ms {
33 u, err := q.GetUserByUsername(ctx, pool, m.Username)
34 if err != nil {
35 continue
36 }
37 if u.SuspendedAt.Valid || u.DeletedAt.Valid {
38 continue
39 }
40 if _, dup := seen[u.ID]; dup {
41 continue
42 }
43 seen[u.ID] = struct{}{}
44 out = append(out, u.ID)
45 }
46 if len(out) == 0 {
47 return nil
48 }
49 return out
50 }
51