-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathindex.js
137 lines (120 loc) · 3.93 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
const util = require('util')
const path = require('path')
const portfinder = require('portfinder')
const { MongodHelper } = require('mongodb-prebuilt');
const mongodb = require('mongodb')
const debug = require('debug')('mockgo')
let connectionCache = {}
let maxRetries = 5
let mongoClient = null
let mongodHelper = null
let initPromise = null
const startServer = retries => {
retries = retries || 0
return portfinder.getPortPromise().then(port => {
const config = {
host: '127.0.0.1',
port: port
}
const mongodArgs = [
'--port', config.port,
'--bind_ip', config.host,
'--storageEngine', 'ephemeralForTest',
'--dbpath', path.join(__dirname, './.data')
]
mongodHelper = new MongodHelper(mongodArgs)
debug('startServer on port %d', config.port)
return mongodHelper.run().then(() => {
debug('mongod is running on port %d', config.port)
return config
})
}).catch(error => {
debug('error starting server "%s"', error)
// mongodb-prebuilt no longer returns detailed information about what went wrong
// Its no longer possible to know why it couldnt get started to decide whether retry or not
if (retries < maxRetries) {
return new Promise((resolve, reject) => {
setTimeout(() => startServer(retries++).then(resolve).catch(reject), 200)
})
}
throw error
})
}
const createMongoClient = config => {
const uri = util.format('mongodb://%s:%d', config.host, config.port)
debug('creating MongoClient for "%s"', uri)
//we add the possibilty to override the version of the mongodb driver
//by exposing it via module.exports
return module.exports.mongodb.connect(uri, { useNewUrlParser: true })
.then(client => { mongoClient = client })
}
const createDatabaseConnection = dbName => {
debug('creating connection for db "%s"', dbName)
connectionCache[dbName] = mongoClient.db(dbName)
return connectionCache[dbName]
}
const getConnection = (dbName, callback) => {
if (typeof dbName === 'function') {
callback = dbName
dbName = 'testDatabase'
}
if (!dbName){
dbName = 'testDatabase'
}
if (initPromise === null){
initPromise = startServer().then(createMongoClient)
}
return initPromise
.then(() => createDatabaseConnection(dbName))
.then(connection => {
if (typeof callback === 'function'){
callback(null, connection)
} else {
return connection
}
}).catch(err => {
if (typeof callback === 'function'){
callback(err)
} else {
throw err
}
})
}
const shutDown = callback => {
let cleanup = Promise.resolve()
if (initPromise !== null) {
cleanup = initPromise.then(() => {
debug('closing mongo client')
return mongoClient.close(true)
}).then(() => {
mongoClient = null
debug('sending mongod process')
mongodHelper.kill()
}).then(() => {
// mongodb-prebuilt doesnt provide a mechanism itself to notify when shutdown really happened
// grabbing the spawn process and waiting for the close event
return new Promise((resolve, reject) => {
mongodHelper.mongoBin.childProcess.on('close', code => resolve(code))
mongodHelper = null
})
})
}
initPromise = null
return cleanup.then(() => {
debug('cleanup done')
if (typeof callback === 'function'){
callback(null)
}
}).catch(err => {
if (typeof callback === 'function'){
callback(err)
} else {
throw err
}
})
}
module.exports = {
getConnection,
shutDown,
mongodb: mongodb
}