Revert "[FIX] ir_qweb: assets: write in ir.attachment outside of main transaction"

This reverts commit 6327cda0a7.
This commit is contained in:
Simon Lejeune
2015-10-14 17:42:19 +02:00
parent ed56952079
commit d1fb85d3dc
+37 -55
View File
@@ -22,7 +22,6 @@ import werkzeug
from lxml import etree, html
from PIL import Image
import psycopg2
from collections import namedtuple
import openerp.http
import openerp.tools
@@ -41,7 +40,6 @@ from openerp.modules.module import get_resource_path
_logger = logging.getLogger(__name__)
MAX_CSS_RULES = 4095
MOCK_ATTACH = namedtuple('mock_attach', ['url', 'last_update'])
#--------------------------------------------------------------------
# QWeb template engine
@@ -1216,26 +1214,11 @@ class AssetsBundle(object):
attachment_ids = ira.search(self.cr, openerp.SUPERUSER_ID, domain, context=self.context)
return ira.unlink(self.cr, openerp.SUPERUSER_ID, attachment_ids, context=self.context)
def _mock_attachments(self, attachments):
""" As the assets are generated during the same transaction as the rendering of the
templates calling them, there is a scenario where the assets are unreachable: when
you make a request to read the assets while the transaction creating them is not done.
Indeed, when you make an asset request, the controller has to read the `ir.attachment`
table.
This scenario happens when you want to print a PDF report for the first
time, as the assets are not in cache and must be generated. To workaround this issue, we
need to open multiple cursors to write in the `ir.attachment` table outside of the ~main
transaction. But there's another tweak: a recordset browsed with a closed cursor becomes
unusable. We chose to copy their content in a namedtuple.
"""
return [MOCK_ATTACH(attachment.url, attachment['__last_update']) for attachment in attachments]
def get_attachments(self, type, inc=None):
ira = self.registry['ir.attachment']
domain = [('url', '=like', '/web/content/%%-%s/%s%s.%s' % (self.version, self.xmlid, ('%%' if inc is None else '.%s' % inc), type))]
attachment_ids = ira.search(self.cr, openerp.SUPERUSER_ID, domain, context=self.context)
return self._mock_attachments(ira.browse(self.cr, openerp.SUPERUSER_ID, attachment_ids, context=self.context))
return ira.browse(self.cr, openerp.SUPERUSER_ID, attachment_ids, context=self.context)
def save_attachment(self, type, content, inc=None):
ira = self.registry['ir.attachment']
@@ -1243,27 +1226,27 @@ class AssetsBundle(object):
attachments = self.get_attachments(type, inc)
values = {}
with self.registry.cursor() as cr2:
if not attachments:
values["name"] = "/web/content/%s" % type
values["datas_fname"] = '%s%s.%s' % (self.xmlid, ('' if inc is None else '.%s' % inc), type)
values["res_model"] = 'ir.ui.view'
values["public"] = True
values["type"] = 'binary'
attachment_id = ira.create(cr2, openerp.SUPERUSER_ID, values, context=self.context)
url = '/web/content/%s-%s/%s' % (attachment_id, self.version, values["datas_fname"])
values["name"] = url
values["url"] = url
else:
attachment_id = attachments[0].id
if not attachments:
values["name"] = "/web/content/%s" % type
values["datas_fname"] = '%s%s.%s' % (self.xmlid, ('' if inc is None else '.%s' % inc), type)
values["res_model"] = 'ir.ui.view'
values["public"] = True
values["type"] = 'binary'
attachment_id = ira.create(self.cr, openerp.SUPERUSER_ID, values, context=self.context)
url = '/web/content/%s-%s/%s' % (attachment_id, self.version, values["datas_fname"])
values["name"] = url
values["url"] = url
else:
attachment_id = attachments[0].id
values["datas"] = content.encode('utf8').encode('base64')
ira.write(cr2, openerp.SUPERUSER_ID, attachment_id, values, context=self.context)
return self._mock_attachments(ira.browse(cr2, openerp.SUPERUSER_ID, attachment_id, context=self.context))[0]
values["datas"] = content.encode('utf8').encode('base64')
ira.write(self.cr, openerp.SUPERUSER_ID, attachment_id, values, context=self.context)
return ira.browse(self.cr, openerp.SUPERUSER_ID, attachment_id, context=self.context)
def js(self):
attachments = self.get_attachments('js')
if not attachments or attachments[0].last_update < Datetime.to_string(max([asset.last_modified for asset in self.javascripts])):
if not attachments or attachments[0]['__last_update'] < Datetime.to_string(max([asset.last_modified for asset in self.javascripts])):
content = ';\n'.join(asset.minify() for asset in self.javascripts)
return self.save_attachment('js', content)
return attachments[0]
@@ -1300,7 +1283,7 @@ class AssetsBundle(object):
page = pages[-1]
page_selectors = selectors
for idx, page in enumerate(pages):
attachments.append(self.save_attachment("css", ' '.join(page), inc=idx))
attachments |= self.save_attachment("css", ' '.join(page), inc=idx)
return attachments
def css_message(self, message):
@@ -1557,25 +1540,24 @@ class PreprocessedCSS(StylesheetAsset):
def to_html(self):
if self.url:
try:
with self.registry.cursor() as cr3:
ira = self.registry['ir.attachment']
url = self.html_url % self.url
domain = [('type', '=', 'binary'), ('url', '=', url)]
with cr3.savepoint():
ira_id = ira.search(cr3, openerp.SUPERUSER_ID, domain, context=self.context)
datas = self.content.encode('utf8').encode('base64')
if ira_id:
# TODO: update only if needed
ira.write(cr3, openerp.SUPERUSER_ID, ira_id, {'datas': datas},
context=self.context)
else:
ira.create(cr3, openerp.SUPERUSER_ID, dict(
datas=datas,
mimetype='text/css',
type='binary',
name=url,
url=url,
), context=self.context)
ira = self.registry['ir.attachment']
url = self.html_url % self.url
domain = [('type', '=', 'binary'), ('url', '=', url)]
with self.cr.savepoint():
ira_id = ira.search(self.cr, openerp.SUPERUSER_ID, domain, context=self.context)
datas = self.content.encode('utf8').encode('base64')
if ira_id:
# TODO: update only if needed
ira.write(self.cr, openerp.SUPERUSER_ID, ira_id, {'datas': datas},
context=self.context)
else:
ira.create(self.cr, openerp.SUPERUSER_ID, dict(
datas=datas,
mimetype='text/css',
type='binary',
name=url,
url=url,
), context=self.context)
except psycopg2.Error:
pass
return super(PreprocessedCSS, self).to_html()