@@ -3,13 +3,16 @@ import Logger from "../utils/logger";
33import { performance } from "perf_hooks" ;
44import { setLeaderboard } from "../utils/prometheus" ;
55import { isDevEnvironment } from "../utils/misc" ;
6- import { getCachedConfiguration } from "../init/configuration" ;
6+ import {
7+ getCachedConfiguration ,
8+ getLiveConfiguration ,
9+ } from "../init/configuration" ;
710
811import { addLog } from "./logs" ;
912import { Collection , ObjectId } from "mongodb" ;
1013import { LeaderboardEntry } from "@monkeytype/contracts/schemas/leaderboards" ;
1114import { omit } from "lodash" ;
12- import { DBUser } from "./user" ;
15+ import { DBUser , getUsersCollection } from "./user" ;
1316import MonkeyError from "../utils/error" ;
1417
1518export type DBLeaderboardEntry = LeaderboardEntry & {
@@ -269,7 +272,11 @@ export async function update(
269272 } ;
270273}
271274
272- async function createIndex ( key : string ) : Promise < void > {
275+ async function createIndex (
276+ key : string ,
277+ minTimeTyping : number ,
278+ dropIfMismatch = true
279+ ) : Promise < void > {
273280 const index = {
274281 [ `${ key } .wpm` ] : - 1 ,
275282 [ `${ key } .acc` ] : - 1 ,
@@ -293,16 +300,41 @@ async function createIndex(key: string): Promise<void> {
293300 $gt : 0 ,
294301 } ,
295302 timeTyping : {
296- $gt : isDevEnvironment ( ) ? 0 : 7200 ,
303+ $gt : minTimeTyping ,
297304 } ,
298305 } ,
299306 } ;
300- await db . collection ( "users" ) . createIndex ( index , partial ) ;
307+ try {
308+ await getUsersCollection ( ) . createIndex ( index , partial ) ;
309+ } catch ( e ) {
310+ if ( ! dropIfMismatch ) throw e ;
311+ if (
312+ ( e as Error ) . message . startsWith (
313+ "An existing index has the same name as the requested index"
314+ )
315+ ) {
316+ Logger . warning ( `Index ${ key } not matching, dropping and recreating...` ) ;
317+
318+ const existingIndex = ( await getUsersCollection ( ) . listIndexes ( ) . toArray ( ) )
319+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
320+ . map ( ( it ) => it . name as string )
321+ . find ( ( it ) => it . startsWith ( key ) ) ;
322+
323+ if ( existingIndex !== undefined && existingIndex !== null ) {
324+ await getUsersCollection ( ) . dropIndex ( existingIndex ) ;
325+ return createIndex ( key , minTimeTyping , false ) ;
326+ } else {
327+ throw e ;
328+ }
329+ }
330+ }
301331}
302332
303333export async function createIndicies ( ) : Promise < void > {
304- await createIndex ( "lbPersonalBests.time.15.english" ) ;
305- await createIndex ( "lbPersonalBests.time.60.english" ) ;
334+ const minTimeTyping = ( await getLiveConfiguration ( ) ) . leaderboards
335+ . minTimeTyping ;
336+ await createIndex ( "lbPersonalBests.time.15.english" , minTimeTyping ) ;
337+ await createIndex ( "lbPersonalBests.time.60.english" , minTimeTyping ) ;
306338
307339 if ( isDevEnvironment ( ) ) {
308340 Logger . info ( "Updating leaderboards in dev mode..." ) ;
0 commit comments