I have a cron that call the method my_cron_method() so defined (simplified):
class MyModel(models.Model):
model_cron_id = fields.Many2one('ir.cron', 'Cron Scheduled Action')
def my_cron_method(self):
object_list = self.env['my.model']
for object in object_list:
print('ck_1')
object.att_a = 123
self.update_obj(object)
print('ck_4')
def update_obj(self, object):
print('ck_2')
object.att_b='abc'
print('ck_3')
return
The result when executed by cron is:
ck_1
ck_2
so the method "freezes" at object.att_b='abc' row.
These happens only if model_cron_id is valorized; if object_list has two elements and the valorized is the second, the first is completely elaborated.
I use PyCharm debug to follow step by step execution and when I confirm to execute the row it locks doing nothing else.
I tried to pause the execution a step before and do on console
object._write({'att_a' : 123})
and it locks too.
The rest of Odoo seems going well, only object on write is locked.
If I trigger the cron manually all goes well.
Any idea?
EDIT
I add the information on model_cron_id, because I discovered that it is the element that generates the problem.
After a long search and with some suggestion I arrived to a solution or better a workaround.
I suppose the problem is that when in my_cron_method() the first attribute is setted object.att_a = 123
the object is locked an this propagate the lock to the cron object that is related (the same that is in execution).
Following this suggestion (https://www.odoo.com/it_IT/forum/help-1/question/how-to-force-commit-in-a-loop-109751) I added self.env.cr.commit()
after the attribute update. These solves the lock.
There is another aspect to take present that comes from the Odoo documentation here https://www.odoo.com/documentation/12.0/reference/orm.html#field-access in case there are multiple attribute to update: use .write()
to update all attribute at once.
The complete solution is these:
class MyModel(models.Model):
att_a = fields.Integer('Attr_a')
att_b = fields.Char('Attr_b')
att_c = fields.Char('Attr_c')
model_cron_id = fields.Many2one('ir.cron', 'Cron Scheduled Action')
def my_cron_method(self):
object_list = self.env['my.model']
for object in object_list:
object.att_a = 123
self.env.cr.commit()
self.update_obj(object)
def update_obj(self, object):
object.write({'att_b': 'abc', 'att_c': 'def'})
return