Skip to content

Commit c600609

Browse files
committed
fix(DryMongoBinary::locateBinary): check if download-lock still exists
and treat it like the binary does not exists fixes #872
1 parent 9db479f commit c600609

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

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

+19-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import debug from 'debug';
22
import { DEFAULT_VERSION, envToBool, resolveConfig, ResolveConfigVariables } from './resolveConfig';
3-
import { assertion, checkBinaryPermissions, isNullOrUndefined, pathExists } from './utils';
3+
import {
4+
assertion,
5+
checkBinaryPermissions,
6+
isNullOrUndefined,
7+
lockfilePath,
8+
pathExists,
9+
} from './utils';
410
import * as path from 'path';
511
import { arch, homedir, platform } from 'os';
612
import findCacheDir from 'find-cache-dir';
@@ -100,6 +106,18 @@ export class DryMongoBinary {
100106
return undefined;
101107
}
102108

109+
// check for the race-condition of "extraction started, but not finished"
110+
// or said differently, the file "exists" but is not fully extracted yet
111+
// see https://github.com/nodkz/mongodb-memory-server/issues/872
112+
if (
113+
returnValue[0] &&
114+
(await pathExists(lockfilePath(path.dirname(returnValue[1]), useOpts.version)))
115+
) {
116+
log('locateBinary: binary found, but also a download-lock, trying to resolve lock');
117+
118+
return undefined;
119+
}
120+
103121
log(`locateBinary: found binary at "${returnValue[1]}"`);
104122
this.binaryCache.set(opts.version, returnValue[1]);
105123

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

+22
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,28 @@ describe('DryBinary', () => {
428428
expect(binary.DryMongoBinary.generateDownloadPath).toHaveBeenCalled();
429429
});
430430

431+
it('should return "undefined" if binary can be found but also a download-lock', async () => {
432+
jest
433+
.spyOn(binary.DryMongoBinary, 'generateDownloadPath')
434+
.mockResolvedValue([true, '/tmp/1.1.1']);
435+
436+
const originalPathExists = utils.pathExists;
437+
438+
const utilsSpy = jest.spyOn(utils, 'pathExists').mockImplementation((path) => {
439+
if (path === '/tmp/1.1.1.lock' || path === '/tmp/1.1.1') {
440+
return Promise.resolve(true);
441+
}
442+
443+
return originalPathExists(path);
444+
});
445+
446+
const returnValue = await binary.DryMongoBinary.locateBinary({ version: '1.1.1' });
447+
expect(returnValue).toBeUndefined();
448+
expect(binary.DryMongoBinary.binaryCache.size).toBe(0);
449+
expect(binary.DryMongoBinary.generateDownloadPath).toHaveBeenCalled();
450+
expect(utilsSpy).toHaveBeenCalledWith('/tmp/1.1.1.lock');
451+
});
452+
431453
it('should return cached version if exists', async () => {
432454
const mockBinary = '/custom/path';
433455
binary.DryMongoBinary.binaryCache.set('1.1.1', mockBinary);

0 commit comments

Comments
 (0)