[FIX] core: disable wait_callback during copy_from

Apparently some solutions (e.g. bitnami) deploy odoo using async
workers, and not all pg/psycopg2 features are supported in that mode,
notably COPY FROM (bulk-copying data from a stream to postgres). Work
around this issue by disabling "async mode" as we do the copy (by
resetting the wait callback) then re-enabling it.

While this is not an officially supported run mode, it should Do No
Harm™ for normal operations and could help users and clients.

Of important note: while this fixes an error running in async mode, it
will also prevent the worker from yielding while copy_from is
executing. Hopefully that doesn't take too long (as the entire point
of the copy_from is to be fast) but there you are.

Fixes odoo/odoo#24145

closes odoo/odoo#43481

X-original-commit: c4583cf89c2b24085a2eeafea5ef76f474c5ff84
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
This commit is contained in:
Christopher Ormaza
2020-01-17 12:20:03 +00:00
committed by Xavier Morel
parent 0871ed02ab
commit 51de5eb041
+22 -14
View File
@@ -40,7 +40,7 @@ from operator import attrgetter, itemgetter
import babel.dates
import dateutil.relativedelta
import psycopg2
import psycopg2, psycopg2.extensions
from lxml import etree
from lxml.builder import E
from psycopg2.extensions import AsIs
@@ -755,19 +755,27 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
for r in missing
)
fields = ['module', 'model', 'name', 'res_id']
cr.copy_from(io.StringIO(
u'\n'.join(
u"%s\t%s\t%s\t%d" % (
modname,
record._name,
xids[record.id][1],
record.id,
)
for record in missing
)),
table='ir_model_data',
columns=fields,
)
# disable eventual async callback / support for the extent of
# the COPY FROM, as these are apparently incompatible
callback = psycopg2.extensions.get_wait_callback()
psycopg2.extensions.set_wait_callback(None)
try:
cr.copy_from(io.StringIO(
u'\n'.join(
u"%s\t%s\t%s\t%d" % (
modname,
record._name,
xids[record.id][1],
record.id,
)
for record in missing
)),
table='ir_model_data',
columns=fields,
)
finally:
psycopg2.extensions.set_wait_callback(callback)
self.env['ir.model.data'].invalidate_cache(fnames=fields)
return (