question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Optimistic Locking doesn't work for update

See original GitHub issue

Issue type:

[ ] question [ ] bug report [ ] feature request [ ] documentation issue

Database system/driver:

[ ] cordova [ ] mongodb [ ] mssql [ ] mysql / mariadb [ ] oracle [x ] postgres [ ] sqlite [ ] sqljs [ ] react-native [ ] expo

TypeORM version:

[x ] latest [ ] @next [ ] 0.x.x (or put your version here)

Steps to reproduce or a small repository showing the problem: Hi All,

Trying to use the @Version annotation to implement optimistic locking for ensuring entity updates don’t stomp on newer data. I couldn’t find an example using QueryRunner along with update(), but I tried it anyway like this:

await transactionalRepository.createQueryBuilder(“c”) .setLock(“optimistic”, caseEntity.version) .update() .set(this.createCaseUpdateObj(caseEntity)) .where(“id = :id”, {id: caseEntity.id}) .execute();

However, this operation succeeds no matter what I pass to setLock for version. I CAN ensure that I don’t stomp on newer data by augmenting my query like so:

await transactionalRepository.createQueryBuilder(“c”) .update() .set(this.createCaseUpdateObj(caseEntity)) .where(“id = :id”, {id: caseEntity.id}) .andWhere(“version = :version”, {version: caseEntity.version}) .execute();

However, the problem now is I have no way of finding out whether my update was actually applied. To do that, I need to know how many rows where updated by my query, which does not appear to be returned by this method.

Are there plans to make setLock() handle this case for update() (most ORMs support this)? If not, are there plans to return the number of rows updated by an operation like the one above? If so, any idea of timeframe?

I think until then I’d probably need to drop down to lower level postgres driver to safely perform an update operation.

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:1
  • Comments:8 (1 by maintainers)

github_iconTop GitHub Comments

3reactions
tstearncommented, Sep 25, 2018

I see that issue 1308 would let me check to see how many rows were updated, which would allow me to safely implement an Optimistic Lock for update. This would be a fine intermediate result.

However, I think longer term actually making setLock() with update() work like this would be a more intuitive and reusable API, especially given this is how other ORMs behave.

1reaction
tstearncommented, Nov 2, 2018

I stumbled on a reliable way of making this work for Postgres:

//The version where clause below prevents an update from occurring if a newer version is already in the database //Now, we need to determine if the update did occur so we can signal the user, if not. //The traditional way to do this would be to check to see how many rows where updated - if it’s zero, the updated didn’t go through due to version //TypeORM doesn’t return the number of rows affected, but can use .returning().
//This takes an array of fields to return the updated values for.
//If the update doesn’t go through due to the version where clause, this array will be empty const result = await manager.createQueryBuilder() .update(entityName) .set(updateFields) .where(“id = :id”, {id: entity.id}) .andWhere(“version = :version”, {version: entity.version}) .returning(“version”) .execute();

const updateSucceeded = result.raw.length !== 0;
if(!updateSucceeded) {
		throw new OptimisticLockError(`Update did not go through due to outdated version ${updateParams.entity.version}`);
} 

As discussed in the comment above, using .returning() gives a reliable indicator of whether the update went through. Combining this with the version checking where clause makes an acceptable solution.

Having the .setLock() and @Version feature work together to accomplish this would be better, but this is OK for now.

Read more comments on GitHub >

github_iconTop Results From Across the Web

What should I do when optimistic locking doesn't work?
The first PUT request does not have time to process and update the resource before PUT #2 arrives, which causes PUT #2 to...
Read more >
How to unlock (re-load current state) in optimistic locking?
If you get an optimistic locking failure, that means the object that you tried to update wasn't up-to-date when you edited it. In...
Read more >
Optimistic locking with version number - Amazon DynamoDB
Optimistic locking is a strategy to ensure that the client-side item that you are updating (or deleting) is the same as the item...
Read more >
Optimistic Locking in JPA - Baeldung
Before the transaction wants to make an update, it checks the version property again.
Read more >
Optimistic and pessimistic record locking - IBM
The optimistic locking model, also referred to as optimistic concurrency control, is a concurrency control method used in relational databases that does not...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found