Fix attachment_s3: do not open a new cursor

Because it provokes serialization errors during the installation or
update of addons. Do not commit as we might commit unwanted things...
Later, we might want to add a specific, more elaborate, migration
process.
This commit is contained in:
Guewen Baconnier
2016-12-13 08:58:08 +01:00
parent 8b15070c7f
commit 53d7cdf3e7
+21 -17
View File
@@ -171,7 +171,7 @@ class IrAttachment(models.Model):
super(IrAttachment, self)._file_delete(fname) super(IrAttachment, self)._file_delete(fname)
@api.model @api.model
def _force_storage_s3(self): def _force_storage_s3(self, new_cr=False):
if not self.env['res.users'].browse(self.env.uid)._is_admin(): if not self.env['res.users'].browse(self.env.uid)._is_admin():
raise exceptions.AccessError( raise exceptions.AccessError(
_('Only administrators can execute this action.') _('Only administrators can execute this action.')
@@ -185,7 +185,11 @@ class IrAttachment(models.Model):
'|', '|',
('res_field', '=', False), ('res_field', '=', False),
('res_field', '!=', False)] ('res_field', '!=', False)]
with self.do_in_new_env() as new_env: # We do a copy of the environment so we can workaround the
# cache issue below. We do not create a new cursor because
# it causes serialization issues due to concurrent updates on
# attachments during the installation
with self.do_in_new_env(new_cr=new_cr) as new_env:
attachment_model = new_env['ir.attachment'] attachment_model = new_env['ir.attachment']
ids = attachment_model.search(domain).ids ids = attachment_model.search(domain).ids
for attachment_id in ids: for attachment_id in ids:
@@ -228,11 +232,9 @@ class IrAttachment(models.Model):
elif attachment.db_datas: elif attachment.db_datas:
_logger.info('moving on the object storage from database') _logger.info('moving on the object storage from database')
attachment.write({'datas': attachment.datas}) attachment.write({'datas': attachment.datas})
# we are in a new env, this is a valid commit
new_env.cr.commit() # pylint: disable=invalid-commit
@contextmanager @contextmanager
def do_in_new_env(self): def do_in_new_env(self, new_cr=False):
""" Context manager that yields a new environment """ Context manager that yields a new environment
Using a new Odoo Environment thus a new PG transaction. Using a new Odoo Environment thus a new PG transaction.
@@ -241,18 +243,20 @@ class IrAttachment(models.Model):
registry = openerp.modules.registry.RegistryManager.get( registry = openerp.modules.registry.RegistryManager.get(
self.env.cr.dbname self.env.cr.dbname
) )
with closing(registry.cursor()) as cr: if new_cr:
try: with closing(registry.cursor()) as cr:
new_env = openerp.api.Environment(cr, self.env.uid, try:
self.env.context) yield self.env(cr=cr)
yield new_env except:
except: cr.rollback()
cr.rollback() raise
raise else:
else: # disable pylint error because this is a valid commit,
# disable pylint error because this is a valid commit, # we are in a new env
# we are in a new env cr.commit() # pylint: disable=invalid-commit
cr.commit() # pylint: disable=invalid-commit else:
# make a copy
yield self.env()
@api.model @api.model
def force_storage(self): def force_storage(self):