From 1db107c2ce7283a2370201313c311fff811eebbb Mon Sep 17 00:00:00 2001 From: Don Mitchell <dmitchell@edx.org> Date: Thu, 28 Aug 2014 14:40:21 -0400 Subject: [PATCH] Add memoization for has_changes --- cms/djangoapps/contentstore/views/component.py | 1 + cms/djangoapps/contentstore/views/item.py | 2 +- cms/djangoapps/contentstore/views/tests/test_item.py | 2 -- common/lib/xmodule/xmodule/modulestore/__init__.py | 31 +++++++++++++++++++++++++++++++ common/lib/xmodule/xmodule/modulestore/mongo/draft.py | 2 +- 5 files changed, 34 insertions(+), 4 deletions(-) diff --git a/cms/djangoapps/contentstore/views/component.py b/cms/djangoapps/contentstore/views/component.py index b050ecb..b957d35 100644 --- a/cms/djangoapps/contentstore/views/component.py +++ b/cms/djangoapps/contentstore/views/component.py @@ -28,6 +28,7 @@ from opaque_keys.edx.keys import UsageKey from .access import has_course_access from django.utils.translation import ugettext as _ +from models.settings.course_grading import CourseGradingModel __all__ = ['OPEN_ENDED_COMPONENT_TYPES', 'ADVANCED_COMPONENT_POLICY_KEY', diff --git a/cms/djangoapps/contentstore/views/item.py b/cms/djangoapps/contentstore/views/item.py index 381f016..9a5511c 100644 --- a/cms/djangoapps/contentstore/views/item.py +++ b/cms/djangoapps/contentstore/views/item.py @@ -571,7 +571,7 @@ def _get_xblock(usage_key, user): """ store = modulestore() try: - return store.get_item(usage_key) + return store.get_item(usage_key, depth=None) except ItemNotFoundError: if usage_key.category in CREATE_IF_NOT_FOUND: # Create a new one for certain categories only. Used for course info handouts. diff --git a/cms/djangoapps/contentstore/views/tests/test_item.py b/cms/djangoapps/contentstore/views/tests/test_item.py index bffbfda..a7fac49 100644 --- a/cms/djangoapps/contentstore/views/tests/test_item.py +++ b/cms/djangoapps/contentstore/views/tests/test_item.py @@ -1,9 +1,7 @@ """Tests for items views.""" -import os import json from datetime import datetime, timedelta import ddt -from unittest import skipUnless from mock import patch from pytz import UTC diff --git a/common/lib/xmodule/xmodule/modulestore/__init__.py b/common/lib/xmodule/xmodule/modulestore/__init__.py index df20eaf..95957b9 100644 --- a/common/lib/xmodule/xmodule/modulestore/__init__.py +++ b/common/lib/xmodule/xmodule/modulestore/__init__.py @@ -24,6 +24,7 @@ from opaque_keys import InvalidKeyError from opaque_keys.edx.locations import SlashSeparatedCourseKey from xblock.runtime import Mixologist from xblock.core import XBlock +import functools log = logging.getLogger('edx.modulestore') @@ -559,6 +560,36 @@ class ModuleStoreReadBase(ModuleStoreRead): raise ValueError(u"Cannot set default store to type {}".format(store_type)) yield + @staticmethod + def memoize_request_cache(func): + """ + Memoize a function call results on the request_cache if there's one. Creates the cache key by + joining the unicode of all the args with &; so, if your arg may use the default &, it may + have false hits + """ + @functools.wraps(func) + def wrapper(self, *args, **kwargs): + if self.request_cache: + cache_key = '&'.join([hashvalue(arg) for arg in args]) + if cache_key in self.request_cache.data.setdefault(func.__name__, {}): + return self.request_cache.data[func.__name__][cache_key] + + result = func(self, *args, **kwargs) + + self.request_cache.data[func.__name__][cache_key] = result + return result + else: + return func(self, *args, **kwargs) + return wrapper + +def hashvalue(arg): + """ + If arg is an xblock, use its location. otherwise just turn it into a string + """ + if isinstance(arg, XBlock): + return unicode(arg.location) + else: + return unicode(arg) class ModuleStoreWriteBase(ModuleStoreReadBase, ModuleStoreWrite): ''' diff --git a/common/lib/xmodule/xmodule/modulestore/mongo/draft.py b/common/lib/xmodule/xmodule/modulestore/mongo/draft.py index 6aaa0e1..db84c48 100644 --- a/common/lib/xmodule/xmodule/modulestore/mongo/draft.py +++ b/common/lib/xmodule/xmodule/modulestore/mongo/draft.py @@ -589,13 +589,13 @@ class DraftModuleStore(MongoModuleStore): _internal([root_usage.to_deprecated_son() for root_usage in root_usages]) self.collection.remove({'_id': {'$in': to_be_deleted}}, safe=self.collection.safe) + @MongoModuleStore.memoize_request_cache def has_changes(self, xblock): """ Check if the xblock or its children have been changed since the last publish. :param xblock: xblock to check :return: True if the draft and published versions differ """ - # don't check children if this block has changes (is not public) if self.compute_publish_state(xblock) != PublishState.public: return True -- libgit2 0.26.0