Commit 1db107c2 by Don Mitchell Committed by Andy Armstrong

Add memoization for has_changes

parent 3afc125e
...@@ -28,6 +28,7 @@ from opaque_keys.edx.keys import UsageKey ...@@ -28,6 +28,7 @@ from opaque_keys.edx.keys import UsageKey
from .access import has_course_access from .access import has_course_access
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from models.settings.course_grading import CourseGradingModel
__all__ = ['OPEN_ENDED_COMPONENT_TYPES', __all__ = ['OPEN_ENDED_COMPONENT_TYPES',
'ADVANCED_COMPONENT_POLICY_KEY', 'ADVANCED_COMPONENT_POLICY_KEY',
......
...@@ -571,7 +571,7 @@ def _get_xblock(usage_key, user): ...@@ -571,7 +571,7 @@ def _get_xblock(usage_key, user):
""" """
store = modulestore() store = modulestore()
try: try:
return store.get_item(usage_key) return store.get_item(usage_key, depth=None)
except ItemNotFoundError: except ItemNotFoundError:
if usage_key.category in CREATE_IF_NOT_FOUND: if usage_key.category in CREATE_IF_NOT_FOUND:
# Create a new one for certain categories only. Used for course info handouts. # Create a new one for certain categories only. Used for course info handouts.
......
"""Tests for items views.""" """Tests for items views."""
import os
import json import json
from datetime import datetime, timedelta from datetime import datetime, timedelta
import ddt import ddt
from unittest import skipUnless
from mock import patch from mock import patch
from pytz import UTC from pytz import UTC
......
...@@ -24,6 +24,7 @@ from opaque_keys import InvalidKeyError ...@@ -24,6 +24,7 @@ from opaque_keys import InvalidKeyError
from opaque_keys.edx.locations import SlashSeparatedCourseKey from opaque_keys.edx.locations import SlashSeparatedCourseKey
from xblock.runtime import Mixologist from xblock.runtime import Mixologist
from xblock.core import XBlock from xblock.core import XBlock
import functools
log = logging.getLogger('edx.modulestore') log = logging.getLogger('edx.modulestore')
...@@ -559,6 +560,36 @@ class ModuleStoreReadBase(ModuleStoreRead): ...@@ -559,6 +560,36 @@ class ModuleStoreReadBase(ModuleStoreRead):
raise ValueError(u"Cannot set default store to type {}".format(store_type)) raise ValueError(u"Cannot set default store to type {}".format(store_type))
yield 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): class ModuleStoreWriteBase(ModuleStoreReadBase, ModuleStoreWrite):
''' '''
......
...@@ -589,13 +589,13 @@ class DraftModuleStore(MongoModuleStore): ...@@ -589,13 +589,13 @@ class DraftModuleStore(MongoModuleStore):
_internal([root_usage.to_deprecated_son() for root_usage in root_usages]) _internal([root_usage.to_deprecated_son() for root_usage in root_usages])
self.collection.remove({'_id': {'$in': to_be_deleted}}, safe=self.collection.safe) self.collection.remove({'_id': {'$in': to_be_deleted}}, safe=self.collection.safe)
@MongoModuleStore.memoize_request_cache
def has_changes(self, xblock): def has_changes(self, xblock):
""" """
Check if the xblock or its children have been changed since the last publish. Check if the xblock or its children have been changed since the last publish.
:param xblock: xblock to check :param xblock: xblock to check
:return: True if the draft and published versions differ :return: True if the draft and published versions differ
""" """
# don't check children if this block has changes (is not public) # don't check children if this block has changes (is not public)
if self.compute_publish_state(xblock) != PublishState.public: if self.compute_publish_state(xblock) != PublishState.public:
return True return True
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment