[SalesForce] How to prevent UNABLE_TO_LOCK_ROW via the REST API

I have an app that uses the restforce gem to make queries against Salesforce. I ran into an issue with locked rows (UNABLE_TO_LOCK_ROW error), so now I would like to select Contacts, Leads, Opportunities, and Tasks with the FOR UPDATE clause, but I keep getting this error:

Faraday::ClientError: MALFORMED_QUERY: FOR UPDATE not allowed in this context

None of these queries work:

  1. client.query("SELECT Id, Description from Task FOR UPDATE")
  2. client.query("SELECT Id, Description from Task LIMIT 2 FOR UPDATE")
  3. client.query("SELECT Id, Description from Lead FOR UPDATE")
  4. client.query("SELECT Id, Description from Lead LIMIT 2 FOR UPDATE")

They all throw the error MALFORMED_QUERY. How the heck am I supposed to use FOR UPDATE?

If I can't use FOR UPDATE with the REST API, how do I tell Salesforce I need to lock a row and prevent the UNABLE_TO_LOCK_ROW error?

Any ideas would be helpful! Thanks!

Best Answer

You can really only effectively use FOR UPDATE for record locking within Apex code (which you could expose via a REST resource and call from your external system). It will lock the records returned by the query for the remainder of the transaction, and the transaction is free to make updates to the records in question while it holds the lock. Other simultaneous transactions that attempt to lock the record will have to wait.

You'll be unable to use FOR UPDATE when simply querying a record via the standard REST API because the transaction is over as soon as the data is returned to you. If you're then making an update to the record via the standard REST API after the initial query, this is a separate transaction and Salesforce does not allow any mechanism to lock records between transactions like this. In order to avoid the misconception that a record is locked after your query transaction takes place, Salesforce returns the error messages you've been getting.

Related Topic