Grails Job | Several updates in the mongodb always launch an optimal lock exception, how to handle it?

advertisements

i have a grails job which is scheduled to run at every night, to update stats of all user which are firstOrderDate, lastOrderDate and totalOrders.

Have a look at the code.

 void updateOrderStatsForAllUsers(DateTime date) {
    List<Order> usersByOrders = Delivery.findAllByDeliveryDateAndStatus(date, "DELIVERED")*.order
    List<User> customers = usersByOrders*.customer.unique()

    for (User u in customers) {
        List<Order> orders = new ArrayList<Order>();
        orders = u.orders?.findAll { it.status.equals("DELIVERED") }?.sort { it?.dateCreated }
        if (orders?.size() > 0) {
            u.firstOrderDate = orders?.first()?.dateCreated
            u.lastOrderDate = orders?.last()?.dateCreated
            u.totalOrders = orders.size()
            u.save(flush: true)
        }
    }
}

and the job that runs this code is

def execute(){
    long jobStartTime = System.currentTimeMillis()

    emailService.sendJobStatusEmail(JOB_NAME, "STARTED", 0, null)

    try {
        // Daily job for updating user orders
        DateTime yesterday = new DateTime().withZone(DateTimeZone.getDefault()).withTimeAtStartOfDay().minusDays(1)
        userService.updateOrderStatsForAllUsers(yesterday)
        emailService.sendJobStatusEmail(JOB_NAME, "FINISHED", jobStartTime, null)
    }
    catch (Exception e) {
        emailService.sendJobStatusEmail(JOB_NAME, "FAILED", jobStartTime, e)
    }
}

So i am sending a mail , for any exception that occurs , now the issue is i always get a failure mail of "Error: OptimisticLockingException" at u.save(). For a date i have around 400 users.

I know why optimistic locking happens , but as you can see i am not updating the same user record in loop instead , i have a list of different users and i am iterating them to update all of them. Then how come i get an optimistic locking exception at user save. help !


Optimistic locking is a hibernate error and Mango DB has nothing to do with this.

What entity is throwing optimistic locking exception is it customer or order or delivery?

How do you ensure none of these entities are getting updated elsewhere in the app when this job is running?

How do you ensure this job is getting triggered only once at a time?

Try to add some logging to see it's a repeatable issue by triggering the job again once the previous execution has completed.

More debugging may help resolve the issue.