[IMP] core: introduce OrderedWeakSet
The Weakset Used for envs can lead to unpredictible behaviour when calling flush on the transaction because we iterate on the `envs`. Since WeakSet.data is a set, the iteration will depends on the python hash seed. This commit proposes to replace Transaction.envs.data by an OrderedSet to solve this issue. Some test demonstrates that it does not affect the garbage collection and that the order is now deterministic. The question to now if we should reverse the envs to find the most suitable envs remains. closes odoo/odoo#121604 Signed-off-by: Raphael Collet <rco@odoo.com>
This commit is contained in:
@@ -54,6 +54,7 @@ from . import test_reports
|
||||
from . import test_test_retry
|
||||
from . import test_test_suite
|
||||
from . import test_tests_tags
|
||||
from . import test_transactions
|
||||
from . import test_form_create
|
||||
from . import test_cloc
|
||||
from . import test_profiler
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
from odoo.tests.common import TransactionCase
|
||||
|
||||
|
||||
class TestTransactionEnvs(TransactionCase):
|
||||
def test_transation_envs_weakrefs(self):
|
||||
transaction = self.env.transaction
|
||||
starting_envs = set(transaction.envs)
|
||||
base_x = self.env['base'].with_context(test_stuff=False)
|
||||
self.assertIn(base_x.env, transaction.envs)
|
||||
del base_x
|
||||
self.assertEqual(set(transaction.envs), starting_envs)
|
||||
|
||||
def do_stuff_with_env(self):
|
||||
base_test = self.env['base'].with_context(test_stuff=False)
|
||||
base_test |= self.env['base'].with_context(test_stuff=1)
|
||||
base_test |= self.env['base'].with_context(test_stuff=2)
|
||||
return base_test
|
||||
|
||||
def test_transation_envs_weakrefs_call(self):
|
||||
transaction = self.env.transaction
|
||||
starting_envs = set(transaction.envs)
|
||||
self.do_stuff_with_env()
|
||||
self.assertEqual(set(transaction.envs), starting_envs)
|
||||
|
||||
def test_transation_envs_weakrefs_return(self):
|
||||
transaction = self.env.transaction
|
||||
starting_envs = set(transaction.envs)
|
||||
base_test = self.do_stuff_with_env()
|
||||
self.assertEqual(set(transaction.envs), starting_envs | {base_test.env})
|
||||
|
||||
def test_transation_envs_ordered(self):
|
||||
transaction = self.env.transaction
|
||||
starting_envs = set(transaction.envs)
|
||||
# create environments in a certain order, not sorted on item
|
||||
items = [3, 8, 1, 5, 2, 7, 6, 9, 0, 4]
|
||||
envs = [self.env(context={'item': item}) for item in items]
|
||||
# check that those environments appear in order in transaction.envs
|
||||
env_items = [env.context['item'] for env in transaction.envs if env not in starting_envs]
|
||||
self.assertEqual(env_items, items)
|
||||
del envs
|
||||
self.assertEqual(set(transaction.envs), starting_envs)
|
||||
@@ -825,6 +825,7 @@ class Transaction:
|
||||
self.registry = registry
|
||||
# weak set of environments
|
||||
self.envs = WeakSet()
|
||||
self.envs.data = OrderedSet() # make the weakset OrderedWeakSet
|
||||
# cache for all records
|
||||
self.cache = Cache()
|
||||
# fields to protect {field: ids}
|
||||
|
||||
Reference in New Issue
Block a user