This message was deleted.
# questions
s
This message was deleted.
k
thank you mattias. ill give it a try.
@mattias_reichel thank you mattias. Today i checked the logs and there werent optimistic locking failure. can you please help me understand how this prevented the optimistic locking failure. how does putting
Copy code
PageHitCounter.findOrCreateByPageIdentifier(pageIdentifier)
inside withTransaction prevent optimistic locking failure? thanks for the help!
m
If you're not performing both the read and update operations within the same transaction, there's a risk that another thread could modify the database row between the moment you read the value and when you attempt to update it.
k
@mattias_reichel thank you very much! ill wait one more day. if there is no error in the log tomorrow ill accept the answer. thanks for the help!
@mattias_reichel hi mattias thanks for the response but looks like this approach didnt work. today i saw couple of optimistic locking failure exceptions in the logs. the exceptions are of the same nature as posted in the original post. https://stackoverflow.com/questions/77561762/how-to-create-a-thread-safe-hit-counter-in-grails could you suggest another approach? Thanks!
m
@kofhearts I have updated the answer 👍.
k
thanks mattias. what do you think of this approach? i have moved the hit counter update logic to hitcounterservice.
Copy code
@Transactional
class HitCounterService {

    def synchronized visit(pageIdentifier) {


        def hitCounter = null


        hitCounter = PageHitCounter.findOrCreateByPageIdentifier(pageIdentifier)
        hitCounter.hits = hitCounter.hits + 1
        hitCounter.save()


        return hitCounter?.hits



    }
}
so verifyRegistration now looks like this
def verifyRegistration(Long id){
if(springSecurityService.isLoggedIn()){
redirect(controller: "user", action: "index")
return
}
[id: id, hits: hitCounterService.visit("${controllerName}/${actionName}/${id}")]
}
would making the visit method in the service synchronized do the trick?
m
Yes, that should work. But then you are synchronizing updates to all page identifier even though you only need to prevent updates to the same page identifier (database row) by different threads. That is why I used the a map to store different objects to synchronize on. Maybe that is a premature optimization on my part.
k
@mattias_reichel thank you very much!
👍 1