I am using GORM standalone (groovyVersion = '2.0.8', grailsVersion = '2.2.4', gormVersion = '1.3.7', h2Version = '1.3.170') and have a database of objects which will be undergoing frequent concurrent modification.
These objects are grouped by one property, 'entry' and have another property 'process_flags' that I need to update. I want to update all of the process_flag settings of a group of the objects defined by having the same entry. (This will indicate to other processes that I am processing this group of objects.)
I presently try code like the following:
List<Item> res = null
int triesRemaining = 10 // try locking a group this many times
while (res==null && triesRemaining > 0) {
Item firstItem = Item.findByProcessFlags(Item.ProcessFlags.NEW)
if (firstItem==null) return null
res = Item.findAllByEntry(firstItem.entry)
try {
Item.withTransaction {transStatus->
res.each {it->
if (it.processFlags != Item.ProcessFlags.NEW) {
throw new StaleObjectStateException(Item.class.toString(),it.id)
}
it.processFlags = Item.ProcessFlags.IN_PROCESS
it.save(flush:true)
}
}
} catch (HibernateOptimisticLockingFailureException e) {
logger.debug("Caught HibernateOptimisticLockingFailureException. Trying new group.")
res = null
triesRemaining--
}
return res
This results in a exception propagating up the stack, labelled as occurring at the res.each
and as a StaleObjectStateException
, though I presume is actually a HibernateOptimisticLockingFailureException
, as per this discussion: How to handle GORM exceptions. Note that neither the class nor the method in which this code appears is annotated @Transactional
.
So my questions are how to best handle this situation in code with frequent concurrent accesses? Is there a way to do it with catching a failure of optimistic locking? Or does this need to be handled with some pessimistic locking? And if so, can it still be handled with dynamic finders?