From 1c287daa62187e9c95b474d02b3dafb46717f0ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jarda=20Kote=CC=8Cs=CC=8Covec?= Date: Tue, 23 Jul 2019 15:48:16 +0200 Subject: [PATCH] Wait until primary is transitioned from secondary for replicaSet --- .../src/MongoMemoryReplSet.ts | 17 +++++++++----- .../src/__tests__/replset-test.ts | 22 +++++++++++++++++++ .../mongodb-memory-server-core/src/types.ts | 12 +++------- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/packages/mongodb-memory-server-core/src/MongoMemoryReplSet.ts b/packages/mongodb-memory-server-core/src/MongoMemoryReplSet.ts index 13d7e7842..a24992873 100644 --- a/packages/mongodb-memory-server-core/src/MongoMemoryReplSet.ts +++ b/packages/mongodb-memory-server-core/src/MongoMemoryReplSet.ts @@ -173,9 +173,9 @@ export default class MongoMemoryReplSet extends EventEmitter { const server = this._startServer(this.getInstanceOpts({})); servers.push(server); } + // ensures all servers are listening for connection + await Promise.all(servers.map((s) => s.start())); this.servers = servers; - // Brief delay to wait for servers to start up. - await new Promise((resolve) => setTimeout(resolve, 1000)); await this._initReplSet(); } @@ -251,7 +251,7 @@ export default class MongoMemoryReplSet extends EventEmitter { _startServer(instanceOpts: MongoMemoryInstancePropT): MongoMemoryServer { const serverOpts: MongoMemoryServerOptsT = { - autoStart: true, + autoStart: false, debug: this.opts.debug, binary: this.opts.binary, instance: instanceOpts, @@ -265,13 +265,18 @@ export default class MongoMemoryReplSet extends EventEmitter { if (!this.admin) { return false; } - const replStatus: ReplStatusResultT = await this.admin.command({ replSetGetStatus: 1 }); + const replStatus: ReplStatusResultT = await this.admin.command({ + serverStatus: 1, + metrics: 0, + locks: 0, + }); this.debug(' replStatus:', replStatus); - const hasPrimary = replStatus.members.some((m) => m.stateStr === 'PRIMARY'); + const hasPrimary = replStatus.repl.ismaster; if (!hasPrimary) { this.debug('No PRIMARY yet. Waiting...'); - return new Promise((resolve) => setTimeout(() => resolve(this._waitForPrimary()), 1000)); + return new Promise((resolve) => setTimeout(() => resolve(this._waitForPrimary()), 500)); } + return true; } } diff --git a/packages/mongodb-memory-server-core/src/__tests__/replset-test.ts b/packages/mongodb-memory-server-core/src/__tests__/replset-test.ts index a05ee7f3a..19a4cc0e1 100644 --- a/packages/mongodb-memory-server-core/src/__tests__/replset-test.ts +++ b/packages/mongodb-memory-server-core/src/__tests__/replset-test.ts @@ -1,4 +1,5 @@ import MongoMemoryReplSet from '../MongoMemoryReplSet'; +import { MongoClient } from 'mongodb'; jasmine.DEFAULT_TIMEOUT_INTERVAL = 600000; @@ -40,6 +41,16 @@ describe('single server replset', () => { setTimeout(resolve, 500); }); }); + + it('should be possible to connect replicaset after waitUntilRunning resolveds', async () => { + replSet = new MongoMemoryReplSet(); + await replSet.waitUntilRunning(); + const uri = await replSet.getUri(); + + await MongoClient.connect(`${uri}?replicaSet=testset`, { + useNewUrlParser: true, + }); + }); }); describe('multi-member replica set', () => { @@ -57,4 +68,15 @@ describe('multi-member replica set', () => { const uri = await replSet.getUri(); expect(uri.split(',').length).toEqual(3); }, 40000); + + it('should be possible to connect replicaset after waitUntilRunning resolveds', async () => { + const opts: any = { replSet: { count: 3 } }; + replSet = new MongoMemoryReplSet(opts); + await replSet.waitUntilRunning(); + const uri = await replSet.getUri(); + + await MongoClient.connect(`${uri}?replicaSet=testset`, { + useNewUrlParser: true, + }); + }); }); diff --git a/packages/mongodb-memory-server-core/src/types.ts b/packages/mongodb-memory-server-core/src/types.ts index e71976855..3e72c7dbf 100644 --- a/packages/mongodb-memory-server-core/src/types.ts +++ b/packages/mongodb-memory-server-core/src/types.ts @@ -30,16 +30,10 @@ export interface MongoMemoryInstancePropT extends MongoMemoryInstancePropBaseT { storageEngine?: StorageEngineT; } -export interface ReplStatusMemberT { - _id: number; - name: string; - health: number; - state: number; - stateStr: string; - uptime: number; +export interface ReplStatusReplT { + ismaster: boolean; } export interface ReplStatusResultT { - set: string; - members: ReplStatusMemberT[]; + repl: ReplStatusReplT; }