feat: disciple link
This commit is contained in:
@@ -334,6 +334,62 @@ func (r *NotificationRepo) CreateAdminMessage(ctx context.Context, userID, body
|
||||
return nil
|
||||
}
|
||||
|
||||
// BroadcastToAllUsers writes one notification of `kind` to every active user
|
||||
// except `actorID`, in a single INSERT…SELECT. One round trip regardless of
|
||||
// audience size — the alternative (a row per user from Go) would be hundreds
|
||||
// of round trips on the request path.
|
||||
//
|
||||
// Deliberately does NOT filter on notification_prefs: ListByUser already
|
||||
// excludes kinds the reader has disabled for the in_app channel at read time,
|
||||
// so writing the rows unconditionally keeps a re-enabled preference able to
|
||||
// surface history — exactly how the existing kinds behave.
|
||||
//
|
||||
// Banned accounts are skipped; they can't sign in to read it anyway.
|
||||
func (r *NotificationRepo) BroadcastToAllUsers(ctx context.Context, kind, actorID string) (int64, error) {
|
||||
tag, err := r.pg.Pool.Exec(ctx, `
|
||||
INSERT INTO notifications (user_id, actor_id, kind)
|
||||
SELECT u.id, $2, $1
|
||||
FROM users u
|
||||
WHERE u.id <> $2 AND u.banned_at IS NULL`, kind, actorID)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("broadcast notification: %w", err)
|
||||
}
|
||||
return tag.RowsAffected(), nil
|
||||
}
|
||||
|
||||
// PushRecipientsForKind lists the ids of users who should receive a *push* for
|
||||
// `kind` — everyone except the actor, minus banned accounts, minus anyone who
|
||||
// turned this kind off for the push channel, and minus anyone with no push
|
||||
// subscription registered at all.
|
||||
//
|
||||
// That last filter is what keeps a broadcast cheap: only devotees who actually
|
||||
// enabled web push are worth iterating, which is typically a small fraction of
|
||||
// the user base.
|
||||
func (r *NotificationRepo) PushRecipientsForKind(ctx context.Context, kind, actorID string) ([]string, error) {
|
||||
rows, err := r.pg.Pool.Query(ctx, `
|
||||
SELECT DISTINCT u.id
|
||||
FROM users u
|
||||
JOIN push_subscriptions ps ON ps.user_id = u.id
|
||||
WHERE u.id <> $2 AND u.banned_at IS NULL
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM notification_prefs np
|
||||
WHERE np.user_id = u.id AND np.kind = $1
|
||||
AND np.channel = 'push' AND np.enabled = FALSE)`, kind, actorID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("list push recipients: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
out := []string{}
|
||||
for rows.Next() {
|
||||
var id string
|
||||
if err := rows.Scan(&id); err != nil {
|
||||
return nil, fmt.Errorf("scan push recipient: %w", err)
|
||||
}
|
||||
out = append(out, id)
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
// ListByUser returns a recipient's notifications, newest first, with the
|
||||
// actor's display fields joined in for rendering (nil for system
|
||||
// notifications or since-deleted actors). Kinds the user has turned off for
|
||||
|
||||
Reference in New Issue
Block a user