nandi/gleanpublic Fork 0
c03febe
Commits
Clone
git clone https://git.rickub.com/nandi/glean.git
git clone ssh://git@rickub.com/nandi/glean.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Split people recommendations query between follow and non followUnverified

Julien Robert committed 2026-05-11T11:19:48+02:00 Browse files
c03febe parent: 81092e8
modified internal/cluster/scoring.go +22 -23
@@ -87,27 +87,21 @@ func (e *Engine) GetPeopleRecommendations(ctx context.Context, userDID string, l
8787 return entry, nil
8888 }
8989
90- recs, err := e.ComputePeopleRecommendationsOnDemand(ctx, userDID, limit*2)
90+ half := max(limit/2, 1)
91+
92+ inNet, err := e.computePeopleByFollowStatus(ctx, userDID, true, half)
9193 if err != nil {
9294 return nil, err
9395 }
9496
95- half := max(limit/2, 1)
96-
97- var inNet, outNet []*PersonRecommendation
98- for _, r := range recs {
99- if r.IsFollowed {
100- inNet = append(inNet, r)
101- } else {
102- outNet = append(outNet, r)
103- }
97+ outNet, err := e.computePeopleByFollowStatus(ctx, userDID, false, half)
98+ if err != nil {
99+ return nil, err
104100 }
105101
106- outTake := min(half, len(outNet))
107- inTake := min(limit-outTake, len(inNet))
108- recs = recs[:0]
109- recs = append(recs, inNet[:inTake]...)
110- recs = append(recs, outNet[:outTake]...)
102+ var recs []*PersonRecommendation
103+ recs = append(recs, inNet...)
104+ recs = append(recs, outNet...)
111105
112106 normalizePersonScores(recs)
113107 e.peopleCache.Add(userDID, recs)
@@ -522,11 +516,17 @@ func (e *Engine) ComputeArticleRecommendationsOnDemand(ctx context.Context, user
522516 return recs, rows.Err()
523517 }
524518
525-func (e *Engine) ComputePeopleRecommendationsOnDemand(ctx context.Context, userDID string, limit int) ([]*PersonRecommendation, error) {
519+func (e *Engine) computePeopleByFollowStatus(ctx context.Context, userDID string, followed bool, limit int) ([]*PersonRecommendation, error) {
520+ var followCond string
521+ if followed {
522+ followCond = "f.target_did IS NOT NULL"
523+ } else {
524+ followCond = "f.target_did IS NULL"
525+ }
526+
526527 rows, err := e.db.QueryContext(ctx, `
527528 SELECT u.did,
528- sim.jaccard, sim.common_feeds, COALESCE(sim.common_likes, 0), COALESCE(sim.common_tags, 0),
529- CASE WHEN f.target_did IS NOT NULL THEN 1 ELSE 0 END
529+ sim.jaccard, sim.common_feeds, COALESCE(sim.common_likes, 0), COALESCE(sim.common_tags, 0)
530530 FROM (
531531 SELECT user_b AS peer_did, jaccard, common_feeds, common_likes, common_tags FROM recs.user_similarity WHERE user_a = ?
532532 UNION ALL
@@ -534,7 +534,8 @@ func (e *Engine) ComputePeopleRecommendationsOnDemand(ctx context.Context, userD
534534 ) sim
535535 JOIN main.users u ON u.did = sim.peer_did
536536 LEFT JOIN main.follows f ON f.user_did = ? AND f.target_did = u.did
537- WHERE EXISTS (SELECT 1 FROM articles.subscriptions s JOIN articles.feeds f ON s.feed_url = f.feed_url WHERE s.user_did = u.did AND f.subscriber_count > 0)
537+ WHERE `+followCond+`
538+ AND EXISTS (SELECT 1 FROM articles.subscriptions s JOIN articles.feeds f2 ON s.feed_url = f2.feed_url WHERE s.user_did = u.did AND f2.subscriber_count > 0)
538539 AND NOT EXISTS (SELECT 1 FROM main.dismissed_recommendations d WHERE d.user_did = ? AND d.target_type = 'person' AND d.target_id = u.did)
539540 ORDER BY sim.jaccard DESC
540541 LIMIT ?
@@ -547,13 +548,11 @@ func (e *Engine) ComputePeopleRecommendationsOnDemand(ctx context.Context, userD
547548 var results []*PersonRecommendation
548549 for rows.Next() {
549550 rec := &PersonRecommendation{}
550- var isFollowed int
551551 if err := rows.Scan(&rec.DID,
552- &rec.Jaccard, &rec.CommonFeeds, &rec.CommonLikes, &rec.CommonTags,
553- &isFollowed); err != nil {
552+ &rec.Jaccard, &rec.CommonFeeds, &rec.CommonLikes, &rec.CommonTags); err != nil {
554553 return nil, err
555554 }
556- rec.IsFollowed = isFollowed == 1
555+ rec.IsFollowed = followed
557556 results = append(results, rec)
558557 }
559558 return results, rows.Err()
@@ -87,27 +87,21 @@ func (e *Engine) GetPeopleRecommendations(ctx context.Context, userDID string, l
87 return entry, nil87 return entry, nil
88 }88 }
89 89
90- recs, err := e.ComputePeopleRecommendationsOnDemand(ctx, userDID, limit*2)90+ half := max(limit/2, 1)
91+
92+ inNet, err := e.computePeopleByFollowStatus(ctx, userDID, true, half)
91 if err != nil {93 if err != nil {
92 return nil, err94 return nil, err
93 }95 }
94 96
95- half := max(limit/2, 1)97+ outNet, err := e.computePeopleByFollowStatus(ctx, userDID, false, half)
96-98+ if err != nil {
97- var inNet, outNet []*PersonRecommendation99+ return nil, err
98- for _, r := range recs {
99- if r.IsFollowed {
100- inNet = append(inNet, r)
101- } else {
102- outNet = append(outNet, r)
103- }
104 }100 }
105 101
106- outTake := min(half, len(outNet))102+ var recs []*PersonRecommendation
107- inTake := min(limit-outTake, len(inNet))103+ recs = append(recs, inNet...)
108- recs = recs[:0]104+ recs = append(recs, outNet...)
109- recs = append(recs, inNet[:inTake]...)
110- recs = append(recs, outNet[:outTake]...)
111 105
112 normalizePersonScores(recs)106 normalizePersonScores(recs)
113 e.peopleCache.Add(userDID, recs)107 e.peopleCache.Add(userDID, recs)
@@ -522,11 +516,17 @@ func (e *Engine) ComputeArticleRecommendationsOnDemand(ctx context.Context, user
522 return recs, rows.Err()516 return recs, rows.Err()
523 }517 }
524 518
525-func (e *Engine) ComputePeopleRecommendationsOnDemand(ctx context.Context, userDID string, limit int) ([]*PersonRecommendation, error) {519+func (e *Engine) computePeopleByFollowStatus(ctx context.Context, userDID string, followed bool, limit int) ([]*PersonRecommendation, error) {
520+ var followCond string
521+ if followed {
522+ followCond = "f.target_did IS NOT NULL"
523+ } else {
524+ followCond = "f.target_did IS NULL"
525+ }
526+
526 rows, err := e.db.QueryContext(ctx, `527 rows, err := e.db.QueryContext(ctx, `
527 SELECT u.did,528 SELECT u.did,
528- sim.jaccard, sim.common_feeds, COALESCE(sim.common_likes, 0), COALESCE(sim.common_tags, 0),529+ sim.jaccard, sim.common_feeds, COALESCE(sim.common_likes, 0), COALESCE(sim.common_tags, 0)
529- CASE WHEN f.target_did IS NOT NULL THEN 1 ELSE 0 END
530 FROM (530 FROM (
531 SELECT user_b AS peer_did, jaccard, common_feeds, common_likes, common_tags FROM recs.user_similarity WHERE user_a = ?531 SELECT user_b AS peer_did, jaccard, common_feeds, common_likes, common_tags FROM recs.user_similarity WHERE user_a = ?
532 UNION ALL532 UNION ALL
@@ -534,7 +534,8 @@ func (e *Engine) ComputePeopleRecommendationsOnDemand(ctx context.Context, userD
534 ) sim534 ) sim
535 JOIN main.users u ON u.did = sim.peer_did535 JOIN main.users u ON u.did = sim.peer_did
536 LEFT JOIN main.follows f ON f.user_did = ? AND f.target_did = u.did536 LEFT JOIN main.follows f ON f.user_did = ? AND f.target_did = u.did
537- WHERE EXISTS (SELECT 1 FROM articles.subscriptions s JOIN articles.feeds f ON s.feed_url = f.feed_url WHERE s.user_did = u.did AND f.subscriber_count > 0)537+ WHERE `+followCond+`
538+ AND EXISTS (SELECT 1 FROM articles.subscriptions s JOIN articles.feeds f2 ON s.feed_url = f2.feed_url WHERE s.user_did = u.did AND f2.subscriber_count > 0)
538 AND NOT EXISTS (SELECT 1 FROM main.dismissed_recommendations d WHERE d.user_did = ? AND d.target_type = 'person' AND d.target_id = u.did)539 AND NOT EXISTS (SELECT 1 FROM main.dismissed_recommendations d WHERE d.user_did = ? AND d.target_type = 'person' AND d.target_id = u.did)
539 ORDER BY sim.jaccard DESC540 ORDER BY sim.jaccard DESC
540 LIMIT ?541 LIMIT ?
@@ -547,13 +548,11 @@ func (e *Engine) ComputePeopleRecommendationsOnDemand(ctx context.Context, userD
547 var results []*PersonRecommendation548 var results []*PersonRecommendation
548 for rows.Next() {549 for rows.Next() {
549 rec := &PersonRecommendation{}550 rec := &PersonRecommendation{}
550- var isFollowed int
551 if err := rows.Scan(&rec.DID,551 if err := rows.Scan(&rec.DID,
552- &rec.Jaccard, &rec.CommonFeeds, &rec.CommonLikes, &rec.CommonTags,552+ &rec.Jaccard, &rec.CommonFeeds, &rec.CommonLikes, &rec.CommonTags); err != nil {
553- &isFollowed); err != nil {
554 return nil, err553 return nil, err
555 }554 }
556- rec.IsFollowed = isFollowed == 1555+ rec.IsFollowed = followed
557 results = append(results, rec)556 results = append(results, rec)
558 }557 }
559 return results, rows.Err()558 return results, rows.Err()