Storage-backed versioned Block Structures: Configuration
This commit is contained in:
23
openedx/core/djangoapps/content/block_structure/admin.py
Normal file
23
openedx/core/djangoapps/content/block_structure/admin.py
Normal file
@@ -0,0 +1,23 @@
|
||||
"""
|
||||
Django Admin for Block Structures.
|
||||
"""
|
||||
from django.contrib import admin
|
||||
|
||||
from config_models.admin import ConfigurationModelAdmin
|
||||
from .config.models import BlockStructureConfiguration
|
||||
|
||||
|
||||
class BlockStructureAdmin(ConfigurationModelAdmin):
|
||||
"""
|
||||
Configuration Admin for BlockStructureConfiguration.
|
||||
"""
|
||||
def get_displayable_field_names(self):
|
||||
"""
|
||||
Excludes unused 'enabled field from super's list.
|
||||
"""
|
||||
displayable_field_names = super(BlockStructureAdmin, self).get_displayable_field_names()
|
||||
displayable_field_names.remove('enabled')
|
||||
return displayable_field_names
|
||||
|
||||
|
||||
admin.site.register(BlockStructureConfiguration, BlockStructureAdmin)
|
||||
@@ -1,28 +0,0 @@
|
||||
"""
|
||||
This module contains various configuration settings via
|
||||
waffle switches for the Block Structure framework.
|
||||
"""
|
||||
|
||||
from waffle import switch_is_active
|
||||
|
||||
|
||||
INVALIDATE_CACHE_ON_PUBLISH = u'invalidate_cache_on_publish'
|
||||
STORAGE_BACKING_FOR_CACHE = u'storage_backing_for_cache'
|
||||
RAISE_ERROR_WHEN_NOT_FOUND = u'raise_error_when_not_found'
|
||||
|
||||
|
||||
def is_enabled(setting_name):
|
||||
"""
|
||||
Returns whether the given setting is enabled.
|
||||
"""
|
||||
return switch_is_active(
|
||||
waffle_switch_name(setting_name)
|
||||
)
|
||||
|
||||
|
||||
def waffle_switch_name(setting_name):
|
||||
"""
|
||||
Returns the name of the waffle switch for the
|
||||
given name of the setting.
|
||||
"""
|
||||
return u'block_structure.{}'.format(setting_name)
|
||||
@@ -0,0 +1,47 @@
|
||||
"""
|
||||
This module contains various configuration settings via
|
||||
waffle switches for the Block Structure framework.
|
||||
"""
|
||||
from openedx.core.djangolib.waffle_utils import is_switch_enabled
|
||||
from request_cache.middleware import request_cached
|
||||
|
||||
from .models import BlockStructureConfiguration
|
||||
|
||||
|
||||
INVALIDATE_CACHE_ON_PUBLISH = u'invalidate_cache_on_publish'
|
||||
STORAGE_BACKING_FOR_CACHE = u'storage_backing_for_cache'
|
||||
RAISE_ERROR_WHEN_NOT_FOUND = u'raise_error_when_not_found'
|
||||
PRUNE_OLD_VERSIONS = u'prune_old_versions'
|
||||
|
||||
|
||||
def is_enabled(setting_name):
|
||||
"""
|
||||
Returns whether the given block_structure setting
|
||||
is enabled.
|
||||
"""
|
||||
bs_waffle_name = _bs_waffle_switch_name(setting_name)
|
||||
return is_switch_enabled(bs_waffle_name)
|
||||
|
||||
|
||||
@request_cached
|
||||
def num_versions_to_keep():
|
||||
"""
|
||||
Returns and caches the current setting for num_versions_to_keep.
|
||||
"""
|
||||
return BlockStructureConfiguration.current().num_versions_to_keep
|
||||
|
||||
|
||||
@request_cached
|
||||
def cache_timeout_in_seconds():
|
||||
"""
|
||||
Returns and caches the current setting for cache_timeout_in_seconds.
|
||||
"""
|
||||
return BlockStructureConfiguration.current().cache_timeout_in_seconds
|
||||
|
||||
|
||||
def _bs_waffle_switch_name(setting_name):
|
||||
"""
|
||||
Returns the name of the waffle switch for the
|
||||
given block structure setting.
|
||||
"""
|
||||
return u'block_structure.{}'.format(setting_name)
|
||||
@@ -0,0 +1,26 @@
|
||||
"""
|
||||
Models for configuration of Block Structures.
|
||||
"""
|
||||
from django.db.models import IntegerField
|
||||
from config_models.models import ConfigurationModel
|
||||
|
||||
|
||||
class BlockStructureConfiguration(ConfigurationModel):
|
||||
"""
|
||||
Configuration model for Block Structures.
|
||||
"""
|
||||
DEFAULT_PRUNE_KEEP_COUNT = 5
|
||||
DEFAULT_CACHE_TIMEOUT_IN_SECONDS = 60 * 60 * 24 # 24 hours
|
||||
|
||||
class Meta(object):
|
||||
app_label = 'block_structure'
|
||||
db_table = 'block_structure_config'
|
||||
|
||||
num_versions_to_keep = IntegerField(blank=True, null=True, default=DEFAULT_PRUNE_KEEP_COUNT)
|
||||
cache_timeout_in_seconds = IntegerField(blank=True, null=True, default=DEFAULT_CACHE_TIMEOUT_IN_SECONDS)
|
||||
|
||||
def __unicode__(self):
|
||||
return u"BlockStructureConfiguration: num_versions_to_keep: {}, cache_timeout_in_seconds: {}".format(
|
||||
self.num_versions_to_keep,
|
||||
self.cache_timeout_in_seconds,
|
||||
)
|
||||
@@ -0,0 +1,30 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='BlockStructureConfiguration',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Enabled')),
|
||||
('num_versions_to_keep', models.IntegerField(default=5, null=True, blank=True)),
|
||||
('cache_timeout_in_seconds', models.IntegerField(default=86400, null=True, blank=True)),
|
||||
('changed_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, editable=False, to=settings.AUTH_USER_MODEL, null=True, verbose_name='Changed by')),
|
||||
],
|
||||
options={
|
||||
'db_table': 'block_structure_config',
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -3,7 +3,10 @@ Helpers for Course Blocks tests.
|
||||
"""
|
||||
|
||||
from openedx.core.lib.block_structure.cache import BlockStructureCache
|
||||
from openedx.core.djangolib.testing.waffle_utils import override_switch
|
||||
|
||||
from ..api import get_cache
|
||||
from ..config import _bs_waffle_switch_name
|
||||
|
||||
|
||||
def is_course_in_block_structure_cache(course_key, store):
|
||||
@@ -12,3 +15,15 @@ def is_course_in_block_structure_cache(course_key, store):
|
||||
"""
|
||||
course_usage_key = store.make_course_usage_key(course_key)
|
||||
return BlockStructureCache(get_cache()).get(course_usage_key) is not None
|
||||
|
||||
|
||||
class override_config_setting(override_switch): # pylint:disable=invalid-name
|
||||
"""
|
||||
Subclasses override_switch to use the block structure
|
||||
name-spaced switch names.
|
||||
"""
|
||||
def __init__(self, name, active):
|
||||
super(override_config_setting, self).__init__(
|
||||
_bs_waffle_switch_name(name),
|
||||
active
|
||||
)
|
||||
|
||||
@@ -3,7 +3,6 @@ Unit tests for the Course Blocks signals
|
||||
"""
|
||||
import ddt
|
||||
from mock import patch
|
||||
from waffle.testutils import override_switch
|
||||
|
||||
from opaque_keys.edx.locator import LibraryLocator, CourseLocator
|
||||
from xmodule.modulestore.exceptions import ItemNotFoundError
|
||||
@@ -11,9 +10,9 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
from ..api import get_block_structure_manager
|
||||
from ..config import INVALIDATE_CACHE_ON_PUBLISH
|
||||
from ..signals import _listen_for_course_publish
|
||||
from ..config import INVALIDATE_CACHE_ON_PUBLISH, waffle_switch_name
|
||||
from .helpers import is_course_in_block_structure_cache
|
||||
from .helpers import is_course_in_block_structure_cache, override_config_setting
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@@ -55,7 +54,7 @@ class CourseBlocksSignalTest(ModuleStoreTestCase):
|
||||
def test_cache_invalidation(self, invalidate_cache_enabled, mock_bs_manager_clear):
|
||||
test_display_name = "Jedi 101"
|
||||
|
||||
with override_switch(waffle_switch_name(INVALIDATE_CACHE_ON_PUBLISH), active=invalidate_cache_enabled):
|
||||
with override_config_setting(INVALIDATE_CACHE_ON_PUBLISH, active=invalidate_cache_enabled):
|
||||
self.course.display_name = test_display_name
|
||||
self.store.update_item(self.course, self.user.id)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user