Commit d328c53d by Don Mitchell

Cached course entry: separate structure from identity

Don't undo inheritance by unsetting course_entry structure
Do finer-grained cache clearing
parent c1789adf
...@@ -27,6 +27,10 @@ class CachingDescriptorSystem(MakoDescriptorSystem): ...@@ -27,6 +27,10 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
modulestore: the module store that can be used to retrieve additional modulestore: the module store that can be used to retrieve additional
modules modules
course_entry: the originally fetched enveloped course_structure w/ branch and course_id info.
Callers to _load_item provide an override but that function ignores the provided structure and
only looks at the branch and course_id
module_data: a dict mapping Location -> json that was cached from the module_data: a dict mapping Location -> json that was cached from the
underlying modulestore underlying modulestore
""" """
...@@ -37,15 +41,13 @@ class CachingDescriptorSystem(MakoDescriptorSystem): ...@@ -37,15 +41,13 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
self.module_data = module_data self.module_data = module_data
# Compute inheritance # Compute inheritance
modulestore.inherit_settings( modulestore.inherit_settings(
course_entry.get('blocks', {}), course_entry['structure'].get('blocks', {}),
course_entry.get('blocks', {}).get(course_entry.get('root')) course_entry['structure'].get('blocks', {}).get(course_entry['structure'].get('root'))
) )
self.default_class = default_class self.default_class = default_class
self.local_modules = {} self.local_modules = {}
def _load_item(self, usage_id, course_entry_override=None): def _load_item(self, usage_id, course_entry_override=None):
# TODO ensure all callers of system.load_item pass just the id
if isinstance(usage_id, BlockUsageLocator) and isinstance(usage_id.usage_id, LocalId): if isinstance(usage_id, BlockUsageLocator) and isinstance(usage_id.usage_id, LocalId):
try: try:
return self.local_modules[usage_id] return self.local_modules[usage_id]
...@@ -66,9 +68,24 @@ class CachingDescriptorSystem(MakoDescriptorSystem): ...@@ -66,9 +68,24 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
) )
return self.xblock_from_json(class_, usage_id, json_data, course_entry_override) return self.xblock_from_json(class_, usage_id, json_data, course_entry_override)
# xblock's runtime does not always pass enough contextual information to figure out
# which named container (course x branch) or which parent is requesting an item. Because split allows
# a many:1 mapping from named containers to structures and because item's identities encode
# context as well as unique identity, this function must sometimes infer whether the access is
# within an unspecified named container. In most cases, course_entry_override will give the
# explicit context; however, runtime.get_block(), e.g., does not. HOWEVER, there are simple heuristics
# which will work 99.999% of the time: a runtime is thread & even context specific. The likelihood that
# the thread is working with more than one named container pointing to the same specific structure is
# low; thus, the course_entry is most likely correct. If the thread is looking at > 1 named container
# pointing to the same structure, the access is likely to be chunky enough that the last known container
# is the intended one when not given a course_entry_override; thus, the caching of the last branch/course_id.
def xblock_from_json(self, class_, usage_id, json_data, course_entry_override=None): def xblock_from_json(self, class_, usage_id, json_data, course_entry_override=None):
if course_entry_override is None: if course_entry_override is None:
course_entry_override = self.course_entry course_entry_override = self.course_entry
else:
# most recent retrieval is most likely the right one for next caller (see comment above fn)
self.course_entry['branch'] = course_entry_override['branch']
self.course_entry['course_id'] = course_entry_override['course_id']
# most likely a lazy loader or the id directly # most likely a lazy loader or the id directly
definition = json_data.get('definition', {}) definition = json_data.get('definition', {})
definition_id = self.modulestore.definition_locator(definition) definition_id = self.modulestore.definition_locator(definition)
...@@ -78,7 +95,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem): ...@@ -78,7 +95,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
usage_id = LocalId() usage_id = LocalId()
block_locator = BlockUsageLocator( block_locator = BlockUsageLocator(
version_guid=course_entry_override['_id'], version_guid=course_entry_override['structure']['_id'],
usage_id=usage_id, usage_id=usage_id,
course_id=course_entry_override.get('course_id'), course_id=course_entry_override.get('course_id'),
branch=course_entry_override.get('branch') branch=course_entry_override.get('branch')
...@@ -103,7 +120,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem): ...@@ -103,7 +120,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
json_data, json_data,
self, self,
BlockUsageLocator( BlockUsageLocator(
version_guid=course_entry_override['_id'], version_guid=course_entry_override['structure']['_id'],
usage_id=usage_id usage_id=usage_id
), ),
error_msg=exc_info_to_str(sys.exc_info()) error_msg=exc_info_to_str(sys.exc_info())
......
import copy import copy
from xblock.fields import Scope from xblock.fields import Scope
from collections import namedtuple from collections import namedtuple
from xblock.runtime import KeyValueStore
from xblock.exceptions import InvalidScopeError from xblock.exceptions import InvalidScopeError
from .definition_lazy_loader import DefinitionLazyLoader from .definition_lazy_loader import DefinitionLazyLoader
from xmodule.modulestore.inheritance import InheritanceKeyValueStore from xmodule.modulestore.inheritance import InheritanceKeyValueStore
......
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