Skip to content

Commit 4af436a

Browse files
authored
Merge pull request #375 from hasezoey/fix/improveMongoBinary
2 parents a6da2ed + 8257926 commit 4af436a

File tree

7 files changed

+403
-385
lines changed

7 files changed

+403
-385
lines changed

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
flow-typed/*
22
lib/*
3+
.eslintrc.js

.vscode/settings.json

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
{
22
"javascript.validate.enable": false,
3-
"eslint.validate": [
4-
{ "language": "javascript", "autoFix": true },
5-
{ "language": "javascriptreact", "autoFix": true },
6-
{ "language": "typescript", "autoFix": true },
7-
{ "language": "typescriptreact", "autoFix": true }
8-
],
93
"typescript.tsdk": "node_modules/typescript/lib",
4+
"editor.formatOnSave": false,
5+
"javascript.format.enable": false,
6+
"typescript.format.enable": false,
107
"editor.codeActionsOnSave": {
118
"source.fixAll.eslint": true
129
},
13-
"eslint.autoFixOnSave": true,
1410
}

package.json

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,32 @@
55
"description": "In-memory MongoDB Server. Designed with testing in mind, the server will allow you to connect your favourite ODM or client library to the MongoDB Server and run integration tests isolated from each other.",
66
"repository": "https://github.com/nodkz/mongodb-memory-server",
77
"devDependencies": {
8-
"@commitlint/cli": "^9.1.2",
9-
"@commitlint/config-conventional": "^9.1.2",
8+
"@commitlint/cli": "11.0.0",
9+
"@commitlint/config-conventional": "11.0.0",
1010
"@google/semantic-release-replace-plugin": "^1.0.0",
1111
"@semantic-release/changelog": "^5.0.1",
1212
"@semantic-release/commit-analyzer": "^8.0.1",
1313
"@semantic-release/git": "^9.0.0",
1414
"@semantic-release/github": "^7.1.1",
1515
"@semantic-release/npm": "^7.0.6",
1616
"@semantic-release/release-notes-generator": "^9.0.1",
17-
"@types/jest": "26.0.13",
17+
"@types/jest": "26.0.14",
1818
"@types/mongodb": "3.5.27",
19-
"@types/node": "14.10.0",
20-
"@typescript-eslint/eslint-plugin": "4.1.0",
21-
"@typescript-eslint/parser": "4.1.0",
22-
"commitlint": "^9.1.2",
19+
"@types/node": "14.10.2",
20+
"@typescript-eslint/eslint-plugin": "4.1.1",
21+
"@typescript-eslint/parser": "4.1.1",
22+
"commitlint": "11.0.0",
2323
"cross-env": "^7.0.2",
2424
"doctoc": "^1.4.0",
25-
"eslint": "7.8.1",
25+
"eslint": "7.9.0",
2626
"eslint-config-prettier": "6.11.0",
2727
"eslint-plugin-prettier": "3.1.4",
2828
"husky": "^4.3.0",
2929
"jest": "26.4.2",
3030
"lerna": "^3.22.1",
31-
"lint-staged": "^10.3.0",
32-
"prettier": "2.1.1",
31+
"lint-staged": "10.4.0",
32+
"mongodb": "3.6.2",
33+
"prettier": "2.1.2",
3334
"semantic-release": "^17.1.1",
3435
"ts-jest": "26.3.0",
3536
"typescript": "4.0.2"
@@ -58,6 +59,7 @@
5859
"scripts": {
5960
"test": "lerna run test --stream",
6061
"lint": "lerna run lint --stream --npm-client=yarn --no-prefix",
62+
"eslint": "eslint 'packages/mongodb-memory-server-core/src/**/*.{js,ts}'",
6163
"watch": "jest --env node --watch",
6264
"jest": "jest --env node",
6365
"build": "tsc --build tsconfig.build.json",

packages/mongodb-memory-server-core/package.json

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,27 +36,14 @@
3636
"@types/dedent": "^0.7.0",
3737
"@types/find-cache-dir": "^3.2.0",
3838
"@types/find-package-json": "^1.1.1",
39-
"@types/jest": "26.0.13",
4039
"@types/lockfile": "^1.0.1",
4140
"@types/md5-file": "^4.0.2",
4241
"@types/mkdirp": "^1.0.1",
4342
"@types/mongodb": "3.5.27",
44-
"@types/semver": "^7.3.3",
43+
"@types/semver": "7.3.4",
4544
"@types/tar-stream": "^2.1.0",
4645
"@types/uuid": "^8.0.0",
47-
"@types/yauzl": "^2.9.1",
48-
"@typescript-eslint/eslint-plugin": "4.1.0",
49-
"@typescript-eslint/parser": "4.1.0",
50-
"cross-env": "^7.0.2",
51-
"eslint": "7.8.1",
52-
"eslint-config-prettier": "6.11.0",
53-
"flowgen": "^1.10.0",
54-
"jest": "26.4.2",
55-
"lerna": "3.22.1",
56-
"mongodb": "3.6.2",
57-
"rimraf": "^3.0.2",
58-
"ts-jest": "26.3.0",
59-
"typescript": "4.0.2"
46+
"@types/yauzl": "^2.9.1"
6047
},
6148
"dependencies": {
6249
"@types/tmp": "^0.2.0",

packages/mongodb-memory-server-core/src/util/MongoBinary.ts

Lines changed: 59 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -32,54 +32,67 @@ export interface MongoBinaryOpts {
3232
export default class MongoBinary {
3333
static cache: MongoBinaryCache = {};
3434

35+
/**
36+
* Probe if the provided "systemBinary" is an existing path
37+
* @param systemBinary The Path to probe for an System-Binary
38+
* @return System Binary path or empty string
39+
*/
3540
static async getSystemPath(systemBinary: string): Promise<string> {
3641
let binaryPath = '';
3742

3843
try {
3944
await promisify(fs.access)(systemBinary);
4045

41-
log(`MongoBinary: found sytem binary path at ${systemBinary}`);
46+
log(`MongoBinary: found system binary path at "${systemBinary}"`);
4247
binaryPath = systemBinary;
4348
} catch (err) {
44-
log(`MongoBinary: can't find system binary at ${systemBinary}. ${err.message}`);
49+
log(`MongoBinary: can't find system binary at "${systemBinary}".\n${err.message}`);
4550
}
4651

4752
return binaryPath;
4853
}
4954

50-
static async getCachePath(version: string): Promise<string> {
55+
/**
56+
* Check if specified version already exists in the cache
57+
* @param version The Version to check for
58+
*/
59+
static getCachePath(version: string): string {
5160
return this.cache[version];
5261
}
5362

63+
/**
64+
* Probe download path and download the binary
65+
* @param options Options Configuring which binary to download and to which path
66+
* @returns The BinaryPath the binary has been downloaded to
67+
*/
5468
static async getDownloadPath(options: Required<MongoBinaryOpts>): Promise<string> {
5569
const { downloadDir, platform, arch, version, checkMD5 } = options;
56-
// create downloadDir if not exists
70+
// create downloadDir
5771
await mkdirp(downloadDir);
5872

73+
/** Lockfile path */
5974
const lockfile = path.resolve(downloadDir, `${version}.lock`);
60-
// wait lock
75+
// wait to get a lock
76+
// downloading of binaries may be quite long procedure
77+
// that's why we are using so big wait/stale periods
6178
await new Promise((resolve, reject) => {
6279
LockFile.lock(
6380
lockfile,
6481
{
65-
wait: 120000,
82+
wait: 1000 * 120, // 120 seconds
6683
pollPeriod: 100,
67-
stale: 110000,
84+
stale: 1000 * 110, // 110 seconds
6885
retries: 3,
6986
retryWait: 100,
7087
},
7188
(err: any) => {
72-
if (err) {
73-
reject(err);
74-
} else {
75-
resolve();
76-
}
89+
return err ? reject(err) : resolve();
7790
}
7891
);
7992
});
8093

81-
// again check cache, maybe other instance resolve it
82-
if (!this.cache[version]) {
94+
// check cache if it got already added to the cache
95+
if (!this.getCachePath(version)) {
8396
const downloader = new MongoBinaryDownload({
8497
downloadDir,
8598
platform,
@@ -90,16 +103,25 @@ export default class MongoBinary {
90103
this.cache[version] = await downloader.getMongodPath();
91104
}
92105
// remove lock
93-
LockFile.unlock(lockfile, (err: any) => {
94-
log(
95-
err
96-
? `MongoBinary: Error when removing download lock ${err}`
97-
: `MongoBinary: Download lock removed`
98-
);
106+
await new Promise((res) => {
107+
LockFile.unlock(lockfile, (err) => {
108+
log(
109+
err
110+
? `MongoBinary: Error when removing download lock ${err}`
111+
: `MongoBinary: Download lock removed`
112+
);
113+
res(); // we don't care if it was successful or not
114+
});
99115
});
100-
return this.cache[version];
116+
return this.getCachePath(version);
101117
}
102118

119+
/**
120+
* Probe all supported paths for an binary and return the binary path
121+
* @param opts Options configuring which binary to search for
122+
* @throws {Error} if no valid BinaryPath has been found
123+
* @return The first found BinaryPath
124+
*/
103125
static async getPath(opts: MongoBinaryOpts = {}): Promise<string> {
104126
const legacyDLDir = path.resolve(os.homedir(), '.cache/mongodb-binaries');
105127

@@ -109,6 +131,7 @@ export default class MongoBinary {
109131
nodeModulesDLDir = path.resolve(nodeModulesDLDir, '..', '..');
110132
}
111133

134+
// "||" is still used here, because it should default if the value is false-y (like an empty string)
112135
const defaultOptions = {
113136
downloadDir:
114137
resolveConfig('DOWNLOAD_DIR') ||
@@ -128,17 +151,16 @@ export default class MongoBinary {
128151
checkMD5: envToBool(resolveConfig('MD5_CHECK') ?? ''),
129152
};
130153

154+
/** Provided Options combined with the Default Options */
131155
const options = { ...defaultOptions, ...opts };
132-
log(`MongoBinary options: ${JSON.stringify(options)}`);
133-
134-
const { version, systemBinary } = options;
156+
log(`MongoBinary options:`, JSON.stringify(options, null, 2));
135157

136158
let binaryPath = '';
137159

138-
if (systemBinary) {
139-
binaryPath = await this.getSystemPath(systemBinary);
160+
if (options.systemBinary) {
161+
binaryPath = await this.getSystemPath(options.systemBinary);
140162
if (binaryPath) {
141-
if (~binaryPath.indexOf(' ')) {
163+
if (binaryPath.indexOf(' ') >= 0) {
142164
binaryPath = `"${binaryPath}"`;
143165
}
144166

@@ -147,36 +169,33 @@ export default class MongoBinary {
147169
.split('\n')[0]
148170
.split(' ')[2];
149171

150-
if (version !== LATEST_VERSION && version !== binaryVersion) {
172+
if (options.version !== LATEST_VERSION && options.version !== binaryVersion) {
151173
// we will log the version number of the system binary and the version requested so the user can see the difference
152174
log(
153175
'MongoMemoryServer: Possible version conflict\n' +
154176
` SystemBinary version: ${binaryVersion}\n` +
155-
` Requested version: ${version}\n\n` +
177+
` Requested version: ${options.version}\n\n` +
156178
' Using SystemBinary!'
157179
);
158180
}
159181
}
160182
}
161183

162184
if (!binaryPath) {
163-
binaryPath = await this.getCachePath(version);
185+
binaryPath = this.getCachePath(options.version);
164186
}
165187

166188
if (!binaryPath) {
167189
binaryPath = await this.getDownloadPath(options);
168190
}
169191

170-
log(`MongoBinary: Mongod binary path: ${binaryPath}`);
171-
return binaryPath;
172-
}
173-
174-
static hasValidBinPath(files: string[]): boolean {
175-
if (files.length === 1) {
176-
return true;
177-
} else if (files.length > 1) {
178-
return false;
192+
if (!binaryPath) {
193+
throw new Error(
194+
`MongoBinary.getPath: could not find an valid binary path! (Got: "${binaryPath}")`
195+
);
179196
}
180-
return false;
197+
198+
log(`MongoBinary: Mongod binary path: "${binaryPath}"`);
199+
return binaryPath;
181200
}
182201
}

packages/mongodb-memory-server-core/src/util/__tests__/MongoBinary-test.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ describe('MongoBinary', () => {
4545

4646
describe('getDownloadPath', () => {
4747
it('should download binary and keep it in cache', async () => {
48-
// download
4948
const version = LATEST_VERSION;
5049
const binPath = await MongoBinary.getPath({
5150
downloadDir: tmpDir.name,
@@ -71,14 +70,14 @@ describe('MongoBinary', () => {
7170
describe('getCachePath', () => {
7271
it('should get the cache', async () => {
7372
MongoBinary.cache['3.4.2'] = '/bin/mongod';
74-
await expect(MongoBinary.getCachePath('3.4.2')).resolves.toEqual('/bin/mongod');
73+
expect(MongoBinary.getCachePath('3.4.2')).toEqual('/bin/mongod');
7574
});
7675
});
7776

7877
describe('getSystemPath', () => {
7978
it('should use system binary if option is passed.', async () => {
8079
const accessSpy = jest.spyOn(fs, 'access');
81-
await MongoBinary.getSystemPath('/usr/bin/mongod');
80+
await MongoBinary.getSystemPath('/usr/bin/mongod'); // ignoring return, because this depends on the host system
8281

8382
expect(accessSpy).toHaveBeenCalledWith('/usr/bin/mongod', expect.any(Function));
8483

0 commit comments

Comments
 (0)