@@ -119,89 +119,103 @@ func NewLocalLeaderboardRankCache(startupLogger *zap.Logger, db *sql.DB, config
119
119
120
120
nowTime := time .Now ().UTC ()
121
121
122
- skippedLeaderboards := make ([]string , 0 , 10 )
123
- leaderboards := leaderboardCache .GetAllLeaderboards ()
124
- cachedLeaderboards := make ([]string , 0 , len (leaderboards ))
125
- for _ , leaderboard := range leaderboards {
126
- if _ , ok := cache .blacklistIds [leaderboard .Id ]; ok {
127
- startupLogger .Debug ("Skip caching leaderboard ranks" , zap .String ("leaderboard_id" , leaderboard .Id ))
128
- skippedLeaderboards = append (skippedLeaderboards , leaderboard .Id )
129
- continue
130
- }
122
+ go func () {
123
+ skippedLeaderboards := make ([]string , 0 , 10 )
124
+ leaderboards := leaderboardCache .GetAllLeaderboards ()
125
+ cachedLeaderboards := make ([]string , 0 , len (leaderboards ))
126
+ for _ , leaderboard := range leaderboards {
127
+ if _ , ok := cache .blacklistIds [leaderboard .Id ]; ok {
128
+ startupLogger .Debug ("Skip caching leaderboard ranks" , zap .String ("leaderboard_id" , leaderboard .Id ))
129
+ skippedLeaderboards = append (skippedLeaderboards , leaderboard .Id )
130
+ continue
131
+ }
131
132
132
- cachedLeaderboards = append (cachedLeaderboards , leaderboard .Id )
133
- startupLogger .Debug ("Caching leaderboard ranks" , zap .String ("leaderboard_id" , leaderboard .Id ))
133
+ cachedLeaderboards = append (cachedLeaderboards , leaderboard .Id )
134
+ startupLogger .Debug ("Caching leaderboard ranks" , zap .String ("leaderboard_id" , leaderboard .Id ))
134
135
135
- // Current expiry for this leaderboard.
136
- // This matches calculateTournamentDeadlines
137
- var expiryUnix int64
138
- if leaderboard .ResetSchedule != nil {
139
- expiryUnix = leaderboard .ResetSchedule .Next (nowTime ).UTC ().Unix ()
140
- if leaderboard .EndTime > 0 && expiryUnix > leaderboard .EndTime {
136
+ // Current expiry for this leaderboard.
137
+ // This matches calculateTournamentDeadlines
138
+ var expiryUnix int64
139
+ if leaderboard .ResetSchedule != nil {
140
+ expiryUnix = leaderboard .ResetSchedule .Next (nowTime ).UTC ().Unix ()
141
+ if leaderboard .EndTime > 0 && expiryUnix > leaderboard .EndTime {
142
+ expiryUnix = leaderboard .EndTime
143
+ }
144
+ } else {
141
145
expiryUnix = leaderboard .EndTime
142
146
}
143
- } else {
144
- expiryUnix = leaderboard .EndTime
145
- }
146
147
147
- // Prepare structure to receive rank data.
148
- rankCache := & RankCache {
149
- owners : make (map [uuid.UUID ]skiplist.Interface ),
150
- cache : skiplist .New (),
151
- }
152
- key := LeaderboardWithExpiry {LeaderboardId : leaderboard .Id , Expiry : expiryUnix }
153
- cache .cache [key ] = rankCache
148
+ // Prepare structure to receive rank data.
149
+ key := LeaderboardWithExpiry {LeaderboardId : leaderboard .Id , Expiry : expiryUnix }
150
+ cache .Lock ()
151
+ rankCache , found := cache .cache [key ]
152
+ if ! found {
153
+ rankCache = & RankCache {
154
+ owners : make (map [uuid.UUID ]skiplist.Interface ),
155
+ cache : skiplist .New (),
156
+ }
157
+ cache .cache [key ] = rankCache
158
+ }
159
+ cache .Unlock ()
154
160
155
- // Look up all active records for this leaderboard.
156
- query := `
161
+ // Look up all active records for this leaderboard.
162
+ query := `
157
163
SELECT owner_id, score, subscore
158
164
FROM leaderboard_record
159
165
WHERE leaderboard_id = $1 AND expiry_time = $2`
160
- rows , err := db .Query (query , leaderboard .Id , time .Unix (expiryUnix , 0 ).UTC ())
161
- if err != nil {
162
- startupLogger .Fatal ("Failed to caching leaderboard ranks" , zap .String ("leaderboard_id" , leaderboard .Id ), zap .Error (err ))
163
- return nil
164
- }
165
-
166
- // Process the records.
167
- for rows .Next () {
168
- var ownerIDStr string
169
- var score int64
170
- var subscore int64
171
-
172
- if err = rows .Scan (& ownerIDStr , & score , & subscore ); err != nil {
173
- startupLogger .Fatal ("Failed to scan leaderboard rank data" , zap .String ("leaderboard_id" , leaderboard .Id ), zap .Error (err ))
174
- return nil
175
- }
176
- ownerID , err := uuid .FromString (ownerIDStr )
166
+ rows , err := db .Query (query , leaderboard .Id , time .Unix (expiryUnix , 0 ).UTC ())
177
167
if err != nil {
178
- startupLogger .Fatal ("Failed to parse scanned leaderboard rank data " , zap .String ("leaderboard_id" , leaderboard .Id ), zap . String ( "owner_id" , ownerIDStr ), zap .Error (err ))
179
- return nil
168
+ startupLogger .Error ("Failed to caching leaderboard ranks " , zap .String ("leaderboard_id" , leaderboard .Id ), zap .Error (err ))
169
+ continue
180
170
}
181
171
182
- // Prepare new rank data for this leaderboard entry.
183
- var rankData skiplist.Interface
184
- if leaderboard .SortOrder == LeaderboardSortOrderDescending {
185
- rankData = & RankDesc {
186
- OwnerId : ownerID ,
187
- Score : score ,
188
- Subscore : subscore ,
172
+ // Process the records.
173
+ for rows .Next () {
174
+ var ownerIDStr string
175
+ var score int64
176
+ var subscore int64
177
+
178
+ if err = rows .Scan (& ownerIDStr , & score , & subscore ); err != nil {
179
+ startupLogger .Error ("Failed to scan leaderboard rank data" , zap .String ("leaderboard_id" , leaderboard .Id ), zap .Error (err ))
180
+ break
189
181
}
190
- } else {
191
- rankData = & RankAsc {
192
- OwnerId : ownerID ,
193
- Score : score ,
194
- Subscore : subscore ,
182
+ ownerID , err := uuid .FromString (ownerIDStr )
183
+ if err != nil {
184
+ startupLogger .Error ("Failed to parse scanned leaderboard rank data" , zap .String ("leaderboard_id" , leaderboard .Id ), zap .String ("owner_id" , ownerIDStr ), zap .Error (err ))
185
+ break
195
186
}
196
- }
197
187
198
- rankCache .owners [ownerID ] = rankData
199
- rankCache .cache .Insert (rankData )
188
+ // Prepare new rank data for this leaderboard entry.
189
+ var rankData skiplist.Interface
190
+ if leaderboard .SortOrder == LeaderboardSortOrderDescending {
191
+ rankData = & RankDesc {
192
+ OwnerId : ownerID ,
193
+ Score : score ,
194
+ Subscore : subscore ,
195
+ }
196
+ } else {
197
+ rankData = & RankAsc {
198
+ OwnerId : ownerID ,
199
+ Score : score ,
200
+ Subscore : subscore ,
201
+ }
202
+ }
203
+
204
+ rankCache .Lock ()
205
+ if _ , alreadyInserted := rankCache .owners [ownerID ]; alreadyInserted {
206
+ rankCache .Unlock ()
207
+ continue
208
+ }
209
+ rankCache .owners [ownerID ] = rankData
210
+ rankCache .cache .Insert (rankData )
211
+ rankCache .Unlock ()
212
+ }
213
+ _ = rows .Close ()
200
214
}
201
- _ = rows .Close ()
202
- }
203
215
204
- startupLogger .Info ("Leaderboard rank cache initialization completed successfully" , zap .Strings ("cached" , cachedLeaderboards ), zap .Strings ("skipped" , skippedLeaderboards ))
216
+ startupLogger .Info ("Leaderboard rank cache initialization completed successfully" , zap .Strings ("cached" , cachedLeaderboards ), zap .Strings ("skipped" , skippedLeaderboards ))
217
+ }()
218
+
205
219
return cache
206
220
}
207
221
0 commit comments