@@ -3,41 +3,39 @@ const fetch = require("node-fetch");
33const Contest = require ( "../models/contest" ) ;
44let halfHour = 1000 * 60 * 30 ;
55
6- async function pushRankingsToContest (
7- contest_id ,
8- rankings ,
9- pagesCnt ,
10- islastPage
11- ) {
12- try {
13- await Contest . findOneAndUpdate (
14- {
15- _id : contest_id ,
16- } ,
17- {
18- $push : {
19- rankings : rankings ,
20- } ,
21- $inc : {
22- pages_fetched : pagesCnt ,
23- } ,
24- $set : {
25- rankings_fetched : islastPage ,
26- } ,
27- }
28- ) ;
6+ // async function pushRankingsToContest(
7+ // contest_id,
8+ // rankings,
9+ // pagesCnt,
10+ // islastPage
11+ // ) {
12+ // try {
13+ // await Contest.findOneAndUpdate(
14+ // {
15+ // _id: contest_id,
16+ // },
17+ // {
18+ // $push: {
19+ // rankings: rankings,
20+ // },
21+ // $inc: {
22+ // pages_fetched: pagesCnt,
23+ // },
24+ // $set: {
25+ // rankings_fetched: islastPage,
26+ // },
27+ // }
28+ // );
2929
30- return null ;
31- } catch ( err ) {
32- console . log ( err ) ;
33- return err ;
34- }
35- }
30+ // return null;
31+ // } catch (err) {
32+ // console.log(err);
33+ // return err;
34+ // }
35+ // }
3636const fetchContestRankings = async function ( contestSlug ) {
3737 try {
38- let contest = await Contest . findById ( contestSlug , {
39- rankings : 0 ,
40- } ) ;
38+ let contest = await Contest . findById ( contestSlug , { rankings : 0 } ) ;
4139 if ( ! contest ) {
4240 return Error ( `Contest ${ contestSlug } not found in the db` ) ;
4341 }
@@ -47,54 +45,86 @@ const fetchContestRankings = async function (contestSlug) {
4745 `https://leetcode.com/contest/api/ranking/${ contestSlug } /?region=global`
4846 ) ;
4947 resp = await resp . json ( ) ;
50- // let num_user = resp.user_num
51- let pages = Math . floor ( resp . user_num / 25 ) ,
52- page = contest . pages_fetched + 1 ;
53- for ( let i = page ; i <= pages ; i ++ ) {
54- console . log ( `Fetching rankings (${ contestSlug } ): page: ${ i } ` ) ;
55- let res = await fetch (
56- `https://leetcode.com/contest/api/ranking/${ contestSlug } /?pagination=${ i } ®ion=global`
57- ) ;
58- res = await res . json ( ) ;
59- rankings = res . total_rank
60- . filter (
61- ( ranks ) =>
62- ! (
63- ranks . score == 0 &&
64- ranks . finish_time * 1000 ==
65- contest . startTime . getTime ( )
66- )
67- )
68- . map ( ( ranks ) => {
69- let {
70- username,
71- user_slug,
72- country_code,
73- country_name,
74- data_region,
75- rank,
76- } = ranks ;
77- let ranking = {
78- username,
79- user_slug,
80- country_code,
81- country_name,
82- data_region,
83- rank,
84- } ;
85- ranking [ "_id" ] = username ;
86- return ranking ;
87- } ) ;
88- let err = await pushRankingsToContest (
89- contest . _id ,
90- rankings ,
91- 1 ,
92- i === pages
93- ) ;
94- if ( err ) {
95- return err ;
48+ let pages = Math . floor ( resp . user_num / 25 ) ;
49+ let all_rankings = [ ] ;
50+ let failed = [ ] ;
51+ const fetchPageRankings = async (
52+ pageNo ,
53+ retries ,
54+ throwError = false
55+ ) => {
56+ console . log ( `Fetching rankings (${ contestSlug } ): page: ${ pageNo } ` ) ;
57+ try {
58+ let res = await fetch (
59+ `https://leetcode.com/contest/api/ranking/${ contestSlug } /?pagination=${ pageNo } ®ion=global`
60+ ) ;
61+ res = await res . json ( ) ;
62+ rankings = res . total_rank
63+ . filter (
64+ ( ranks ) =>
65+ ! (
66+ ranks . score == 0 &&
67+ ranks . finish_time * 1000 ==
68+ contest . startTime . getTime ( )
69+ )
70+ )
71+ . map ( ( ranks ) => {
72+ let {
73+ username,
74+ user_slug,
75+ country_code,
76+ country_name,
77+ data_region,
78+ rank,
79+ } = ranks ;
80+ let ranking = {
81+ username,
82+ user_slug,
83+ country_code,
84+ country_name,
85+ data_region,
86+ rank,
87+ } ;
88+ ranking [ "_id" ] = username ;
89+ return ranking ;
90+ } ) ;
91+ all_rankings = all_rankings . concat ( rankings ) ;
92+ console . log (
93+ `Fetched rankings (${ contestSlug } ): page: ${ pageNo } `
94+ ) ;
95+ } catch ( err ) {
96+ console . log (
97+ `Failed to fetch rankings (${ contestSlug } , page: ${ pageNo } )`
98+ ) ;
99+ console . log ( err ) ;
100+ if ( retries > 0 ) {
101+ await fetchPageRankings ( pageNo , retries - 1 ) ;
102+ } else if ( throwError ) {
103+ throw err ;
104+ } else {
105+ failed . push ( pageNo ) ;
106+ }
107+ }
108+ } ;
109+ const limit = 5 ;
110+ const maxRetries = 5 ;
111+ for ( let i = 0 ; i < pages ; i += limit ) {
112+ let promises = [ ] ;
113+ for ( let j = 0 ; j < limit && i + j < pages ; j ++ ) {
114+ promises . push ( fetchPageRankings ( i + j + 1 , maxRetries ) ) ;
96115 }
116+ await Promise . all ( promises ) ;
117+ }
118+
119+ for ( let i = 0 ; i < failed . length ; i ++ ) {
120+ await fetchPageRankings ( failed [ i ] , maxRetries , true ) ;
97121 }
122+
123+ all_rankings . sort ( ( a , b ) => ( a . rank > b . rank ? 1 : - 1 ) ) ;
124+ contest . rankings = all_rankings ;
125+ contest . rankings_fetched = true ;
126+ contest . user_num = resp . user_num ;
127+ await contest . save ( ) ;
98128 console . log ( `Updated Rankings in ${ contestSlug } .` ) ;
99129 } catch ( err ) {
100130 return err ;
0 commit comments