From 76889a6eb678a3b3994315bfc0cbee916a622564 Mon Sep 17 00:00:00 2001 From: hasezoey Date: Tue, 8 Sep 2020 12:20:31 +0200 Subject: [PATCH] fix(MongoInstance): de-duplicate killer code & actually log output from "mongo_killer" - de-duplicate "MongoInstance.kill" code - add check that "childProcess.pid" is not undefined before returning "MongoInstance._launchMongod" - actually log output from "mongo_killer" in "MongoInstance._launchKiller" - add custom message if "libcurl4" is missing --- .../src/util/MongoInstance.ts | 67 ++++++++++++------- .../src/util/db_util.ts | 8 +++ 2 files changed, 50 insertions(+), 25 deletions(-) diff --git a/packages/mongodb-memory-server-core/src/util/MongoInstance.ts b/packages/mongodb-memory-server-core/src/util/MongoInstance.ts index 58230737f..fad079a23 100644 --- a/packages/mongodb-memory-server-core/src/util/MongoInstance.ts +++ b/packages/mongodb-memory-server-core/src/util/MongoInstance.ts @@ -11,6 +11,7 @@ import { EmptyVoidCallback, } from '../types'; import debug from 'debug'; +import { isNullOrUndefined } from './db_util'; const log = debug('MongoMS:MongoInstance'); @@ -123,31 +124,31 @@ export default class MongoInstance { async kill(): Promise { this.debug('Called MongoInstance.kill():'); - if (this.childProcess && !this.childProcess.killed) { + + /** + * Function to De-Duplicate Code + * @param process The Process to kill + * @param name the name used in the logs + * @param debug the debug function + */ + async function kill_internal(process: ChildProcess, name: string, debug: DebugFn) { await new Promise((resolve) => { - if (this.childProcess) { - this.childProcess.once(`exit`, () => { - this.debug(' - childProcess: got exit signal. Ok!'); - resolve(); - }); - this.childProcess.kill(); - this.debug(' - childProcess: send kill cmd...'); - } + process.once(`exit`, () => { + debug(` - ${name}: got exit signal. Ok!`); + resolve(); + }); + debug(` - ${name}: send kill cmd...`); + process.kill('SIGINT'); }); + } + + if (this.childProcess && !this.childProcess.killed) { + await kill_internal(this.childProcess, 'childProcess', this.debug); } else { this.debug(' - childProcess: nothing to kill, skipping.'); } if (this.killerProcess && !this.killerProcess.killed) { - await new Promise((resolve) => { - if (this.killerProcess) { - this.killerProcess.once(`exit`, () => { - this.debug(' - killerProcess: got exit signal. Ok!'); - resolve(); - }); - this.killerProcess.kill(); - this.debug(' - killerProcess: send kill cmd...'); - } - }); + await kill_internal(this.killerProcess, 'killerProcess', this.debug); } else { this.debug(' - killerProcess: nothing to kill, skipping.'); } @@ -182,15 +183,15 @@ export default class MongoInstance { if (!spawnOpts.stdio) spawnOpts.stdio = 'pipe'; const childProcess = spawnChild(mongoBin, this.prepareCommandArgs(), spawnOpts); - if (childProcess.stderr) { - childProcess.stderr.on('data', this.stderrHandler.bind(this)); - } - if (childProcess.stdout) { - childProcess.stdout.on('data', this.stdoutHandler.bind(this)); - } + childProcess.stderr?.on('data', this.stderrHandler.bind(this)); + childProcess.stdout?.on('data', this.stdoutHandler.bind(this)); childProcess.on('close', this.closeHandler.bind(this)); childProcess.on('error', this.errorHandler.bind(this)); + if (isNullOrUndefined(childProcess.pid)) { + throw new Error('Spawned Mongo Instance PID is undefined'); + } + return childProcess; } @@ -212,6 +213,14 @@ export default class MongoInstance { { stdio: 'pipe' } ); + killer.stdout?.on('data', (data) => { + this.debug(`[MongoKiller]: ${data}`); + }); + + killer.stderr?.on('data', (data) => { + this.debug(`[MongoKiller]: ${data}`); + }); + ['exit', 'message', 'disconnect', 'error'].forEach((type) => { killer.on(type, (...args) => { this.debug(`[MongoKiller]: ${type} - ${JSON.stringify(args)}`); @@ -230,6 +239,9 @@ export default class MongoInstance { * @param code The Exit code */ closeHandler(code: number): void { + if (code != 0) { + this.debug('Mongod instance closed with an non-0 code!'); + } this.debug(`CLOSE: ${code}`); } @@ -264,6 +276,11 @@ export default class MongoInstance { 'libcurl3 is not available on your system. Mongod requires it and cannot be started without it.\n' + 'You should manually install libcurl3 or try to use an newer version of MongoDB\n' ); + } else if (/CURL_OPENSSL_4.*not found/i.test(line)) { + this.instanceFailed( + 'libcurl4 is not available on your system. Mongod requires it and cannot be started without it.\n' + + 'You need to manually install libcurl4\n' + ); } else if (/shutting down with code/i.test(line)) { // if mongod started succesfully then no error on shutdown! if (!this.isInstanceReady) { diff --git a/packages/mongodb-memory-server-core/src/util/db_util.ts b/packages/mongodb-memory-server-core/src/util/db_util.ts index 4289304e4..30bc3d92b 100644 --- a/packages/mongodb-memory-server-core/src/util/db_util.ts +++ b/packages/mongodb-memory-server-core/src/util/db_util.ts @@ -23,4 +23,12 @@ export function getUriBase(host: string, port: number, dbName: string): string { return `mongodb://${host}:${port}/${dbName}?`; } +/** + * Because since node 4.0.0 the internal util.is* functions got deprecated + * @param val Any value to test if null or undefined + */ +export function isNullOrUndefined(val: unknown): val is null | undefined { + return val === null || val === undefined; +} + export default generateDbName;