Merge pull request #18879 from edx/revert-revert-18861-robrap/ARCH-223-replace-request-cache

ARCH-223: Revert the revert of Replace Request Cache
This commit is contained in:
Robert Raposa
2018-09-08 16:30:37 -04:00
committed by GitHub
38 changed files with 108 additions and 185 deletions

View File

@@ -5,9 +5,9 @@ from contextlib import contextmanager
import ddt
from django.test import TestCase
from edx_django_utils.cache import RequestCache
from opaque_keys.edx.locator import CourseLocator
from openedx.core.djangoapps.request_cache.middleware import RequestCache
from xblock_config.models import CourseEditLTIFieldsEnabledFlag
@@ -20,7 +20,7 @@ def lti_consumer_fields_editing_flag(course_id, enabled_for_course=False):
course_id (CourseLocator): course locator to control this feature for.
enabled_for_course (bool): whether feature is enabled for 'course_id'
"""
RequestCache.clear_request_cache()
RequestCache.clear_all_namespaces()
CourseEditLTIFieldsEnabledFlag.objects.create(course_id=course_id, enabled=enabled_for_course)
yield

View File

@@ -472,9 +472,6 @@ XQUEUE_INTERFACE = {
MIDDLEWARE_CLASSES = [
'crum.CurrentRequestUserMiddleware',
# Deprecated, but well entrenched RequestCache
'openedx.core.djangoapps.request_cache.middleware.RequestCache',
# A newer and safer request cache.
'edx_django_utils.cache.middleware.RequestCacheMiddleware',
'edx_django_utils.monitoring.middleware.MonitoringMemoryMiddleware',

View File

@@ -13,11 +13,12 @@ from django.db.models import Q
from django.dispatch import receiver
from django.utils.timezone import now
from django.utils.translation import ugettext_lazy as _
from edx_django_utils.cache import RequestCache
from opaque_keys.edx.keys import CourseKey
from opaque_keys.edx.django.models import CourseKeyField
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from openedx.core.djangoapps.request_cache.middleware import RequestCache, ns_request_cached
from openedx.core.djangoapps.request_cache.middleware import ns_request_cached
Mode = namedtuple('Mode',
[
@@ -727,7 +728,7 @@ class CourseMode(models.Model):
@receiver(models.signals.post_delete, sender=CourseMode)
def invalidate_course_mode_cache(sender, **kwargs): # pylint: disable=unused-argument
"""Invalidate the cache of course modes. """
RequestCache.clear_request_cache(name=CourseMode.CACHE_NAMESPACE)
RequestCache(namespace=CourseMode.CACHE_NAMESPACE).clear()
def get_cosmetic_verified_display_price(course):

View File

@@ -7,12 +7,12 @@ from django.http import HttpResponse
from django.test import TestCase
from django.test.client import RequestFactory
from django.test.utils import override_settings
from edx_django_utils.cache import RequestCache
from mock import Mock, patch
from edxmako import LOOKUP, add_lookup
from edxmako.request_context import get_template_request_context
from edxmako.shortcuts import is_any_marketing_link_set, is_marketing_link_set, marketing_link, render_to_string
from openedx.core.djangoapps.request_cache.middleware import RequestCache
from student.tests.factories import UserFactory
from util.testing import UrlResetMixin
@@ -89,7 +89,7 @@ class MakoRequestContextTest(TestCase):
self.request.user = self.user
self.response = Mock(spec=HttpResponse)
self.addCleanup(RequestCache.clear_request_cache)
self.addCleanup(RequestCache.clear_all_namespaces)
def test_with_current_request(self):
"""
@@ -128,7 +128,7 @@ class MakoRequestContextTest(TestCase):
self.assertIsNotNone(get_template_request_context())
mock_get_current_request.assert_not_called()
RequestCache.clear_request_cache()
RequestCache.clear_all_namespaces()
with patch('edxmako.request_context.get_current_request', return_value=None):
# requestcontext should be None, because the cache isn't filled

View File

@@ -23,8 +23,8 @@ from django.core.cache import caches, InvalidCacheBackendError
import django.dispatch
import django.utils
from django.utils.translation import get_language, to_locale
from edx_django_utils.cache import DEFAULT_REQUEST_CACHE
from openedx.core.djangoapps.request_cache.middleware import RequestCache
from xmodule.contentstore.django import contentstore
from xmodule.modulestore.draft_and_published import BranchSettingMixin
from xmodule.modulestore.mixed import MixedModuleStore
@@ -249,7 +249,7 @@ def create_modulestore_instance(
if key in _options and isinstance(_options[key], basestring):
_options[key] = load_function(_options[key])
request_cache = RequestCache.get_request_cache()
request_cache = DEFAULT_REQUEST_CACHE
try:
metadata_inheritance_cache = caches['mongo_metadata_inheritance']
@@ -278,14 +278,9 @@ def create_modulestore_instance(
if disabled_xblocks is None:
return []
if request_cache:
if 'disabled_xblock_types' not in request_cache.data:
request_cache.data['disabled_xblock_types'] = [block.name for block in disabled_xblocks()]
return request_cache.data['disabled_xblock_types']
else:
disabled_xblock_types = [block.name for block in disabled_xblocks()]
return disabled_xblock_types
if 'disabled_xblock_types' not in request_cache.data:
request_cache.data['disabled_xblock_types'] = [block.name for block in disabled_xblocks()]
return request_cache.data['disabled_xblock_types']
return class_(
contentstore=content_store,

View File

@@ -16,10 +16,10 @@ from django.conf import settings
from django.core.cache import caches
from django.test.client import RequestFactory
from django.test.utils import override_settings
from edx_django_utils.cache import RequestCache
from lms.djangoapps.ccx.tests.factories import CcxFactory
from opaque_keys.edx.keys import CourseKey
from openedx.core.djangoapps.content.block_structure.api import get_course_in_cache
from openedx.core.djangoapps.request_cache.middleware import RequestCache
from openedx.core.djangoapps.waffle_utils.testutils import WAFFLE_TABLES
from pytz import UTC
from student.models import CourseEnrollment
@@ -176,7 +176,7 @@ class FieldOverridePerformanceTestCase(FieldOverrideTestMixin, ProceduralCourseT
get_course_in_cache(course_key)
# We clear the request cache to simulate a new request in the LMS.
RequestCache.clear_request_cache()
RequestCache.clear_all_namespaces()
# Reset the list of provider classes, so that our django settings changes
# can actually take affect.

View File

@@ -8,6 +8,7 @@ import mock
import pytz
from ccx_keys.locator import CCXLocator
from django.test.utils import override_settings
from edx_django_utils.cache import RequestCache
from courseware.courses import get_course_by_id
from courseware.field_overrides import OverrideFieldData
@@ -16,7 +17,6 @@ from lms.djangoapps.ccx.models import CustomCourseForEdX
from lms.djangoapps.ccx.overrides import override_field_for_ccx
from lms.djangoapps.ccx.tests.utils import flatten, iter_blocks
from lms.djangoapps.courseware.tests.test_field_overrides import inject_field_overrides
from openedx.core.djangoapps.request_cache.middleware import RequestCache
from student.tests.factories import AdminFactory
from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, SharedModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
@@ -74,7 +74,7 @@ class TestFieldOverrides(FieldOverrideTestMixin, SharedModuleStoreTestCase):
get_ccx.return_value = ccx
self.addCleanup(patch.stop)
self.addCleanup(RequestCache.clear_request_cache)
self.addCleanup(RequestCache.clear_all_namespaces)
inject_field_overrides(iter_blocks(ccx.course), self.course, AdminFactory.create())

View File

@@ -26,6 +26,7 @@ from courseware.testutils import FieldOverrideTestMixin
from django_comment_client.utils import has_forum_access
from django_comment_common.models import FORUM_ROLE_ADMINISTRATOR
from django_comment_common.utils import are_permissions_roles_seeded
from edx_django_utils.cache import RequestCache
from edxmako.shortcuts import render_to_response
from lms.djangoapps.ccx.models import CustomCourseForEdX
from lms.djangoapps.ccx.overrides import get_override_for_ccx, override_field_for_ccx
@@ -36,7 +37,6 @@ from lms.djangoapps.ccx.views import get_date
from lms.djangoapps.grades.tasks import compute_all_grades_for_course
from lms.djangoapps.instructor.access import allow_access, list_with_level
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from openedx.core.djangoapps.request_cache.middleware import RequestCache
from openedx.core.lib.tests import attr
from student.models import CourseEnrollment, CourseEnrollmentAllowed
from student.roles import CourseCcxCoachRole, CourseInstructorRole, CourseStaffRole
@@ -1051,7 +1051,7 @@ class TestCCXGrades(FieldOverrideTestMixin, SharedModuleStoreTestCase, LoginEnro
CourseOverview.load_from_module_store(self.course.id)
setup_students_and_grades(self)
self.client.login(username=coach.username, password="test")
self.addCleanup(RequestCache.clear_request_cache)
self.addCleanup(RequestCache.clear_all_namespaces)
from xmodule.modulestore.django import SignalHandler
# using CCX object as sender here.
@@ -1064,7 +1064,7 @@ class TestCCXGrades(FieldOverrideTestMixin, SharedModuleStoreTestCase, LoginEnro
@patch('lms.djangoapps.instructor.views.gradebook_api.MAX_STUDENTS_PER_PAGE_GRADE_BOOK', 1)
def test_gradebook(self):
self.course.enable_ccx = True
RequestCache.clear_request_cache()
RequestCache.clear_all_namespaces()
url = reverse(
'ccx_gradebook',
@@ -1081,7 +1081,7 @@ class TestCCXGrades(FieldOverrideTestMixin, SharedModuleStoreTestCase, LoginEnro
def test_grades_csv(self):
self.course.enable_ccx = True
RequestCache.clear_request_cache()
RequestCache.clear_all_namespaces()
url = reverse(
'ccx_grades_csv',

View File

@@ -5,11 +5,11 @@ from __future__ import unicode_literals
import logging
from crum import get_current_request
from django.contrib.auth.models import AnonymousUser
from django.dispatch import receiver
from openedx.core.djangoapps.commerce.utils import is_commerce_service_configured
from openedx.core.djangoapps.request_cache.middleware import RequestCache
from student.signals import REFUND_ORDER
from .utils import refund_seat
@@ -56,5 +56,5 @@ def get_request_user():
If the requester of an unenrollment is not the same person as the student
being unenrolled, we authenticate to the commerce service as the requester.
"""
request = RequestCache.get_current_request()
request = get_current_request()
return getattr(request, 'user', None)

View File

@@ -73,7 +73,7 @@ def has_course_goal_permission(request, course_id, user_access):
can use this feature.
"""
course_key = CourseKey.from_string(course_id)
has_verified_mode = CourseMode.has_verified_mode(CourseMode.modes_for_course_dict(unicode(course_id)))
has_verified_mode = CourseMode.has_verified_mode(CourseMode.modes_for_course_dict(course_key))
return user_access['is_enrolled'] and has_verified_mode and ENABLE_COURSE_GOALS.is_enabled(course_key) \
and settings.FEATURES.get('ENABLE_COURSE_GOALS')

View File

@@ -4,10 +4,10 @@ Platform plugins to support a verified upgrade tool.
import datetime
import pytz
from crum import get_current_request
from django.utils.translation import ugettext as _
from course_modes.models import CourseMode
from openedx.core.djangoapps.request_cache import get_request
from openedx.features.course_experience.course_tools import CourseTool
from student.models import CourseEnrollment
from courseware.date_summary import verified_upgrade_deadline_link
@@ -69,5 +69,5 @@ class VerifiedUpgradeTool(CourseTool):
"""
Returns the URL for this tool for the specified course key.
"""
request = get_request()
request = get_current_request()
return verified_upgrade_deadline_link(request.user, course_id=course_key)

View File

@@ -19,9 +19,9 @@ from abc import ABCMeta, abstractmethod
from contextlib import contextmanager
from django.conf import settings
from edx_django_utils.cache import DEFAULT_REQUEST_CACHE
from xblock.field_data import FieldData
from openedx.core.djangoapps.request_cache.middleware import RequestCache
from xmodule.modulestore.inheritance import InheritanceMixin
NOTSET = object()
@@ -180,7 +180,7 @@ class OverrideFieldData(FieldData):
Arguments:
course: The course XBlock
"""
request_cache = RequestCache.get_request_cache()
request_cache = DEFAULT_REQUEST_CACHE
if course is None:
cache_key = ENABLED_OVERRIDE_PROVIDERS_KEY.format(course_id='None')
else:
@@ -294,7 +294,7 @@ class OverrideModulestoreFieldData(OverrideFieldData):
course_id = unicode(block.location.course_key)
cache_key = ENABLED_MODULESTORE_OVERRIDE_PROVIDERS_KEY.format(course_id=course_id)
request_cache = RequestCache.get_request_cache()
request_cache = DEFAULT_REQUEST_CACHE
enabled_providers = request_cache.data.get(cache_key)
if enabled_providers is None:

View File

@@ -2414,7 +2414,7 @@ class TestDisabledXBlockTypes(ModuleStoreTestCase):
self._verify_descriptor('problem', course, 'CapaDescriptorWithMixins', item_usage_id)
# Now simulate a new request cache.
self.store.request_cache.data = {}
self.store.request_cache.data.clear()
self._verify_descriptor('problem', course, 'RawDescriptorWithMixins', item_usage_id)
def _verify_descriptor(self, category, course, descriptor, item_id=None):

View File

@@ -8,6 +8,7 @@ from django.http import Http404
from django.test.client import Client, RequestFactory
from django.test.utils import override_settings
from django.utils import translation
from edx_django_utils.cache import RequestCache
from mock import ANY, Mock, call, patch
from six import text_type
@@ -43,7 +44,6 @@ from lms.lib.comment_client.utils import CommentClientPaginatedResult
from openedx.core.djangoapps.course_groups.models import CourseUserGroup
from openedx.core.djangoapps.course_groups.tests.helpers import config_course_cohorts
from openedx.core.djangoapps.course_groups.tests.test_views import CohortViewsTestCase
from openedx.core.djangoapps.request_cache.middleware import RequestCache
from openedx.core.djangoapps.util.testing import ContentGroupTestCase
from openedx.core.djangoapps.waffle_utils.testutils import WAFFLE_TABLES
from openedx.features.enterprise_support.tests.mixins.enterprise import EnterpriseTestConsentRequired
@@ -1968,7 +1968,7 @@ class CourseDiscussionsHandlerTestCase(DividedDiscussionsTestCase):
expected_response = self.get_expected_response()
self.assertEqual(response, expected_response)
RequestCache.clear_request_cache()
RequestCache.clear_all_namespaces()
now = datetime.now()
# inline discussion
ItemFactory.create(

View File

@@ -5,18 +5,19 @@ Module for checking permissions with the comment_client backend
import logging
from types import NoneType
from edx_django_utils.cache import DEFAULT_REQUEST_CACHE
from opaque_keys.edx.keys import CourseKey
from django_comment_common.models import CourseDiscussionSettings, all_permissions_for_user_in_course
from django_comment_common.utils import get_course_discussion_settings
from lms.djangoapps.teams.models import CourseTeam
from lms.lib.comment_client import Thread
from openedx.core.djangoapps.request_cache.middleware import RequestCache, request_cached
from openedx.core.djangoapps.request_cache.middleware import request_cached
def has_permission(user, permission, course_id=None):
assert isinstance(course_id, (NoneType, CourseKey))
request_cache_dict = RequestCache.get_request_cache().data
request_cache_dict = DEFAULT_REQUEST_CACHE.data
cache_key = "django_comment_client.permissions.has_permission.all_permissions.{}.{}".format(
user.id, course_id
)
@@ -65,7 +66,7 @@ def _check_condition(user, condition, content):
if not content:
return False
try:
request_cache_dict = RequestCache.get_request_cache().data
request_cache_dict = DEFAULT_REQUEST_CACHE.data
if content["type"] == "thread":
cache_key = "django_comment_client.permissions._check_condition.check_question_author.{}.{}".format(
user.id, content['id']
@@ -98,7 +99,7 @@ def _check_condition(user, condition, content):
return False
try:
commentable_id = content['commentable_id']
request_cache_dict = RequestCache.get_request_cache().data
request_cache_dict = DEFAULT_REQUEST_CACHE.data
cache_key = u"django_comment_client.check_team_member.{}.{}".format(user.id, commentable_id)
if cache_key in request_cache_dict:
return request_cache_dict[cache_key]

View File

@@ -7,6 +7,7 @@ import mock
from django.urls import reverse
from django.test import RequestFactory, TestCase
from edx_django_utils.cache import RequestCache
from mock import Mock, patch
from pytz import UTC
from six import text_type
@@ -36,7 +37,6 @@ from lms.lib.comment_client.utils import CommentClientMaintenanceError, perform_
from openedx.core.djangoapps.course_groups import cohorts
from openedx.core.djangoapps.course_groups.cohorts import set_course_cohorted
from openedx.core.djangoapps.course_groups.tests.helpers import CohortFactory, config_course_cohorts
from openedx.core.djangoapps.request_cache.middleware import RequestCache
from openedx.core.djangoapps.util.testing import ContentGroupTestCase
from openedx.core.lib.tests import attr
from student.roles import CourseStaffRole
@@ -217,7 +217,7 @@ class CoursewareContextTestCase(ModuleStoreTestCase):
self.assertEqual(len(utils.get_accessible_discussion_xblocks(course, self.user)), 1)
# The above call is request cached, so we need to clear it for this test.
RequestCache.clear_request_cache()
RequestCache.clear_all_namespaces()
# Add an orphan discussion xblock to that course
orphan = course.id.make_usage_key('discussion', 'orphan_discussion')
self.store.create_item(self.user.id, orphan.course_key, orphan.block_type, block_id=orphan.block_id)
@@ -261,7 +261,7 @@ class CachedDiscussionIdMapTestCase(ModuleStoreTestCase):
discussion_target='Beta Testing',
visible_to_staff_only=True
)
RequestCache.clear_request_cache() # clear the cache before the last course publish
RequestCache.clear_all_namespaces() # clear the cache before the last course publish
self.bad_discussion = ItemFactory.create(
parent_location=self.course.location,
category='discussion',
@@ -1780,7 +1780,7 @@ class GroupModeratorPermissionsTestCase(ModuleStoreTestCase):
'can_vote': True,
'can_report': True
})
RequestCache.clear_request_cache()
RequestCache.clear_all_namespaces()
set_discussion_division_settings(self.course.id, division_scheme=CourseDiscussionSettings.ENROLLMENT_TRACK)
content = {'user_id': self.verified_user.id, 'type': 'thread', 'username': self.verified_user.username}

View File

@@ -4,6 +4,7 @@ Integration tests for gated content.
import ddt
from crum import set_current_request
from completion import waffle as completion_waffle
from edx_django_utils.cache import RequestCache
from milestones import api as milestones_api
from milestones.tests.utils import MilestonesTestCaseMixin
@@ -12,7 +13,6 @@ from lms.djangoapps.grades.course_grade_factory import CourseGradeFactory
from lms.djangoapps.grades.tests.utils import answer_problem
from openedx.core.djangolib.testing.utils import get_mock_request
from openedx.core.lib.gating import api as gating_api
from openedx.core.djangoapps.request_cache.middleware import RequestCache
from student.tests.factories import UserFactory
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
@@ -141,7 +141,7 @@ class TestGatedContent(MilestonesTestCaseMixin, SharedModuleStoreTestCase):
Verifies access to gated content for the given user is as expected.
"""
# clear the request cache to flush any cached access results
RequestCache.clear_request_cache()
RequestCache.clear_all_namespaces()
# access to gating content (seq1) remains constant
self.assertTrue(bool(has_access(user, 'load', self.seq1, self.course.id)))

View File

@@ -3,9 +3,9 @@ Provides helper functions for tests that want
to configure flags related to persistent grading.
"""
from contextlib import contextmanager
from edx_django_utils.cache import RequestCache
from lms.djangoapps.grades.config.models import CoursePersistentGradesFlag, PersistentGradesEnabledFlag
from openedx.core.djangoapps.request_cache.middleware import RequestCache
@contextmanager
@@ -20,7 +20,7 @@ def persistent_grades_feature_flags(
as they need to set the global setting and the course-specific
setting for a single course.
"""
RequestCache.clear_request_cache()
RequestCache.clear_all_namespaces()
PersistentGradesEnabledFlag.objects.create(enabled=global_flag, enabled_for_all_courses=enabled_for_all_courses)
if course_id:
CoursePersistentGradesFlag.objects.create(course_id=course_id, enabled=enabled_for_course)

View File

@@ -24,6 +24,7 @@ from courseware.tests.factories import InstructorFactory
from django.conf import settings
from django.urls import reverse
from django.test.utils import override_settings
from edx_django_utils.cache import RequestCache
from freezegun import freeze_time
from instructor_analytics.basic import UNAVAILABLE, list_problem_responses
from mock import MagicMock, Mock, patch, ANY
@@ -85,7 +86,6 @@ from lms.djangoapps.verify_student.tests.factories import SoftwareSecurePhotoVer
from openedx.core.djangoapps.course_groups.models import CohortMembership, CourseUserGroupPartitionGroup
from openedx.core.djangoapps.course_groups.tests.helpers import CohortFactory
from openedx.core.djangoapps.credit.tests.factories import CreditCourseFactory
from openedx.core.djangoapps.request_cache.middleware import RequestCache
from openedx.core.djangoapps.user_api.partition_schemes import RandomUserPartitionScheme
from openedx.core.djangoapps.util.testing import ContentGroupTestCase, TestConditionalContent
from ..models import ReportStore
@@ -411,7 +411,7 @@ class TestInstructorGradeReport(InstructorGradeReportTestCase):
CourseEnrollment.enroll(user, course.id, mode='verified')
SoftwareSecurePhotoVerificationFactory.create(user=user, status='approved')
RequestCache.clear_request_cache()
RequestCache.clear_all_namespaces()
expected_query_count = 43
with patch('lms.djangoapps.instructor_task.tasks_helper.runner._get_current_task'):

View File

@@ -4,6 +4,7 @@ Module implementing `xblock.runtime.Runtime` functionality for the LMS
from completion.services import CompletionService
from django.conf import settings
from django.urls import reverse
from edx_django_utils.cache import DEFAULT_REQUEST_CACHE
import xblock.reference.plugins
from badges.service import BadgingService
@@ -12,7 +13,6 @@ from lms.djangoapps.lms_xblock.models import XBlockAsidesConfig
from openedx.core.djangoapps.user_api.course_tag import api as user_course_tag_api
from openedx.core.lib.url_utils import quote_slashes
from openedx.core.lib.xblock_utils import xblock_local_resource_url
from openedx.core.djangoapps.request_cache.middleware import RequestCache
from xmodule.library_tools import LibraryToolsService
from xmodule.modulestore.django import ModuleI18nService, modulestore
from xmodule.partitions.partitions_service import PartitionService
@@ -133,7 +133,7 @@ class LmsModuleSystem(ModuleSystem): # pylint: disable=abstract-method
ModuleSystem specialized to the LMS
"""
def __init__(self, **kwargs):
request_cache_dict = RequestCache.get_request_cache().data
request_cache_dict = DEFAULT_REQUEST_CACHE.data
store = modulestore()
services = kwargs.setdefault('services', {})

View File

@@ -1216,9 +1216,6 @@ CREDIT_NOTIFICATION_CACHE_TIMEOUT = 5 * 60 * 60
MIDDLEWARE_CLASSES = [
'crum.CurrentRequestUserMiddleware',
# Deprecated, but well entrenched RequestCache
'openedx.core.djangoapps.request_cache.middleware.RequestCache',
# A newer and safer request cache.
'edx_django_utils.cache.middleware.RequestCacheMiddleware',
'edx_django_utils.monitoring.middleware.MonitoringCustomMetricsMiddleware',
@@ -3259,8 +3256,6 @@ AUDIT_CERT_CUTOFF_DATE = None
CREDENTIALS_SERVICE_USERNAME = 'credentials_service_user'
CREDENTIALS_GENERATION_ROUTING_KEY = HIGH_PRIORITY_QUEUE
WIKI_REQUEST_CACHE_MIDDLEWARE_CLASS = "openedx.core.djangoapps.request_cache.middleware.RequestCache"
# Settings for Comprehensive Theming app
# See https://github.com/edx/edx-django-sites-extensions for more info

View File

@@ -4,8 +4,8 @@ Bookmarks service.
import logging
from django.core.exceptions import ObjectDoesNotExist
from edx_django_utils.cache import DEFAULT_REQUEST_CACHE
from openedx.core.djangoapps.request_cache.middleware import RequestCache
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.exceptions import ItemNotFoundError
@@ -46,12 +46,12 @@ class BookmarksService(object):
return []
cache_key = CACHE_KEY_TEMPLATE.format(self._user.id, course_key)
bookmarks_cache = RequestCache.get_request_cache().data.get(cache_key, None)
bookmarks_cache = DEFAULT_REQUEST_CACHE.data.get(cache_key, None)
if bookmarks_cache is None and fetch is True:
bookmarks_cache = api.get_bookmarks(
self._user, course_key=course_key, fields=DEFAULT_FIELDS
)
RequestCache.get_request_cache().data[cache_key] = bookmarks_cache
DEFAULT_REQUEST_CACHE.data[cache_key] = bookmarks_cache
return bookmarks_cache

View File

@@ -9,10 +9,10 @@ import logging
from celery import task
from django.conf import settings
from django.utils import six, timezone
from edx_django_utils.cache import RequestCache
from opaque_keys.edx.keys import CourseKey
from py2neo import Graph, Node, Relationship, authenticate, NodeSelector
from py2neo.compat import integer, string, unicode as neo4j_unicode
from openedx.core.djangoapps.request_cache.middleware import RequestCache
log = logging.getLogger(__name__)
@@ -348,7 +348,7 @@ class ModuleStoreSerializer(object):
for index, course_key in enumerate(self.course_keys):
# first, clear the request cache to prevent memory leaks
RequestCache.clear_request_cache()
RequestCache.clear_all_namespaces()
log.info(
"Now submitting %s for export to neo4j: course %d of %d total courses",

View File

@@ -19,12 +19,12 @@ from django.db import IntegrityError, models, transaction
from django.dispatch import receiver
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy
from edx_django_utils.cache import RequestCache
from jsonfield.fields import JSONField
from model_utils.models import TimeStampedModel
from opaque_keys.edx.django.models import CourseKeyField
from openedx.core.djangoapps.request_cache.middleware import RequestCache, ns_request_cached
from openedx.core.djangoapps.request_cache.middleware import ns_request_cached
CREDIT_PROVIDER_ID_REGEX = r"[a-z,A-Z,0-9,\-]+"
log = logging.getLogger(__name__)
@@ -401,7 +401,7 @@ class CreditRequirement(TimeStampedModel):
@receiver(models.signals.post_delete, sender=CreditRequirement)
def invalidate_credit_requirement_cache(sender, **kwargs): # pylint: disable=unused-argument
"""Invalidate the cache of credit requirements. """
RequestCache.clear_request_cache(name=CreditRequirement.CACHE_NAMESPACE)
RequestCache(namespace=CreditRequirement.CACHE_NAMESPACE).clear()
class CreditRequirementStatus(TimeStampedModel):

View File

@@ -12,6 +12,7 @@ from celery.signals import task_postrun
import crum
from django.conf import settings
from django.test.client import RequestFactory
from edx_django_utils.cache import RequestCache
from openedx.core.djangoapps.request_cache import middleware
@@ -26,7 +27,7 @@ def clear_request_cache(**kwargs): # pylint: disable=unused-argument
prevent memory leaks.
"""
if getattr(settings, 'CLEAR_REQUEST_CACHE_ON_TASK_COMPLETION', True):
middleware.RequestCache.clear_request_cache()
RequestCache.clear_all_namespaces()
def get_cache(name):
@@ -38,7 +39,8 @@ def get_cache(name):
Returns: dict
"""
return middleware.RequestCache.get_request_cache(name)
assert name is not None
return RequestCache(name).data
def clear_cache(name):
@@ -48,16 +50,7 @@ def clear_cache(name):
Arguments:
name (str): The name of the request cache to clear
"""
return middleware.RequestCache.clear_request_cache(name)
def get_request():
"""
Return the current request.
Deprecated: Please use crum to retrieve current requests.
"""
return crum.get_current_request()
RequestCache(name).clear()
def get_request_or_stub():

View File

@@ -1,71 +1,12 @@
"""
An implementation of a RequestCache. This cache is reset at the beginning
and end of every request.
"""
# pylint: disable=unused-argument
import threading
The middleware for the edx-platform version of the RequestCache has been
removed in favor of the RequestCache found in edx-django-utils.
import crum
TODO: This file still contains request cache related decorators that
should be moved out of this middleware file.
"""
from django.utils.encoding import force_text
class _RequestCache(threading.local):
"""
A thread-local for storing the per-request cache.
"""
def __init__(self):
super(_RequestCache, self).__init__()
self.data = {}
REQUEST_CACHE = _RequestCache()
class RequestCache(object):
"""
DEPRECATED Request Cache Middleware. Will be removed very shortly.
"""
@classmethod
def get_request_cache(cls, name=None):
"""
This method is deprecated. Please use :func:`request_cache.get_cache`.
"""
if name is None:
return REQUEST_CACHE
else:
return REQUEST_CACHE.data.setdefault(name, {})
@classmethod
def get_current_request(cls):
"""
This method is deprecated. Please use :func:`request_cache.get_request`.
"""
return crum.get_current_request()
@classmethod
def clear_request_cache(cls, name=None):
"""
Empty the request cache.
"""
if name is None:
REQUEST_CACHE.data = {}
elif REQUEST_CACHE.data.get(name):
REQUEST_CACHE.data[name] = {}
def process_request(self, request):
self.clear_request_cache()
return None
def process_response(self, request, response):
self.clear_request_cache()
return response
def process_exception(self, request, exception):
"""
Clear the RequestCache after a failed request.
"""
self.clear_request_cache()
return None
from edx_django_utils.cache import RequestCache
def request_cached(f):
@@ -98,7 +39,8 @@ def ns_request_cached(namespace=None):
Arguments:
namespace (string): An optional namespace to use for the cache. Useful if the caller wants to manage
their own sub-cache by, for example, calling RequestCache.clear_request_cache for their own namespace.
their own sub-cache by, for example, calling RequestCache(namespace=NAMESPACE).clear() for their own
namespace.
"""
def outer_wrapper(f):
"""
@@ -113,22 +55,22 @@ def ns_request_cached(namespace=None):
"""
# Check to see if we have a result in cache. If not, invoke our wrapped
# function. Cache and return the result to the caller.
rcache = RequestCache.get_request_cache(namespace)
rcache = rcache.data if namespace is None else rcache
cache_key = func_call_cache_key(f, *args, **kwargs)
request_cache = RequestCache(namespace)
cache_key = _func_call_cache_key(f, *args, **kwargs)
if cache_key in rcache:
return rcache.get(cache_key)
else:
result = f(*args, **kwargs)
rcache[cache_key] = result
return result
cached_response = request_cache.get_cached_response(cache_key)
if cached_response.is_found:
return cached_response.value
result = f(*args, **kwargs)
request_cache.set(cache_key, result)
return result
return inner_wrapper
return outer_wrapper
def func_call_cache_key(func, *args, **kwargs):
def _func_call_cache_key(func, *args, **kwargs):
"""
Returns a cache key based on the function's module
the function's name, and a stringified list of arguments

View File

@@ -6,16 +6,17 @@ from celery.task import task
from django.conf import settings
from django.test import TestCase
from django.test.utils import override_settings
from edx_django_utils.cache import RequestCache
from mock import Mock
from openedx.core.djangoapps.request_cache import get_request_or_stub
from openedx.core.djangoapps.request_cache.middleware import RequestCache, request_cached
from openedx.core.djangoapps.request_cache.middleware import request_cached
from xmodule.modulestore.django import modulestore
class TestRequestCache(TestCase):
"""
Tests for the request cache.
Tests for request cache helpers and decorators.
"""
def test_get_request_or_stub(self):
@@ -43,7 +44,7 @@ class TestRequestCache(TestCase):
"""
Ensure that after a cache miss, we fill the cache and can hit it.
"""
RequestCache.clear_request_cache()
RequestCache.clear_all_namespaces()
to_be_wrapped = Mock()
to_be_wrapped.return_value = 42
@@ -66,7 +67,7 @@ class TestRequestCache(TestCase):
"""
Ensure that after caching a result, we always send it back, even if the underlying result changes.
"""
RequestCache.clear_request_cache()
RequestCache.clear_all_namespaces()
to_be_wrapped = Mock()
to_be_wrapped.side_effect = [1, 2, 3]
@@ -102,7 +103,7 @@ class TestRequestCache(TestCase):
Ensure that calling a decorated function with different positional arguments
will not use a cached value invoked by a previous call with different arguments.
"""
RequestCache.clear_request_cache()
RequestCache.clear_all_namespaces()
to_be_wrapped = Mock()
to_be_wrapped.side_effect = [1, 2, 3, 4, 5, 6]
@@ -143,7 +144,7 @@ class TestRequestCache(TestCase):
Ensure that calling a decorated function with different keyword arguments
will not use a cached value invoked by a previous call with different arguments.
"""
RequestCache.clear_request_cache()
RequestCache.clear_all_namespaces()
to_be_wrapped = Mock()
to_be_wrapped.side_effect = [1, 2, 3, 4, 5, 6]
@@ -188,7 +189,7 @@ class TestRequestCache(TestCase):
"""
Ensure that request_cached can work with mixed str and Unicode parameters.
"""
RequestCache.clear_request_cache()
RequestCache.clear_all_namespaces()
def dummy_function(arg1, arg2):
"""
@@ -212,7 +213,7 @@ class TestRequestCache(TestCase):
properly caches the result and doesn't recall the underlying
function.
"""
RequestCache.clear_request_cache()
RequestCache.clear_all_namespaces()
to_be_wrapped = Mock()
to_be_wrapped.side_effect = [None, None, None, 1, 1]

View File

@@ -8,6 +8,7 @@ import os
import re
from logging import getLogger
import crum
from django.conf import settings
from microsite_configuration import microsite
@@ -19,7 +20,7 @@ from openedx.core.djangoapps.theming.helpers_dirs import (
get_theme_dirs,
get_themes_unchecked
)
from openedx.core.djangoapps.request_cache.middleware import RequestCache, request_cached
from openedx.core.djangoapps.request_cache.middleware import request_cached
logger = getLogger(__name__) # pylint: disable=invalid-name
@@ -165,7 +166,7 @@ def get_current_request():
Returns:
(HttpRequest): returns current request
"""
return RequestCache.get_current_request()
return crum.get_current_request()
def get_current_site():

View File

@@ -5,6 +5,7 @@ from mock import patch, Mock
from django.test import TestCase, override_settings
from django.conf import settings
from edx_django_utils.cache import RequestCache
from openedx.core.djangoapps.theming.tests.test_util import with_comprehensive_theme
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
@@ -12,7 +13,6 @@ from openedx.core.djangoapps.theming import helpers as theming_helpers
from openedx.core.djangoapps.theming.helpers import get_template_path_with_theme, strip_site_theme_templates_path, \
get_themes, Theme, get_theme_base_dir
from openedx.core.djangolib.testing.utils import skip_unless_cms, skip_unless_lms
from openedx.core.djangoapps.request_cache.middleware import RequestCache
class TestHelpers(TestCase):
@@ -190,7 +190,7 @@ class TestHelpers(TestCase):
mock_microsite_backend.get_template = Mock(return_value="/microsite/about.html")
self.assertEqual(theming_helpers.get_template_path("about.html"), "about.html")
RequestCache.clear_request_cache()
RequestCache.clear_all_namespaces()
# if the current site does not have associated SiteTheme then get_template_path should return microsite override
with patch(

View File

@@ -8,6 +8,7 @@ from django.db import models
from django.db.models.signals import post_save, pre_save
from django.dispatch import receiver
from django.utils.translation import ugettext_lazy
from edx_django_utils.cache import RequestCache
from opaque_keys.edx.django.models import CourseKeyField
from lms.djangoapps.courseware.courses import get_course_by_id
@@ -18,7 +19,7 @@ from openedx.core.djangoapps.course_groups.cohorts import (
is_course_cohorted
)
from openedx.core.djangoapps.verified_track_content.tasks import sync_cohort_with_mode
from openedx.core.djangoapps.request_cache.middleware import RequestCache, ns_request_cached
from openedx.core.djangoapps.request_cache.middleware import ns_request_cached
from student.models import CourseEnrollment
log = logging.getLogger(__name__)
@@ -147,7 +148,7 @@ class VerifiedTrackCohortedCourse(models.Model):
@receiver(models.signals.post_delete, sender=VerifiedTrackCohortedCourse)
def invalidate_verified_track_cache(sender, **kwargs): # pylint: disable=unused-argument
"""Invalidate the cache of VerifiedTrackCohortedCourse. """
RequestCache.clear_request_cache(name=VerifiedTrackCohortedCourse.CACHE_NAMESPACE)
RequestCache(namespace=VerifiedTrackCohortedCourse.CACHE_NAMESPACE).clear()
class MigrateVerifiedTrackCohortsSetting(ConfigurationModel):

View File

@@ -5,9 +5,9 @@ import crum
import ddt
from django.test import TestCase
from django.test.client import RequestFactory
from edx_django_utils.cache import RequestCache
from mock import patch
from opaque_keys.edx.keys import CourseKey
from openedx.core.djangoapps.request_cache.middleware import RequestCache
from waffle.testutils import override_flag
from .. import CourseWaffleFlag, WaffleFlagNamespace, WaffleSwitchNamespace, WaffleSwitch
@@ -34,7 +34,7 @@ class TestCourseWaffleFlag(TestCase):
request = RequestFactory().request()
self.addCleanup(crum.set_current_request, None)
crum.set_current_request(request)
RequestCache.clear_request_cache()
RequestCache.clear_all_namespaces()
@ddt.data(
{'course_override': WaffleFlagCourseOverrideModel.ALL_CHOICES.on, 'waffle_enabled': False, 'result': True},

View File

@@ -3,10 +3,9 @@ Tests for waffle utils models.
"""
from ddt import data, ddt, unpack
from django.test import TestCase
from edx_django_utils.cache import RequestCache
from opaque_keys.edx.keys import CourseKey
from openedx.core.djangoapps.request_cache.middleware import RequestCache
from ..models import WaffleFlagCourseOverrideModel
@@ -26,7 +25,7 @@ class WaffleFlagCourseOverrideTests(TestCase):
(False, OVERRIDE_CHOICES.on, OVERRIDE_CHOICES.unset))
@unpack
def test_setting_override(self, is_enabled, override_choice, expected_result):
RequestCache.clear_request_cache()
RequestCache.clear_all_namespaces()
self.set_waffle_course_override(override_choice, is_enabled)
override_value = WaffleFlagCourseOverrideModel.override_value(
self.WAFFLE_TEST_NAME, self.TEST_COURSE_KEY
@@ -34,7 +33,7 @@ class WaffleFlagCourseOverrideTests(TestCase):
self.assertEqual(override_value, expected_result)
def test_setting_override_multiple_times(self):
RequestCache.clear_request_cache()
RequestCache.clear_all_namespaces()
self.set_waffle_course_override(self.OVERRIDE_CHOICES.on)
self.set_waffle_course_override(self.OVERRIDE_CHOICES.off)
override_value = WaffleFlagCourseOverrideModel.override_value(

View File

@@ -5,9 +5,9 @@ Tests for waffle utils test utilities.
import crum
from django.test import TestCase
from django.test.client import RequestFactory
from edx_django_utils.cache import RequestCache
from opaque_keys.edx.keys import CourseKey
from openedx.core.djangoapps.request_cache.middleware import RequestCache
from .. import CourseWaffleFlag, WaffleFlagNamespace
from ..testutils import override_waffle_flag
@@ -30,7 +30,7 @@ class OverrideWaffleFlagTests(TestCase):
request = RequestFactory().request()
self.addCleanup(crum.set_current_request, None)
crum.set_current_request(request)
RequestCache.clear_request_cache()
RequestCache.clear_all_namespaces()
@override_waffle_flag(TEST_COURSE_FLAG, True)
def assert_decorator_activates_flag(self):

View File

@@ -21,8 +21,6 @@ from django.test import RequestFactory, TestCase, override_settings
from django.test.utils import CaptureQueriesContext
from edx_django_utils.cache import RequestCache
from openedx.core.djangoapps.request_cache.middleware import RequestCache as DeprecatedRequestCache
class CacheIsolationMixin(object):
"""
@@ -120,7 +118,6 @@ class CacheIsolationMixin(object):
# Clear that.
sites.models.SITE_CACHE.clear()
DeprecatedRequestCache.clear_request_cache()
RequestCache.clear_all_namespaces()

View File

@@ -115,7 +115,7 @@ edx-completion==0.1.9
edx-django-oauth2-provider==1.3.4
edx-django-release-util==0.3.1
edx-django-sites-extensions==2.3.1
edx-django-utils==1.0.0
edx-django-utils==1.0.1
edx-drf-extensions==1.6.2
edx-enterprise==0.73.0
edx-i18n-tools==0.4.6

View File

@@ -134,7 +134,7 @@ edx-completion==0.1.9
edx-django-oauth2-provider==1.3.4
edx-django-release-util==0.3.1
edx-django-sites-extensions==2.3.1
edx-django-utils==1.0.0
edx-django-utils==1.0.1
edx-drf-extensions==1.6.2
edx-enterprise==0.73.0
edx-i18n-tools==0.4.6

View File

@@ -36,7 +36,7 @@ pyquery # jQuery-like API for retrieving fragments of HTML and
pysqlite # DB-API 2.0 interface for SQLite 3.x (used as the relational database for most tests)
pytest==3.6.3 # Testing framework # Pinned due to https://github.com/pytest-dev/pytest/issues/3749
pytest-attrib # Select tests based on attributes
pytest-cov # pytest plugin for measuring code coverage
pytest-cov<2.6 # pytest plugin for measuring code coverage
pytest-django==3.1.2 # Django support for pytest
pytest-randomly # pytest plugin to randomly order tests
pytest-xdist # Parallel execution of tests on multiple CPU cores or hosts

View File

@@ -129,7 +129,7 @@ edx-completion==0.1.9
edx-django-oauth2-provider==1.3.4
edx-django-release-util==0.3.1
edx-django-sites-extensions==2.3.1
edx-django-utils==1.0.0
edx-django-utils==1.0.1
edx-drf-extensions==1.6.2
edx-enterprise==0.73.0
edx-i18n-tools==0.4.6