Commit 3cf75198 by Don Mitchell

Merge pull request #1954 from edx/dhm/loc_mapper_memoize

loc mapper memoize
parents 7bf68907 9ad7a1c1
...@@ -17,6 +17,11 @@ Common: Switch from mitx.db to edx.db for sqlite databases. This will effectivel ...@@ -17,6 +17,11 @@ Common: Switch from mitx.db to edx.db for sqlite databases. This will effectivel
reset state for local instances of the code, unless you manually rename your reset state for local instances of the code, unless you manually rename your
mitx.db file to edx.db. mitx.db file to edx.db.
Common: significant performance improvement for authorization checks and location translations.
Ensure all auth checks, check all possible permutations of the auth key (Instructor dashboard
now shows when it should for all courses in lms).
Made queries for Studio dashboard 2 orders of magnitude faster (and fewer).
Blades: Video Transcripts: Fix clear and download buttons. BLD-438. Blades: Video Transcripts: Fix clear and download buttons. BLD-438.
Common: Switch over from MITX_FEATURES to just FEATURES. To override items in Common: Switch over from MITX_FEATURES to just FEATURES. To override items in
......
...@@ -63,7 +63,7 @@ def get_all_course_role_groupnames(location, role, use_filter=True): ...@@ -63,7 +63,7 @@ def get_all_course_role_groupnames(location, role, use_filter=True):
# filter to the ones which exist # filter to the ones which exist
default = groupnames[0] default = groupnames[0]
if use_filter: if use_filter:
groupnames = [group for group in groupnames if Group.objects.filter(name=group).exists()] groupnames = [group.name for group in Group.objects.filter(name__in=groupnames)]
return groupnames, default return groupnames, default
...@@ -203,12 +203,8 @@ def remove_user_from_course_group(caller, user, location, role): ...@@ -203,12 +203,8 @@ def remove_user_from_course_group(caller, user, location, role):
# see if the user is actually in that role, if not then we don't have to do anything # see if the user is actually in that role, if not then we don't have to do anything
groupnames, _ = get_all_course_role_groupnames(location, role) groupnames, _ = get_all_course_role_groupnames(location, role)
for groupname in groupnames: user.groups.remove(*user.groups.filter(name__in=groupnames))
groups = user.groups.filter(name=groupname) user.save()
if groups:
# will only be one with that name
user.groups.remove(groups[0])
user.save()
def remove_user_from_creator_group(caller, user): def remove_user_from_creator_group(caller, user):
...@@ -243,7 +239,7 @@ def is_user_in_course_group_role(user, location, role, check_staff=True): ...@@ -243,7 +239,7 @@ def is_user_in_course_group_role(user, location, role, check_staff=True):
if check_staff and user.is_staff: if check_staff and user.is_staff:
return True return True
groupnames, _ = get_all_course_role_groupnames(location, role) groupnames, _ = get_all_course_role_groupnames(location, role)
return any(user.groups.filter(name=groupname).exists() for groupname in groupnames) return user.groups.filter(name__in=groupnames).exists()
return False return False
...@@ -266,7 +262,7 @@ def is_user_in_creator_group(user): ...@@ -266,7 +262,7 @@ def is_user_in_creator_group(user):
# Feature flag for using the creator group setting. Will be removed once the feature is complete. # Feature flag for using the creator group setting. Will be removed once the feature is complete.
if settings.FEATURES.get('ENABLE_CREATOR_GROUP', False): if settings.FEATURES.get('ENABLE_CREATOR_GROUP', False):
return user.groups.filter(name=COURSE_CREATOR_GROUP_NAME).count() > 0 return user.groups.filter(name=COURSE_CREATOR_GROUP_NAME).exists()
return True return True
......
...@@ -7,7 +7,6 @@ from textwrap import dedent ...@@ -7,7 +7,6 @@ from textwrap import dedent
from django.test.utils import override_settings from django.test.utils import override_settings
from django.conf import settings from django.conf import settings
from django.core.urlresolvers import reverse
from path import path from path import path
from tempdir import mkdtemp_clean from tempdir import mkdtemp_clean
from fs.osfs import OSFS from fs.osfs import OSFS
...@@ -427,7 +426,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): ...@@ -427,7 +426,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
course = module_store.get_item(course_location) course = module_store.get_item(course_location)
num_tabs = len(course.tabs) num_tabs = len(course.tabs)
last_tab = course.tabs[num_tabs - 1] last_tab = course.tabs[-1]
url_slug = last_tab['url_slug'] url_slug = last_tab['url_slug']
delete_url = self._get_tab_locator(course, last_tab).url_reverse('xblock') delete_url = self._get_tab_locator(course, last_tab).url_reverse('xblock')
...@@ -446,7 +445,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): ...@@ -446,7 +445,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
def _get_tab_locator(self, course, tab): def _get_tab_locator(self, course, tab):
""" Returns the locator for a given tab. """ """ Returns the locator for a given tab. """
tab_location = 'i4x://MITx/999/static_tab/{0}'.format(tab['url_slug']) tab_location = 'i4x://edX/999/static_tab/{0}'.format(tab['url_slug'])
return loc_mapper().translate_location( return loc_mapper().translate_location(
course.location.course_id, Location(tab_location), False, True course.location.course_id, Location(tab_location), False, True
) )
......
...@@ -128,7 +128,8 @@ def course_listing(request): ...@@ -128,7 +128,8 @@ def course_listing(request):
""" """
List all courses available to the logged in user List all courses available to the logged in user
""" """
courses = modulestore('direct').get_items(Location('i4x', None, None, 'course', None)) # there's an index on category which will be used if none of its antecedents are set
courses = modulestore('direct').get_items(Location(None, None, None, 'course', None))
# filter out courses that we don't have access too # filter out courses that we don't have access too
def course_filter(course): def course_filter(course):
......
...@@ -129,7 +129,12 @@ CACHES = { ...@@ -129,7 +129,12 @@ CACHES = {
'LOCATION': '/var/tmp/mongo_metadata_inheritance', 'LOCATION': '/var/tmp/mongo_metadata_inheritance',
'TIMEOUT': 300, 'TIMEOUT': 300,
'KEY_FUNCTION': 'util.memcache.safe_key', 'KEY_FUNCTION': 'util.memcache.safe_key',
} },
'loc_cache': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'edx_location_mem_cache',
},
} }
# Make the keyedcache startup warnings go away # Make the keyedcache startup warnings go away
......
...@@ -138,7 +138,12 @@ CACHES = { ...@@ -138,7 +138,12 @@ CACHES = {
'LOCATION': '/var/tmp/mongo_metadata_inheritance', 'LOCATION': '/var/tmp/mongo_metadata_inheritance',
'TIMEOUT': 300, 'TIMEOUT': 300,
'KEY_FUNCTION': 'util.memcache.safe_key', 'KEY_FUNCTION': 'util.memcache.safe_key',
} },
'loc_cache': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'edx_location_mem_cache',
},
} }
# hide ratelimit warnings while running tests # hide ratelimit warnings while running tests
......
...@@ -129,8 +129,12 @@ def loc_mapper(): ...@@ -129,8 +129,12 @@ def loc_mapper():
global _loc_singleton global _loc_singleton
# pylint: disable=W0212 # pylint: disable=W0212
if _loc_singleton is None: if _loc_singleton is None:
try:
loc_cache = get_cache('loc_cache')
except InvalidCacheBackendError:
loc_cache = get_cache('default')
# instantiate # instantiate
_loc_singleton = LocMapperStore(**settings.DOC_STORE_CONFIG) _loc_singleton = LocMapperStore(loc_cache, **settings.DOC_STORE_CONFIG)
# inject into split mongo modulestore # inject into split mongo modulestore
if 'split' in _MODULESTORES: if 'split' in _MODULESTORES:
_MODULESTORES['split'].loc_mapper = _loc_singleton _MODULESTORES['split'].loc_mapper = _loc_singleton
......
...@@ -43,7 +43,10 @@ class TestMigration(unittest.TestCase): ...@@ -43,7 +43,10 @@ class TestMigration(unittest.TestCase):
def setUp(self): def setUp(self):
super(TestMigration, self).setUp() super(TestMigration, self).setUp()
self.loc_mapper = LocMapperStore(**self.db_config) noop_cache = mock.Mock(spec=['get', 'set_many'])
noop_cache.configure_mock(**{'get.return_value': None})
# pylint: disable=W0142
self.loc_mapper = LocMapperStore(noop_cache, **self.db_config)
self.old_mongo = MongoModuleStore(self.db_config, **self.modulestore_options) self.old_mongo = MongoModuleStore(self.db_config, **self.modulestore_options)
self.draft_mongo = DraftModuleStore(self.db_config, **self.modulestore_options) self.draft_mongo = DraftModuleStore(self.db_config, **self.modulestore_options)
self.split_mongo = SplitMongoModuleStore( self.split_mongo = SplitMongoModuleStore(
......
...@@ -4,7 +4,6 @@ adding users, removing users, and listing members ...@@ -4,7 +4,6 @@ adding users, removing users, and listing members
""" """
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
from functools import partial
from django.contrib.auth.models import User, Group from django.contrib.auth.models import User, Group
......
...@@ -85,7 +85,11 @@ CACHES = { ...@@ -85,7 +85,11 @@ CACHES = {
'LOCATION': '/var/tmp/mongo_metadata_inheritance', 'LOCATION': '/var/tmp/mongo_metadata_inheritance',
'TIMEOUT': 300, 'TIMEOUT': 300,
'KEY_FUNCTION': 'util.memcache.safe_key', 'KEY_FUNCTION': 'util.memcache.safe_key',
} },
'loc_cache': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'edx_location_mem_cache',
},
} }
......
...@@ -165,7 +165,12 @@ CACHES = { ...@@ -165,7 +165,12 @@ CACHES = {
'LOCATION': '/var/tmp/mongo_metadata_inheritance', 'LOCATION': '/var/tmp/mongo_metadata_inheritance',
'TIMEOUT': 300, 'TIMEOUT': 300,
'KEY_FUNCTION': 'util.memcache.safe_key', 'KEY_FUNCTION': 'util.memcache.safe_key',
} },
'loc_cache': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'edx_location_mem_cache',
},
} }
# Dummy secret key for dev # Dummy secret key for dev
......
These are the indexes each mongo db should have in order to perform well.
Each section states the collection name and then the indexes. To create an index,
you'll typically either use the mongohq type web interface or a standard terminal console.
If a terminal, this assumes you've logged in and gotten to the mongo prompt
```
mongo mydatabasename
```
If using the terminal, to add an index to a collection, you'll need to prefix ```ensureIndex``` with
```
db.collection_name
```
as in ```db.location_map.ensureIndex({'course_id': 1}{background: true})```
location_map:
=============
```
ensureIndex({'_id.org': 1, '_id.course': 1})
ensureIndex({'course_id': 1})
```
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