+79
-3
appview/db/follow.go
+79
-3
appview/db/follow.go
···
55
return err
56
}
57
58
-
func GetFollowerFollowingCount(e Execer, did string) (int, int, error) {
59
followers, following := 0, 0
60
err := e.QueryRow(
61
`SELECT
···
63
COUNT(CASE WHEN user_did = ? THEN 1 END) AS following
64
FROM follows;`, did, did).Scan(&followers, &following)
65
if err != nil {
66
-
return 0, 0, err
67
}
68
-
return followers, following, nil
69
}
70
71
func GetFollows(e Execer, limit int, filters ...filter) ([]Follow, error) {
···
55
return err
56
}
57
58
+
type FollowStats struct {
59
+
Followers int
60
+
Following int
61
+
}
62
+
63
+
func GetFollowerFollowingCount(e Execer, did string) (FollowStats, error) {
64
followers, following := 0, 0
65
err := e.QueryRow(
66
`SELECT
···
68
COUNT(CASE WHEN user_did = ? THEN 1 END) AS following
69
FROM follows;`, did, did).Scan(&followers, &following)
70
if err != nil {
71
+
return FollowStats{}, err
72
+
}
73
+
return FollowStats{
74
+
Followers: followers,
75
+
Following: following,
76
+
}, nil
77
+
}
78
+
79
+
func GetFollowerFollowingCounts(e Execer, dids []string) (map[string]FollowStats, error) {
80
+
if len(dids) == 0 {
81
+
return nil, nil
82
+
}
83
+
84
+
placeholders := make([]string, len(dids))
85
+
for i := range placeholders {
86
+
placeholders[i] = "?"
87
}
88
+
placeholderStr := strings.Join(placeholders, ",")
89
+
90
+
args := make([]any, len(dids)*2)
91
+
for i, did := range dids {
92
+
args[i] = did
93
+
args[i+len(dids)] = did
94
+
}
95
+
96
+
query := fmt.Sprintf(`
97
+
select
98
+
coalesce(f.did, g.did) as did,
99
+
coalesce(f.followers, 0) as followers,
100
+
coalesce(g.following, 0) as following
101
+
from (
102
+
select subject_did as did, count(*) as followers
103
+
from follows
104
+
where subject_did in (%s)
105
+
group by subject_did
106
+
) f
107
+
full outer join (
108
+
select user_did as did, count(*) as following
109
+
from follows
110
+
where user_did in (%s)
111
+
group by user_did
112
+
) g on f.did = g.did`,
113
+
placeholderStr, placeholderStr)
114
+
115
+
result := make(map[string]FollowStats)
116
+
117
+
rows, err := e.Query(query, args...)
118
+
if err != nil {
119
+
return nil, err
120
+
}
121
+
defer rows.Close()
122
+
123
+
for rows.Next() {
124
+
var did string
125
+
var followers, following int
126
+
if err := rows.Scan(&did, &followers, &following); err != nil {
127
+
return nil, err
128
+
}
129
+
result[did] = FollowStats{
130
+
Followers: followers,
131
+
Following: following,
132
+
}
133
+
}
134
+
135
+
for _, did := range dids {
136
+
if _, exists := result[did]; !exists {
137
+
result[did] = FollowStats{
138
+
Followers: 0,
139
+
Following: 0,
140
+
}
141
+
}
142
+
}
143
+
144
+
return result, nil
145
}
146
147
func GetFollows(e Execer, limit int, filters ...filter) ([]Follow, error) {
+3
-15
appview/db/timeline.go
+3
-15
appview/db/timeline.go
···
20
*FollowStats
21
}
22
23
-
type FollowStats struct {
24
-
Followers int
25
-
Following int
26
-
}
27
-
28
const Limit = 50
29
30
// TODO: this gathers heterogenous events from different sources and aggregates
···
156
return nil, err
157
}
158
159
-
followStatMap := make(map[string]FollowStats)
160
-
for _, s := range subjects {
161
-
followers, following, err := GetFollowerFollowingCount(e, s)
162
-
if err != nil {
163
-
return nil, err
164
-
}
165
-
followStatMap[s] = FollowStats{
166
-
Followers: followers,
167
-
Following: following,
168
-
}
169
}
170
171
var events []TimelineEvent
···
20
*FollowStats
21
}
22
23
const Limit = 50
24
25
// TODO: this gathers heterogenous events from different sources and aggregates
···
151
return nil, err
152
}
153
154
+
followStatMap, err := GetFollowerFollowingCounts(e, subjects)
155
+
if err != nil {
156
+
return nil, err
157
}
158
159
var events []TimelineEvent
+13
-8
appview/state/profile.go
+13
-8
appview/state/profile.go
···
63
return nil
64
}
65
66
-
followersCount, followingCount, err := db.GetFollowerFollowingCount(s.db, did)
67
if err != nil {
68
log.Printf("getting follow stats for %s: %s", did, err)
69
}
···
82
UserHandle: ident.Handle.String(),
83
Profile: profile,
84
FollowStatus: followStatus,
85
-
FollowersCount: followersCount,
86
-
FollowingCount: followingCount,
87
},
88
}
89
}
···
241
return FollowsPageParams{}, err
242
}
243
244
var loggedInUserFollowing map[string]struct{}
245
if loggedInUser != nil {
246
following, err := db.GetFollowing(s.db, loggedInUser.Did)
···
257
258
followCards := make([]pages.FollowCard, 0, len(follows))
259
for _, did := range followDids {
260
-
followersCount, followingCount, err := db.GetFollowerFollowingCount(s.db, did)
261
-
if err != nil {
262
-
log.Printf("getting follow stats for %s: %s", did, err)
263
}
264
followStatus := db.IsNotFollowing
265
if loggedInUserFollowing != nil {
···
279
followCards = append(followCards, pages.FollowCard{
280
UserDid: did,
281
FollowStatus: followStatus,
282
-
FollowersCount: followersCount,
283
-
FollowingCount: followingCount,
284
Profile: profile,
285
})
286
}
···
63
return nil
64
}
65
66
+
followStats, err := db.GetFollowerFollowingCount(s.db, did)
67
if err != nil {
68
log.Printf("getting follow stats for %s: %s", did, err)
69
}
···
82
UserHandle: ident.Handle.String(),
83
Profile: profile,
84
FollowStatus: followStatus,
85
+
FollowersCount: followStats.Followers,
86
+
FollowingCount: followStats.Following,
87
},
88
}
89
}
···
241
return FollowsPageParams{}, err
242
}
243
244
+
followStatsMap, err := db.GetFollowerFollowingCounts(s.db, followDids)
245
+
if err != nil {
246
+
log.Printf("getting follow counts for %s: %s", followDids, err)
247
+
}
248
+
249
var loggedInUserFollowing map[string]struct{}
250
if loggedInUser != nil {
251
following, err := db.GetFollowing(s.db, loggedInUser.Did)
···
262
263
followCards := make([]pages.FollowCard, 0, len(follows))
264
for _, did := range followDids {
265
+
followStats, exists := followStatsMap[did]
266
+
if !exists {
267
+
followStats = db.FollowStats{}
268
}
269
followStatus := db.IsNotFollowing
270
if loggedInUserFollowing != nil {
···
284
followCards = append(followCards, pages.FollowCard{
285
UserDid: did,
286
FollowStatus: followStatus,
287
+
FollowersCount: followStats.Followers,
288
+
FollowingCount: followStats.Following,
289
Profile: profile,
290
})
291
}
+3
-3
appview/strings/strings.go
+3
-3
appview/strings/strings.go
···
202
followStatus = db.GetFollowStatus(s.Db, loggedInUser.Did, id.DID.String())
203
}
204
205
-
followersCount, followingCount, err := db.GetFollowerFollowingCount(s.Db, id.DID.String())
206
if err != nil {
207
l.Error("failed to get follow stats", "err", err)
208
}
···
214
UserHandle: id.Handle.String(),
215
Profile: profile,
216
FollowStatus: followStatus,
217
-
FollowersCount: followersCount,
218
-
FollowingCount: followingCount,
219
},
220
Strings: all,
221
})
···
202
followStatus = db.GetFollowStatus(s.Db, loggedInUser.Did, id.DID.String())
203
}
204
205
+
followStats, err := db.GetFollowerFollowingCount(s.Db, id.DID.String())
206
if err != nil {
207
l.Error("failed to get follow stats", "err", err)
208
}
···
214
UserHandle: id.Handle.String(),
215
Profile: profile,
216
FollowStatus: followStatus,
217
+
FollowersCount: followStats.Followers,
218
+
FollowingCount: followStats.Following,
219
},
220
Strings: all,
221
})