From 9d956563b8f777000a3c6e57d5c7381ffdbac56b Mon Sep 17 00:00:00 2001
From: Julien Muchembled <jm@nexedi.com>
Date: Fri, 13 Aug 2010 12:53:23 +0000
Subject: [PATCH] Fix possible performance issues with transactional_cached
 decorator

git-svn-id: https://svn.erp5.org/repos/public/erp5/sandbox/amount_generator@37798 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 product/ERP5/mixin/composition.py | 8 +++++---
 product/ERP5Type/Cache.py         | 8 +++++++-
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/product/ERP5/mixin/composition.py b/product/ERP5/mixin/composition.py
index 7fe07c8cba..fce74a216c 100644
--- a/product/ERP5/mixin/composition.py
+++ b/product/ERP5/mixin/composition.py
@@ -38,7 +38,7 @@ from Products.ZSQLCatalog.SQLCatalog import Query, ComplexQuery
 
 
 @transactional_cached()
-def _getEffectiveModel(self, start_date=None, stop_date=None):
+def _getEffectiveModel(self, start_date, stop_date):
   """Return the most appropriate model using effective_date, expiration_date
   and version number.
   An effective model is a model which start and stop_date are equal (or
@@ -85,7 +85,7 @@ def _getEffectiveModel(self, start_date=None, stop_date=None):
 # _findPredicateList's cache has at most 1 entry per specialise value found
 # on SO/SOL.
 @transactional_cached()
-def _findPredicateList(container_list, portal_type=None):
+def _findPredicateList(container_list, portal_type):
   predicate_list = []
   reference_dict = {}
   for container in container_list:
@@ -169,7 +169,9 @@ class CompositionMixin:
 
   security.declareProtected(Permissions.AccessContentsInformation,
                             'asComposedDocument')
-  asComposedDocument = transactional_cached()(asComposedDocument)
+  asComposedDocument = transactional_cached(
+    lambda self, portal_type_list=None: (self, portal_type_list)
+    )(asComposedDocument)
 
   # XXX add accessors to get properties from '_effective_model_list' ?
   #     (cf PaySheetModel)
diff --git a/product/ERP5Type/Cache.py b/product/ERP5Type/Cache.py
index 2b9f571712..0937a7af8d 100644
--- a/product/ERP5Type/Cache.py
+++ b/product/ERP5Type/Cache.py
@@ -294,9 +294,15 @@ def caching_instance_method(*args, **kw):
     return lambda *args, **kw: caching_method(*args, **kw)
   return wrapped
 
-def transactional_cached(key_method=lambda *args: args):
+_default_key_method = lambda *args: args
+def transactional_cached(key_method=_default_key_method):
   @simple_decorator
   def decorator(function):
+    # Unfornately, we can only check functions (not other callable like class).
+    assert (key_method is not _default_key_method or
+            not getattr(function, 'func_defaults', None)), (
+      "default 'key_method' of 'transactional_cached' does not work with"
+      " functions having default values for parameters")
     key = repr(function)
     def wrapper(*args, **kw):
       cache = getTransactionalVariable(None).setdefault(key, {})
-- 
2.30.9