[entity/optimization] Cache rset when entity.related is called with entities=False
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 18 Nov 2016 17:50:56 +0100
changeset 11891 67185e65f020
parent 11888 0849a5eb57b8
child 11892 08cf02efc7ce
[entity/optimization] Cache rset when entity.related is called with entities=False If fail to see why we couldn't cache in this case, while this is important for optimization reason: when doing a single HTTP request, some queries are done two or three times because of predicates / uicfg or alike. Also always store tuple and not list in the cache, because: * else we get some regression * and inconsistent result type (tuple or list) * and it simply feels better to cache an unmutable object.
cubicweb/entity.py
cubicweb/test/unittest_entity.py
cubicweb/web/test/unittest_application.py
--- a/cubicweb/entity.py	Wed Nov 09 16:14:17 2016 +0100
+++ b/cubicweb/entity.py	Fri Nov 18 17:50:56 2016 +0100
@@ -985,11 +985,10 @@
             if not safe:
                 raise
             rset = self._cw.empty_rset()
+        if cacheable:
+            self.cw_set_relation_cache(rtype, role, rset)
         if entities:
-            if cacheable:
-                self.cw_set_relation_cache(rtype, role, rset)
-                return self.related(rtype, role, entities=entities)
-            return list(rset.entities())
+            return tuple(rset.entities())
         else:
             return rset
 
@@ -1251,7 +1250,7 @@
     def cw_set_relation_cache(self, rtype, role, rset):
         """set cached values for the given relation"""
         if rset:
-            related = list(rset.entities(0))
+            related = tuple(rset.entities(0))
             rschema = self._cw.vreg.schema.rschema(rtype)
             if role == 'subject':
                 rcard = rschema.rdef(self.e_schema, related[0].e_schema).cardinality[1]
--- a/cubicweb/test/unittest_entity.py	Wed Nov 09 16:14:17 2016 +0100
+++ b/cubicweb/test/unittest_entity.py	Fri Nov 18 17:50:56 2016 +0100
@@ -182,10 +182,15 @@
                 req.create_entity('Tag', name=tag)
             req.execute('SET X tags Y WHERE X is Tag, Y is Personne')
             self.assertEqual(len(p.related('tags', 'object', limit=2)), 2)
+            self.assertFalse(p.cw_relation_cached('tags', 'object'))
             self.assertEqual(len(p.related('tags', 'object')), 4)
+            self.assertTrue(p.cw_relation_cached('tags', 'object'))
             p.cw_clear_all_caches()
+            self.assertFalse(p.cw_relation_cached('tags', 'object'))
             self.assertEqual(len(p.related('tags', 'object', entities=True, limit=2)), 2)
+            self.assertFalse(p.cw_relation_cached('tags', 'object'))
             self.assertEqual(len(p.related('tags', 'object', entities=True)), 4)
+            self.assertTrue(p.cw_relation_cached('tags', 'object'))
 
     def test_related_targettypes(self):
         with self.admin_access.web_request() as req:
--- a/cubicweb/web/test/unittest_application.py	Wed Nov 09 16:14:17 2016 +0100
+++ b/cubicweb/web/test/unittest_application.py	Fri Nov 18 17:50:56 2016 +0100
@@ -503,7 +503,7 @@
             self.assertTrue(cnx.find('Directory', eid=subd.eid))
             self.assertTrue(cnx.find('Filesystem', eid=fs.eid))
             self.assertEqual(cnx.find('Directory', eid=subd.eid).one().parent,
-                             [topd,])
+                             (topd,))
 
     def test_subject_mixed_composite_subentity_removal_2(self):
         """Editcontroller: detaching several subentities respects each rdef's
@@ -542,7 +542,7 @@
             self.assertTrue(cnx.find('Directory', eid=subd.eid))
             self.assertTrue(cnx.find('Filesystem', eid=fs.eid))
             self.assertEqual(cnx.find('Directory', eid=subd.eid).one().parent,
-                             [topd,])
+                             (topd,))
 
     def test_object_mixed_composite_subentity_removal_2(self):
         """Editcontroller: detaching several subentities respects each rdef's