0
votes

We are using Sequelize with a AWS Aurora Postgresql database with a read and write database. Sequelize is configured to use the read replica and write databases.

We have a users table and follows table. The User object type has fields that are subqueries, for instance the field followingCount on the user:

...
followingCount: {
  type: new GraphQLNonNull(GraphQLInt),
  resolve(user) {
    return db.Follower.count({
      where: { followerId: user.id, status: "Approved" }
    });
  }
},

When we add a record to the follows table for a user, then return that user instance, the followingCount is not updated. I'm 99% confident this is because it's reading from the replica/read database which does not have the data. I've verified this by disabling the replica and seeing the issue disappear.

I'm hesitant to add the useMaster option to these fields, as it negates our concurrency strategy.

Here is the exact code I am calling:

const followingUser = await db.User.findOne({
  where: {
    id
  }
});

await db.Follower.create({
  followerId: getCurrentUserId(context),
  followingId: id,
  status: followingUser.privateProfile ? "Pending" : "Approved"
});

return followingUser.reload();

The followingCount field on the user instance(followingUser) isn't returning the newest count even though it exists on the master/write db.

What options are there? Is there someway I can wrap my mutations in a block so that anything executed within uses the Master/Write database? Would wrapping it in a transaction help, and if so how do I pass the transaction down to my

ANY help appreciated

psql 9.6.8

sequelize 4.38.0

2
My dear, Can I have your comment on z answer ?bereket gebredingle

2 Answers

2
votes

I was able to solve this by calling reload() on the DB Object I was returning, and passing it useMaster: true

followingUser.reload({ useMaster: true });

I created a ticket with sequelize that has more context if it's helpful for anyone: https://github.com/sequelize/sequelize/issues/9971

0
votes

In PostgreSQL replication can be made in various ways:

  • Synchronous
  • Asynchronous

If you are running asynchronous replication, data might hit the slave AFTER a transaction has been committed on the primary server (master). There is usually a small replication delay.

You can replicate synchronously to as many slaves as you want to ensure that a COMMIT is only valid once it has been confirmed by the desired number of PostgreSQL servers.

Synchronous transaction can return only if a sufficient number of slaves have confirmed the write.

so I think you are using asynchronous replication and you need to shift to synchronous replication.

https://www.cybertec-postgresql.com/en/services/postgresql-replication/synchronous-synchronous-replication/

In order to set up synchronous replication, you need to configure synchronous_standby_name and synchronous_commit parameters in the postgresql.conf file. The synchronous_commit parameter can have following values: off, on, remote_write, remote_apply (a Postgres 9.6 feature), and local.

More on how to set up sync replication