Skip to content

Commit

Permalink
[FIX] core: add invalidation of Environment's _cache_key.
Browse files Browse the repository at this point in the history
Changing the environment in method create() to force bin_size=False
looks harmless, but it actually breaks many tests, in particular in
module account.  The reason is that company_dependent fields are read at
the wrong place in the cache.  And this is because `env._cache_key` can
be polluted with old data.

Make sure that `_cache_key` is cleared when resetting all the lazy
properties on the environment.  Only the change in res_user.py makes it
work, but let's not tempt the devil.

Side note: I hate caches.

Part-of: odoo#160708
  • Loading branch information
ryv-odoo committed Apr 26, 2024
1 parent 695ff39 commit a0bf434
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 1 deletion.
4 changes: 3 additions & 1 deletion odoo/addons/base/models/res_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -672,13 +672,15 @@ def write(self, values):
user.partner_id.write({'company_id': user.company_id.id})

if 'company_id' in values or 'company_ids' in values:
# Reset lazy properties `company` & `companies` on all envs
# Reset lazy properties `company` & `companies` on all envs,
# and also their _cache_key, which may depend on them.
# This is unlikely in a business code to change the company of a user and then do business stuff
# but in case it happens this is handled.
# e.g. `account_test_savepoint.py` `setup_company_data`, triggered by `test_account_invoice_report.py`
for env in list(self.env.transaction.envs):
if env.user in self:
lazy_property.reset_all(env)
env._cache_key.clear()

# clear caches linked to the users
if self.ids and 'groups_id' in values:
Expand Down
21 changes: 21 additions & 0 deletions odoo/addons/test_new_api/tests/test_new_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -2921,6 +2921,27 @@ def test_99_prefetch_group(self):
records.mapped('harry') # fetch all fields with prefetch='Harry Potter'
records.mapped('rare_description') # fetch that field only

def test_cache_key_invalidation(self):
company0 = self.env.ref('base.main_company')
company1 = self.env['res.company'].create({'name': 'A'})

user0 = self.env['res.users'].create({
'name': 'Foo', 'login': 'foo', 'company_id': company0.id,
'company_ids': [Command.set([company0.id, company1.id])],
})

# this uses company0
record = self.env['test_new_api.company'].with_user(user0).create({
'foo': 'main',
})
self.assertEqual(record.env.company, company0)
self.assertEqual(record.foo, 'main')

# change the user's company, so we implicitly switch to company1
user0.company_id = company1
self.assertEqual(record.env.company, company1)
self.assertEqual(record.foo, False)


class TestX2many(common.TransactionCase):

Expand Down
2 changes: 2 additions & 0 deletions odoo/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,7 @@ def clear(self):
This may be useful when recovering from a failed ORM operation.
"""
lazy_property.reset_all(self)
self._cache_key.clear()
self.transaction.clear()

def invalidate_all(self, flush=True):
Expand Down Expand Up @@ -873,6 +874,7 @@ def reset(self):
for env in self.envs:
env.registry = self.registry
lazy_property.reset_all(env)
env._cache_key.clear()
self.clear()


Expand Down

0 comments on commit a0bf434

Please sign in to comment.