TIL: Use the `useMaster` property to fetch data from the write pool in Sequelize.
Sequelize offers support for read replication, enabling the use of multiple servers for executing SELECT queries. In this configuration, you designate one or more servers as read replicas, while appointing one server as the primary writer. The primary writer manages all write and update operations, disseminating them to the designated replicas. It's important to note that Sequelize does not handle the actual replication process; this responsibility lies with the database backend, requiring proper setup.
const sequelize = new Sequelize('database', null, null, {
dialect: 'mysql',
port: 3306,
replication: {
read: [
{ host: '8.8.8.8', username: 'read-1-username', password: process.env.READ_DB_1_PW },
{ host: '9.9.9.9', username: 'read-2-username', password: process.env.READ_DB_2_PW }
],
write: { host: '1.1.1.1', username: 'write-username', password: process.env.WRITE_DB_PW }
},
pool: {
max: 20,
idle: 30000
},
})
Recently, I came across a situation where I was creating(writing) data and immediately on the next line was returning the created record along with some association as an API response but the record was returning empty.
const recordIds = await fileService.create(req.files)
const files = await fileService.list({ id: recordIds })
return response(res, {record: files})
The fileService.create
function creates record file records in the database and returns an array of ids
of the files created. In the next line i.e. the fileService.list
function takes the array of IDs, fetches the record, and returns an API response in the last line. Below is the implementation of the list
function
async list(ids) {
return await Model.findAll({
where: {
id: ids
},
...associationQuery
})
}
This looks plain and simple but for some reason, the list
function didn't return any record. I did a lot of debugging and everything looked fine. Then I came across the property useMaster
. The read replication we read about in our introduction takes some time to replicate in the read
pool. The write
or useMaster: true
query uses a write pool to create or fetch data. So, the useMaster: true
property fixes the issue of fetching data immediately after creating and it fulfills my requirement. Hence, I added useMaster: true
in the above query. So the above list
function becomes like this ๐
async list(ids) {
return await Model.findAll({
where: {
id: ids
},
...associationQuery,
useMaster: true // New added line
})
}
The above code fixed the issue of data not being fetched in read replicas. I hope you like this small TIL
blog. If you have any questions please comment below. Thanks for reading ๐.