We have a high concurrency Grails app, with several worker threads attempting update the same domain object, Message, but the pessimistic locking solution implemented in the service (with transactional set to false) using a static lock Message.lock(msg.id) results in many instances of HibernateOptimisticLockingFailureException.
Facility.withTransaction {
if (resp?.status == 200) {
Message msgCopy = Message.lock(msg.id)
msgCopy.state = State.SoftDeleted
msgCopy.save(flush: true)
}
}
How can a static lock result in a HibernateOptimisticLockingFailure? My understanding is that static lock will read the latest persistent version. It this only a case when another thread has deleted it?
Full error:
[com.cds.healthdock.messaging.Message] with identifier [58653744]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.cds.healthdock.messaging.Message#58653744] at messaging.OutboxService$_pushMessageToPeer_closure8.doCall(OutboxService.groovy:442) at org.grails.datastore.gorm.GormStaticApi.withTransaction(GormStaticApi.groovy:815)
Any strategies (other than catching the exception) I should consider? isDirty() isEmpty()