Skip to content

Commit 5151f87

Browse files
gvuyknodkz
authored andcommitted
fix: wait for mongod process to exit before removing its files (#27)
* wait for mongodb process to exit before removing its files * feat(MongoInstance): add kill(), getPid() methods. Small refactoring. * test(MongoInstance): check async kill() * expect mongod to be running before killing it
1 parent 4e40bd9 commit 5151f87

File tree

3 files changed

+54
-13
lines changed

3 files changed

+54
-13
lines changed

src/MongoMemoryServer.js

+8-3
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export type MongoInstanceDataT = {
3636
dbName: string,
3737
uri: string,
3838
storageEngine: string,
39+
instance: MongoInstance,
3940
childProcess: ChildProcess,
4041
tmpDir?: {
4142
name: string,
@@ -125,7 +126,7 @@ export default class MongoMemoryServer {
125126

126127
// Download if not exists mongo binaries in ~/.mongodb-prebuilt
127128
// After that startup MongoDB instance
128-
const childProcess = await MongoInstance.run({
129+
const instance = await MongoInstance.run({
129130
instance: {
130131
port: data.port,
131132
storageEngine: data.storageEngine,
@@ -136,7 +137,8 @@ export default class MongoMemoryServer {
136137
spawn: this.opts.spawn,
137138
debug: this.debug,
138139
});
139-
data.childProcess = childProcess;
140+
data.instance = instance;
141+
data.childProcess = instance.childProcess;
140142
data.tmpDir = tmpDir;
141143

142144
return data;
@@ -147,7 +149,10 @@ export default class MongoMemoryServer {
147149

148150
if (childProcess && childProcess.kill) {
149151
this.debug(`Shutdown MongoDB server on port ${port} with pid ${childProcess.pid}`);
150-
childProcess.kill();
152+
await new Promise(resolve => {
153+
childProcess.once(`exit`, resolve);
154+
childProcess.kill();
155+
});
151156
}
152157

153158
if (tmpDir) {

src/util/MongoInstance.js

+21-7
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export default class MongodbInstance {
4343
instanceReady: Function;
4444
instanceFailed: Function;
4545

46-
static run(opts: MongodOps): Promise<ChildProcess> {
46+
static run(opts: MongodOps): Promise<MongodbInstance> {
4747
const instance = new this(opts);
4848
return instance.run();
4949
}
@@ -85,7 +85,7 @@ export default class MongodbInstance {
8585
return result;
8686
}
8787

88-
async run(): Promise<ChildProcess> {
88+
async run(): Promise<MongodbInstance> {
8989
const launch = new Promise((resolve, reject) => {
9090
this.instanceReady = () => {
9191
this.debug('MongodbInstance: is ready!');
@@ -99,14 +99,28 @@ export default class MongodbInstance {
9999
});
100100

101101
const mongoBin = await MongoBinary.getPath(this.opts.binary);
102-
this.childProcess = this.launchMongod(mongoBin);
103-
this.killerProcess = this.launchKiller(process.pid, this.childProcess.pid);
102+
this.childProcess = this._launchMongod(mongoBin);
103+
this.killerProcess = this._launchKiller(process.pid, this.childProcess.pid);
104104

105105
await launch;
106-
return this.childProcess;
106+
return this;
107107
}
108108

109-
launchMongod(mongoBin: string): ChildProcess {
109+
async kill(): Promise<MongodbInstance> {
110+
if (this.childProcess && !this.childProcess.killed) {
111+
await new Promise(resolve => {
112+
this.childProcess.once(`exit`, resolve);
113+
this.childProcess.kill();
114+
});
115+
}
116+
return this;
117+
}
118+
119+
getPid(): ?number {
120+
return this.childProcess ? this.childProcess.pid : undefined;
121+
}
122+
123+
_launchMongod(mongoBin: string): ChildProcess {
110124
const spawnOpts = this.opts.spawn || {};
111125
if (!spawnOpts.stdio) spawnOpts.stdio = 'pipe';
112126
const childProcess = spawnChild(mongoBin, this.prepareCommandArgs(), spawnOpts);
@@ -118,7 +132,7 @@ export default class MongodbInstance {
118132
return childProcess;
119133
}
120134

121-
launchKiller(parentPid: number, childPid: number): ChildProcess {
135+
_launchKiller(parentPid: number, childPid: number): ChildProcess {
122136
// spawn process which kills itself and mongo process if current process is dead
123137
const killer = spawnChild(
124138
process.argv[0],

src/util/__tests__/MongoInstance-test.js

+25-3
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ describe('MongoInstance', () => {
4141
binary: { version: '3.4.4' },
4242
});
4343

44-
expect(mongod.pid).toBeGreaterThan(0);
45-
mongod.kill();
44+
expect(mongod.getPid()).toBeGreaterThan(0);
45+
46+
await mongod.kill();
4647
});
4748

4849
it('should throw error if port is busy', async () => {
@@ -58,6 +59,27 @@ describe('MongoInstance', () => {
5859
})
5960
).rejects.toBeDefined();
6061

61-
mongod.kill();
62+
await mongod.kill();
63+
});
64+
65+
it('should await while mongo is killed', async () => {
66+
const mongod = await MongoInstance.run({
67+
instance: { port: 27445, dbPath: tmpDir.name },
68+
binary: { version: '3.4.4' },
69+
});
70+
const pid: any = mongod.getPid();
71+
expect(pid).toBeGreaterThan(0);
72+
73+
function isPidRunning(p: number) {
74+
try {
75+
return process.kill(p, 0);
76+
} catch (e) {
77+
return e.code === 'EPERM';
78+
}
79+
}
80+
81+
expect(isPidRunning(pid)).toBeTruthy();
82+
await mongod.kill();
83+
expect(isPidRunning(pid)).toBeFalsy();
6284
});
6385
});

0 commit comments

Comments
 (0)