Iworb's blog

Full Stack (Node + Express + MongoDb + Vue + Nuxt) application. Part 4: MongoDb

2018-02-13

Connection

We’re going to use mongoose to communicate with our MongoDb instance. Make sure MongoDb running and configured.
For storing sessions in the database we also need connect-mongo package.

1
yarn add mongoose connect-mongo

Configs for mongo connection looks like this:

1
2
3
4
5
6
7
8
9
10
db: {
uri: 'mongodb://localhost/nemvn?authSource=admin',
options: {
user: 'admin',
pass: 'admin',
socketTimeoutMS: 0,
keepAlive: true,
reconnectTries: 30
}
}

Make sure you’re set correct user and pass for your mongo instance. If there’s no auth - just remove this options from list.

Initialization

MongoDb initialization will be described in server/engine/mongo.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
const config = require('@config')
const logger = require('@engine/logger')
const {env} = require('@helpers')

const chalk = require('chalk')
const mongoose = require('mongoose')

module.exports = () => {
mongoose.Promise = global.Promise

if (mongoose.connection.readyState !== 1) {
logger.info(`Connecting to Mongo ${config.db.uri} ...`)
mongoose.connection.on('error', err => {
if (err.message.code === 'ETIMEDOUT') {
logger.warn('Mongo connection timeout!', err)
setTimeout(() => {
mongoose.connect(config.db.uri, config.db.options)
}, 1000)
return
}

logger.error('Could not connect to MongoDB!')
return logger.error(err)
})
mongoose.connection.once('open', () => {
logger.info(chalk.yellow.bold('Mongo DB connected.'))
logger.info()
})
mongoose.connect(config.db.uri, config.db.options)
.then(() => {
mongoose.set('debug', env.isDev())
})
.catch(err => {
logger.error('Could not connect to MongoDB!')
return logger.error(err)
})
} else {
logger.info('Mongo already connected.')
}

return mongoose.connection
}

Connection process is simple. There’s some extra handlers for logging.
We should init MongoDb before express:

1
2
const db = require('@engine/mongo')()
const app = require('@engine/express')(db)

Session

Now we can use this MongoDb instance as session storage.
As you can see above, we passed db constant into express init function, let’s handle this:

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
const MongoStore = require('connect-mongo')(session)
...
/**
* Initialize session
* @param {any} app
* @param {db} db
*/
function initSession (app, db) {
const configSession = config.session
configSession.store = new MongoStore({
mongooseConnection: db,
autoReconnect: true
})
app.use(session(configSession))
}
...
module.exports = db => {
const app = express()

initMiddleware(app)
initHelmetHeaders(app)
initSession(app, db)
initNuxt(app)

return app
}

Now all sessions will be saved in the database.
NB: we’re saving just initialized sessions of authorized users. There’s no users atm, so you could set saveUninitialized to true in your config to look how it works.

Close connection

The final thing is about connection closing when server have to stop. Let’s modify helper safeStop.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const logger = require('@engine/logger')
const env = require('./env')

const chalk = require('chalk')
const moment = require('moment')
const mongoose = require('mongoose')

const smoothExit = async () => {
const exit = () => {
logger.info()
logger.info(chalk.bold('------[ Server stopped at %s Uptime: %s ]------'), moment().format('YYYY-MM-DD HH:mm:ss.SSS'), moment.duration(process.uptime() * 1000).humanize())
return process.exit(0)
}
if (mongoose.connection.readyState === 0) {
return exit()
} else {
if (env.isTest()) await mongoose.connection.dropDatabase()
await mongoose.connection.close()
return exit()
}
}

process.on('SIGINT', smoothExit).on('SIGTERM', smoothExit)

This part wraps up 04-mongo git branch.

Tags: mongo