Skip to content

Commit c7bb43c

Browse files
Feature/general improvements 1 (#91)
* added number_of_simultaneously_running_loader_processes config parameter * refactoring * improved getNumberOfSimultaneouslyRunningLoaderProcesses function * create identity for auto-incremented columns instead of plain sequences * fixed DefaultProcessor.ts * updated dependencies * fixed TypeScript minor compilation errors * improved data loading performance * small refactoring * updated dependencies Co-authored-by: Anatoly Khaytovich <[email protected]>
1 parent 0463549 commit c7bb43c

21 files changed

+1822
-419
lines changed

config/config.json

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,29 @@
4343
],
4444
"max_each_db_connection_pool_size" : 20,
4545

46+
"number_of_simultaneously_running_loader_processes_description": [
47+
"Number of data-loader processes that will run simultaneously.",
48+
"Acceptable values:",
49+
"1. 'DEFAULT' - when set to 'DEFAULT', Nmig will run 2 data-loader processes.",
50+
"2. Any positive integer.",
51+
"Notice:",
52+
"1.",
53+
"Usually, migration gets accomplished faster with only 2 data-loader processes,",
54+
"even if more CPU cores are available.",
55+
"Yet, it is worth an effort to 'play' with this parameter prior running migration in production,",
56+
"to check how many processes work best in your case.",
57+
"When trying Nmig on your test-database, try both decreasing and increasing this number.",
58+
"2.",
59+
"'number_of_simultaneously_running_loader_processes' will never be greater",
60+
"than a number of logical CPU cores of the machine running Nmig.",
61+
"If greater number chosen - Nmig will run one loader process per each available CPU core."
62+
],
63+
"number_of_simultaneously_running_loader_processes": "DEFAULT",
64+
4665
"loader_max_old_space_size_description" : [
4766
"V8 memory limit of the loader process.",
4867
"Possible values are:",
49-
"1. any number, representing memory limit (in MB).",
68+
"1. any positive integer, representing memory limit (in MB).",
5069
"2. 'DEFAULT', representing V8 default memory limit for your current hardware."
5170
],
5271
"loader_max_old_space_size" : "DEFAULT",

package-lock.json

Lines changed: 1629 additions & 335 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "nmig",
3-
"version": "5.5.0",
3+
"version": "5.6.0",
44
"description": "The database migration app",
55
"author": "Anatoly Khaytovich<[email protected]>",
66
"license": "GPL-3.0",
@@ -12,21 +12,21 @@
1212
"node": ">=10.0.0"
1313
},
1414
"dependencies": {
15-
"json2csv": "^5.0.3",
15+
"@types/mysql": "^2.15.21",
16+
"@types/node": "^17.0.16",
17+
"@types/pg": "^8.6.4",
18+
"json2csv": "^5.0.6",
1619
"mysql": "^2.18.1",
17-
"pg": "^8.4.2",
18-
"pg-copy-streams": "^5.1.1",
19-
"@types/mysql": "^2.15.15",
20-
"@types/node": "^14.14.5",
21-
"@types/pg": "^7.14.5"
20+
"pg": "^8.7.3",
21+
"pg-copy-streams": "^6.0.2"
2222
},
2323
"devDependencies": {
24-
"@types/tape": "^4.13.0",
25-
"tape": "^5.0.1",
26-
"typescript": "^4.0.5"
24+
"@types/tape": "^4.13.2",
25+
"tape": "^5.5.0",
26+
"typescript": "4.5.5"
2727
},
2828
"scripts": {
29-
"build": "tsc",
29+
"build": "tsc --incremental -p tsconfig.json",
3030
"start": "node dist/src/Main.js",
3131
"test": "node dist/test/Main.test.js"
3232
},

src/BinaryDataDecoder.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,14 @@
1818
*
1919
* @author Anatoly Khaytovich <[email protected]>
2020
*/
21+
import { PoolClient } from 'pg';
22+
2123
import { log } from './FsOps';
2224
import Conversion from './Conversion';
2325
import DBAccess from './DBAccess';
2426
import DBAccessQueryResult from './DBAccessQueryResult';
2527
import DBVendors from './DBVendors';
2628
import IDBAccessQueryParams from './IDBAccessQueryParams';
27-
import { PoolClient } from 'pg';
2829

2930
/**
3031
* Decodes binary data from from textual representation in string.

src/BootProcessor.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
* @author Anatoly Khaytovich <[email protected]>
2020
*/
2121
import * as path from 'path';
22+
2223
import Conversion from './Conversion';
2324
import DBAccess from './DBAccess';
2425
import DBAccessQueryResult from './DBAccessQueryResult';

src/ConstraintsProcessor.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
*
1919
* @author Anatoly Khaytovich <[email protected]>
2020
*/
21-
import * as identityProcessor from './IdentityProcessor';
21+
import * as sequencesProcessor from './SequencesProcessor';
2222
import * as migrationStateManager from './MigrationStateManager';
2323
import processEnum from './EnumProcessor';
2424
import processNull from './NullProcessor';
@@ -66,13 +66,13 @@ export const processConstraintsPerTable = async (
6666
migrateOnlyData: boolean
6767
): Promise<void> => {
6868
if (migrateOnlyData) {
69-
return identityProcessor.setSequenceValue(conversion, tableName);
69+
return sequencesProcessor.setSequenceValue(conversion, tableName);
7070
}
7171

7272
await processEnum(conversion, tableName);
7373
await processNull(conversion, tableName);
7474
await processDefault(conversion, tableName);
75-
await identityProcessor.createIdentity(conversion, tableName);
75+
await sequencesProcessor.createIdentity(conversion, tableName);
7676
await processIndexAndKey(conversion, tableName);
7777
await processComments(conversion, tableName);
7878
};

src/Conversion.ts

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@
2020
*/
2121
import * as path from 'path';
2222
import { EventEmitter } from 'events';
23+
2324
import { Pool as MySQLPool } from 'mysql';
2425
import { Pool as PgPool } from 'pg';
26+
2527
import { Encoding } from './Encoding';
2628

2729
export default class Conversion {
@@ -43,7 +45,7 @@ export default class Conversion {
4345
/**
4446
* V8 memory limit of the loader process.
4547
*/
46-
public _loaderMaxOldSpaceSize: number | string;
48+
public readonly _loaderMaxOldSpaceSize: number | string;
4749

4850
/**
4951
* Maximal amount of simultaneous connections to your MySQL and PostgreSQL servers each.
@@ -113,7 +115,7 @@ export default class Conversion {
113115
/**
114116
* The timestamp, at which the migration began.
115117
*/
116-
public _timeBegin: Date;
118+
public readonly _timeBegin: Date;
117119

118120
/**
119121
* Current version of source (MySQL) db.
@@ -163,7 +165,7 @@ export default class Conversion {
163165
/**
164166
* An array of data chunks.
165167
*/
166-
public readonly _dataPool: any[];
168+
public readonly _dataPool: object[];
167169

168170
/**
169171
* A flag, that indicates if Nmig currently runs in test mode.
@@ -201,6 +203,11 @@ export default class Conversion {
201203
*/
202204
public readonly _streamsHighWaterMark: number;
203205

206+
/**
207+
* Number of data-loader processes that will run simultaneously.
208+
*/
209+
public readonly _numberOfSimultaneouslyRunningLoaderProcesses: string | number;
210+
204211
/**
205212
* Constructor.
206213
*/
@@ -226,24 +233,41 @@ export default class Conversion {
226233
this._dataPool = [];
227234
this._dicTables = Object.create(null);
228235
this._mySqlDbName = this._sourceConString.database;
229-
this._streamsHighWaterMark = this._config.streams_high_water_mark === undefined ? 16384 : +this._config.streams_high_water_mark;
236+
237+
this._streamsHighWaterMark = this._config.streams_high_water_mark === undefined
238+
? 16384
239+
: +this._config.streams_high_water_mark;
230240

231241
this._schema = this._config.schema === undefined || this._config.schema === ''
232242
? this._mySqlDbName
233243
: this._config.schema;
234244

235-
this._maxEachDbConnectionPoolSize = this._config.max_each_db_connection_pool_size !== undefined && Conversion._isIntNumeric(this._config.max_each_db_connection_pool_size)
245+
const isValidMaxEachDbConnectionPoolSize: boolean = this._config.max_each_db_connection_pool_size !== undefined
246+
&& Conversion._isIntNumeric(this._config.max_each_db_connection_pool_size);
247+
248+
this._maxEachDbConnectionPoolSize = isValidMaxEachDbConnectionPoolSize
236249
? +this._config.max_each_db_connection_pool_size
237250
: 20;
238251

252+
this._maxEachDbConnectionPoolSize = this._maxEachDbConnectionPoolSize > 0 ? this._maxEachDbConnectionPoolSize : 20;
239253
this._runsInTestMode = false;
240254
this._eventEmitter = null;
241255
this._migrationCompletedEvent = 'migrationCompleted';
242-
this._removeTestResources = this._config.remove_test_resources === undefined ? true : this._config.remove_test_resources;
243-
this._maxEachDbConnectionPoolSize = this._maxEachDbConnectionPoolSize > 0 ? this._maxEachDbConnectionPoolSize : 20;
244-
this._loaderMaxOldSpaceSize = this._config.loader_max_old_space_size;
245-
this._loaderMaxOldSpaceSize = Conversion._isIntNumeric(this._loaderMaxOldSpaceSize) ? this._loaderMaxOldSpaceSize : 'DEFAULT';
256+
257+
this._removeTestResources = this._config.remove_test_resources === undefined
258+
? true
259+
: this._config.remove_test_resources;
260+
261+
this._numberOfSimultaneouslyRunningLoaderProcesses = Conversion._isIntNumeric(this._config.number_of_simultaneously_running_loader_processes)
262+
? +this._config.number_of_simultaneously_running_loader_processes
263+
: 'DEFAULT';
264+
265+
this._loaderMaxOldSpaceSize = Conversion._isIntNumeric(this._config.loader_max_old_space_size)
266+
? +this._config.loader_max_old_space_size
267+
: 'DEFAULT';
268+
246269
this._migrateOnlyData = this._config.migrate_only_data === undefined ? false : this._config.migrate_only_data;
270+
247271
this._delimiter = this._config.delimiter !== undefined && this._config.delimiter.length === 1
248272
? this._config.delimiter
249273
: ',';

src/DBAccess.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import * as mysql from 'mysql';
2222
import { MysqlError, Pool as MySQLPool, PoolConnection } from 'mysql';
2323
import { Pool as PgPool, PoolClient } from 'pg';
24+
2425
import { log, generateError } from './FsOps';
2526
import Conversion from './Conversion';
2627
import DBVendors from './DBVendors';
@@ -72,8 +73,8 @@ export default class DBAccess {
7273
* Closes both connection-pools.
7374
*/
7475
public static async closeConnectionPools(conversion: Conversion): Promise<Conversion> {
75-
const closeMySqlConnections = () => {
76-
return new Promise(resolve => {
76+
const closeMySqlConnections = (): Promise<void> => {
77+
return new Promise<void>(resolve => {
7778
if (conversion._mysql) {
7879
conversion._mysql.end(async error => {
7980
if (error) {
@@ -88,7 +89,7 @@ export default class DBAccess {
8889
});
8990
};
9091

91-
const closePgConnections = async () => {
92+
const closePgConnections = async (): Promise<void> => {
9293
if (conversion._pg) {
9394
try {
9495
await conversion._pg.end();

src/DataLoader.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
*
1919
* @author Anatoly Khaytovich <[email protected]>
2020
*/
21+
import * as path from 'path';
22+
2123
import { log, generateError } from './FsOps';
2224
import Conversion from './Conversion';
2325
import DBAccess from './DBAccess';
@@ -29,16 +31,17 @@ import { dataTransferred } from './ConsistencyEnforcer';
2931
import IDBAccessQueryParams from './IDBAccessQueryParams';
3032
import * as extraConfigProcessor from './ExtraConfigProcessor';
3133
import { getDataPoolTableName } from './DataPoolManager';
32-
import * as path from 'path';
34+
3335
import { PoolClient, QueryResult } from 'pg';
3436
import { PoolConnection } from 'mysql';
37+
3538
const { from } = require('pg-copy-streams'); // No declaration file for module "pg-copy-streams".
3639
const { Transform: Json2CsvTransform } = require('json2csv'); // No declaration file for module "json2csv".
3740

3841
process.on('message', async (signal: MessageToDataLoader) => {
3942
const { config, chunk } = signal;
4043
const conv: Conversion = new Conversion(config);
41-
log(conv, `\t--[loadData] Loading the data into "${ conv._schema }"."${ chunk._tableName }" table...`);
44+
log(conv, `\t--[NMIG loadData] Loading the data into "${ conv._schema }"."${ chunk._tableName }" table...`);
4245

4346
const isRecoveryMode: boolean = await dataTransferred(conv, chunk._id);
4447

0 commit comments

Comments
 (0)