2020 */
2121'use strict' ;
2222
23+ const generateError = require ( './ErrorGenerator' ) ;
24+ const extraConfigProcessor = require ( './ExtraConfigProcessor' ) ;
25+
2326/**
2427 * Update consistency state.
2528 *
@@ -53,14 +56,15 @@ const updateConsistencyState = (self, dataPoolId) => {
5356}
5457
5558/**
56- * Get consistency state .
59+ * Get the `is_started` value of current chunk .
5760 *
5861 * @param {Conversion } self
5962 * @param {Number } dataPoolId
6063 *
6164 * @returns {Promise }
6265 */
63- const getConsistencyState = ( self , dataPoolId ) => {
66+
67+ const getIsStarted = ( self , dataPoolId ) => {
6468 return new Promise ( resolve => {
6569 self . _pg . connect ( ( error , client , done ) => {
6670 if ( error ) {
@@ -85,27 +89,123 @@ const getConsistencyState = (self, dataPoolId) => {
8589 } ) ;
8690}
8791
92+ /**
93+ * Current data chunk runs after a disaster recovery.
94+ * Must determine if current chunk has already been loaded.
95+ * This is in order to prevent possible data duplications.
96+ *
97+ * @param {Conversion } self
98+ * @param {Object } chunk
99+ *
100+ * @returns {Promise }
101+ */
102+ const hasCurrentChunkLoaded = ( self , chunk ) => {
103+ return new Promise ( resolve => {
104+ self . _pg . connect ( ( pgError , client , done ) => {
105+ if ( pgError ) {
106+ generateError ( self , '\t--[ConsistencyEnforcer::hasCurrentChunkLoaded] Cannot connect to PostgreSQL server...\n' + pgError ) ;
107+ resolve ( true ) ;
108+ } else {
109+ const originalTableName = extraConfigProcessor . getTableName ( self , chunk . _tableName , true ) ;
110+ const sql = 'SELECT EXISTS(SELECT 1 FROM "' + self . _schema + '"."' + chunk . _tableName
111+ + '" WHERE "' + self . _schema + '_' + originalTableName + '_data_chunk_id_temp" = ' + chunk . _id + ');' ;
112+
113+ client . query ( sql , ( err , result ) => {
114+ done ( ) ;
115+
116+ if ( err ) {
117+ generateError ( self , '\t--[ConsistencyEnforcer::hasCurrentChunkLoaded] ' + err , sql ) ;
118+ resolve ( true ) ;
119+ } else {
120+ resolve ( ! ! result . rows [ 0 ] . exists ) ;
121+ }
122+ } ) ;
123+ }
124+ } ) ;
125+ } ) ;
126+ }
127+
128+ /**
129+ * Get consistency state.
130+ *
131+ * @param {Conversion } self
132+ * @param {Object } chunk
133+ *
134+ * @returns {Promise }
135+ */
136+ const getConsistencyState = ( self , chunk ) => {
137+ return new Promise ( resolve => {
138+ getIsStarted ( self , chunk . _id ) . then ( isStarted => {
139+ if ( isStarted ) {
140+ hasCurrentChunkLoaded ( self , chunk ) . then ( result => resolve ( result ) ) ;
141+ } else {
142+ // Normal migration flow.
143+ resolve ( false ) ;
144+ }
145+ } ) ;
146+ } ) ;
147+ }
148+
88149/**
89150 * Enforce consistency before processing a chunk of data.
90151 * Ensure there are no any data duplications.
91152 * In case of normal execution - it is a good practice.
92153 * In case of rerunning nmig after unexpected failure - it is absolutely mandatory.
93154 *
94155 * @param {Conversion } self
95- * @param {Number } chunkId
156+ * @param {Object } chunk
96157 *
97158 * @returns {Promise }
98159 */
99- module . exports = ( self , chunkId ) => {
160+ module . exports . enforceConsistency = ( self , chunk ) => {
100161 return new Promise ( resolve => {
101- getConsistencyState ( self , chunkId ) . then ( isStarted => {
102- if ( isStarted ) {
103- // Current data chunk runs after a disaster recovery.
162+ getConsistencyState ( self , chunk ) . then ( hasAlreadyBeenLoaded => {
163+ if ( hasAlreadyBeenLoaded ) {
164+ /*
165+ * Current data chunk runs after a disaster recovery.
166+ * It has already been loaded.
167+ */
104168 resolve ( false ) ;
105169 } else {
106170 // Normal migration flow.
107- updateConsistencyState ( self , chunkId ) . then ( ( ) => resolve ( true ) ) ;
171+ updateConsistencyState ( self , chunk . _id ) . then ( ( ) => resolve ( true ) ) ;
108172 }
109173 } )
110174 } ) ;
111175} ;
176+
177+ /**
178+ * Drop the {self._schema + '_' + originalTableName + '_data_chunk_id_temp'} column from current table.
179+ *
180+ * @param {Conversion } self
181+ * @param {String } tableName
182+ *
183+ * @returns {Promise }
184+ */
185+ module . exports . dropDataChunkIdColumn = ( self , tableName ) => {
186+ return new Promise ( resolve => {
187+ self . _pg . connect ( ( pgError , client , done ) => {
188+ if ( pgError ) {
189+ generateError ( self , '\t--[ConsistencyEnforcer::dropDataChunkIdColumn] Cannot connect to PostgreSQL server...\n' + pgError ) ;
190+ resolve ( ) ;
191+ } else {
192+ const originalTableName = extraConfigProcessor . getTableName ( self , tableName , true ) ;
193+ const columnToDrop = self . _schema + '_' + originalTableName + '_data_chunk_id_temp' ;
194+ const sql = 'ALTER TABLE "' + self . _schema + '"."' + tableName + '" DROP COLUMN "' + columnToDrop + '";' ;
195+
196+ client . query ( sql , ( err , result ) => {
197+ done ( ) ;
198+
199+ if ( err ) {
200+ const errMsg = '\t--[ConsistencyEnforcer::dropDataChunkIdColumn] Failed to drop column "' + columnToDrop + '"\n'
201+ + '\t--[ConsistencyEnforcer::dropDataChunkIdColumn] ' + err ;
202+
203+ generateError ( self , errMsg , sql ) ;
204+ }
205+
206+ resolve ( ) ;
207+ } ) ;
208+ }
209+ } ) ;
210+ } ) ;
211+ } ;
0 commit comments