11import { GraphQLClient , gql } from 'graphql-request' ;
22import fs from 'fs' ;
33import path from 'path' ;
4- import { AllDataQuery } from '../generated/types' ;
4+ import { ProjectsPageQuery , StaticDataQuery } from '../generated/types' ;
5+
6+ type FetchedData = StaticDataQuery & { publicProjects : ProjectsPageQuery [ 'publicProjects' ] } ;
57
68const datadir = path . join ( __dirname , '../fullData' ) ;
79const baseUrl = process . env . MAPSWIPE_API_ENDPOINT || 'http://localhost:8000/' ;
@@ -12,7 +14,7 @@ const pipelineType = process.env.PIPELINE_TYPE;
1214
1315const graphQLClient = new GraphQLClient ( GRAPHQL_ENDPOINT ) ;
1416
15- const dummyData : AllDataQuery = {
17+ const dummyData : FetchedData = {
1618 publicProjects : {
1719 results : [ ] ,
1820 totalCount : 0 ,
@@ -29,15 +31,17 @@ const dummyData: AllDataQuery = {
2931 globalExportAssets : [ ] ,
3032} ;
3133
32- const query = gql `
33- query AllData {
34+ const PROJECT_PAGE_SIZE = 500 ;
35+
36+ const projectsQuery = gql `
37+ query ProjectsPage($limit: Int!, $offset: Int!) {
3438 publicProjects(
3539 filters: {
3640 status: {
3741 inList: [PUBLISHED, FINISHED],
3842 },
3943 },
40- pagination: { limit: 9999 },
44+ pagination: { limit: $limit, offset: $offset },
4145 ) {
4246 results {
4347 id
@@ -175,6 +179,11 @@ const query = gql`
175179 }
176180 totalCount
177181 }
182+ }
183+ ` ;
184+
185+ const staticQuery = gql `
186+ query StaticData {
178187 communityStats {
179188 id
180189 totalContributors
@@ -225,8 +234,32 @@ async function getCsrfTokenValue() {
225234 return undefined ;
226235}
227236
237+ const MAX_RETRIES = 3 ;
238+
239+ async function requestWithRetry < T > (
240+ requestFn : ( ) => Promise < T > ,
241+ ) : Promise < T > {
242+ for ( let attempt = 1 ; attempt <= MAX_RETRIES ; attempt ++ ) {
243+ try {
244+ // eslint-disable-next-line no-await-in-loop
245+ return await requestFn ( ) ;
246+ } catch ( err : unknown ) {
247+ const status = ( err as { response ?: { status ?: number } } ) ?. response ?. status ;
248+ const isServerError = status !== undefined && status >= 500 ;
249+ if ( isServerError && attempt < MAX_RETRIES ) {
250+ // eslint-disable-next-line no-console
251+ console . warn ( `Request failed with ${ status } (attempt ${ attempt } /${ MAX_RETRIES } ). Retrying...` ) ;
252+ } else {
253+ throw err ;
254+ }
255+ }
256+ }
257+ // unreachable, but satisfies the return type
258+ throw new Error ( 'Unexpected end of requestWithRetry' ) ;
259+ }
260+
228261async function fetchAndWriteData ( ) {
229- let data = { } as AllDataQuery ;
262+ let data = { } as FetchedData ;
230263 if ( pipelineType === 'ci' ) {
231264 data = dummyData ;
232265 } else {
@@ -245,7 +278,33 @@ async function fetchAndWriteData() {
245278 graphQLClient . setHeader ( 'X-CSRFToken' , csrfTokenValue ) ;
246279 graphQLClient . setHeader ( 'Cookie' , `${ COOKIE_NAME } =${ csrfTokenValue } ` ) ;
247280 graphQLClient . setHeader ( 'Referer' , referer ) ;
248- data = ( await graphQLClient . request ( query ) ) as AllDataQuery ;
281+
282+ const staticData = ( await requestWithRetry ( ( ) => graphQLClient . request ( staticQuery ) ) ) as Pick <
283+ FetchedData ,
284+ 'communityStats' | 'publicOrganizations' | 'globalExportAssets'
285+ > ;
286+
287+ const allProjects : FetchedData [ 'publicProjects' ] [ 'results' ] = [ ] ;
288+ let totalCount = Infinity ;
289+ // eslint-disable-next-line no-await-in-loop
290+ for ( let offset = 0 ; offset < totalCount ; offset += PROJECT_PAGE_SIZE ) {
291+ // eslint-disable-next-line no-await-in-loop
292+ const page = ( await requestWithRetry ( ( ) => graphQLClient . request ( projectsQuery , {
293+ limit : PROJECT_PAGE_SIZE ,
294+ offset,
295+ } ) ) ) as Pick < FetchedData , 'publicProjects' > ;
296+ allProjects . push ( ...page . publicProjects . results ) ;
297+ totalCount = page . publicProjects . totalCount ;
298+ console . log ( `Fetched ${ allProjects . length } /${ totalCount } projects` ) ;
299+ }
300+
301+ data = {
302+ ...staticData ,
303+ publicProjects : {
304+ results : allProjects ,
305+ totalCount,
306+ } ,
307+ } ;
249308 }
250309
251310 // ensure the `data` directory exists
0 commit comments