1+ /**
2+ * Store v5 challenge id for current records
3+ */
4+
5+ const _ = require ( 'lodash' )
6+ const co = require ( 'co' )
7+ const config = require ( 'config' )
8+ const logger = require ( '../src/common/logger' )
9+ const dbhelper = require ( '../src/common/dbhelper' )
10+ const helper = require ( '../src/common/helper' )
11+
12+ const esClient = helper . getEsClient ( )
13+
14+ /**
15+ * Update Submission's challenge id to v5
16+ * @param {Object } submission The submission record
17+ * @param {Array } failedContainer The failed records container
18+ * @returns {Promise }
19+ */
20+ function * updateRecord ( submission , failedContainer ) {
21+ let v5challengeId
22+ try {
23+ v5challengeId = yield helper . getV5ChallengeId ( submission . challengeId )
24+ } catch ( err ) {
25+ logger . error ( `fetching the details of the challenge(${ submission . challengeId } ) failed, ${ err . message } ` )
26+ failedContainer . push ( submission )
27+ return
28+ }
29+ const record = {
30+ TableName : 'Submission' ,
31+ Key : {
32+ id : submission . id
33+ } ,
34+ UpdateExpression : `set challengeId = :c, legacyChallengeId = :l` ,
35+ ExpressionAttributeValues : {
36+ ':c' : v5challengeId ,
37+ ':l' : submission . challengeId
38+ }
39+ }
40+ if ( ! v5challengeId ) {
41+ logger . warn ( `the challengeId: ${ submission . challengeId } is not having a v5 challengeId` )
42+ failedContainer . push ( submission )
43+ return
44+ } else if ( v5challengeId === submission . challengeId ) {
45+ logger . info ( `the challengeId: ${ submission . challengeId } is already a v5 challengeId` )
46+ }
47+
48+ yield dbhelper . updateRecord ( record )
49+ try {
50+ const response = yield esClient . update ( {
51+ index : config . get ( 'esConfig.ES_INDEX' ) ,
52+ type : config . get ( 'esConfig.ES_TYPE' ) ,
53+ id : submission . id ,
54+ body : { doc : { challengeId : v5challengeId , legacyChallengeId : submission . challengeId } }
55+ } )
56+ logger . info ( `updated ES for submission ${ submission . id } , response: ${ JSON . stringify ( response ) } ` )
57+ } catch ( error ) {
58+ logger . error ( error . message )
59+ }
60+ }
61+
62+ /*
63+ * Update all submission's challenge id to v5
64+ * @returns {Promise }
65+ */
66+ function * updateRecords ( ) {
67+ const tableName = config . SUBMISSION_TABLE_NAME
68+ const promises = [ ]
69+ const failedRecords = [ ]
70+ const legacyChallengeIds = config . MIGRATE_CHALLENGES
71+ const queryParams = _ . fromPairs ( _ . map ( legacyChallengeIds , ( c , i ) => [ `:challengeId${ i } ` , c ] ) )
72+ const params = {
73+ TableName : tableName ,
74+ FilterExpression : `#challengeId IN (${ _ . join ( _ . keys ( legacyChallengeIds ) , ',' ) } )` ,
75+ ExpressionAttributeNames : {
76+ '#challengeId' : 'challengeId'
77+ } ,
78+ ExpressionAttributeValues : queryParams
79+ }
80+ // Process until all the records from DB is fetched
81+ while ( true ) {
82+ const records = yield dbhelper . scanRecords ( params )
83+ const totalRecords = records . Items . length
84+ logger . debug ( `Number of ${ tableName } s fetched from DB - ${ totalRecords } . More fetch iterations may follow (pagination in progress)` )
85+ for ( let i = 0 ; i < totalRecords ; i ++ ) {
86+ const record = records . Items [ i ]
87+ promises . push ( updateRecord ( record , failedRecords ) )
88+ }
89+ // Continue fetching the remaining records from Database
90+ if ( typeof records . LastEvaluatedKey !== 'undefined' ) {
91+ params . ExclusiveStartKey = records . LastEvaluatedKey
92+ } else {
93+ break // If there are no more records to process, exit the loop
94+ }
95+ }
96+ logger . debug ( `All records fetched. Proceeding to update them in batches of ${ config . UPDATE_V5_CHALLENGE_BATCH_SIZE } ` )
97+ const paraRecords = _ . chunk ( promises , config . UPDATE_V5_CHALLENGE_BATCH_SIZE )
98+ for ( const rs of paraRecords ) {
99+ yield rs
100+ }
101+ logger . info ( `Processed ${ promises . length - failedRecords . length } records successfully` )
102+ if ( failedRecords . length > 0 ) {
103+ logger . warn ( `Processing of ${ failedRecords . length } records failed` )
104+ logger . info ( `Failed records: ${ _ . join ( _ . map ( failedRecords , f => JSON . stringify ( _ . pick ( f , [ 'id' , 'challengeId' ] ) ) , ',' ) ) } ` )
105+ }
106+ }
107+
108+ co ( function * ( ) {
109+ yield updateRecords ( )
110+ } ) . catch ( ( err ) => {
111+ logger . logFullError ( err )
112+ } )
0 commit comments