diff --git a/openedx/features/offline_mode/assets_management.py b/openedx/features/offline_mode/assets_management.py index 3594d31c24c0..95710dabd5ba 100644 --- a/openedx/features/offline_mode/assets_management.py +++ b/openedx/features/offline_mode/assets_management.py @@ -58,8 +58,8 @@ def save_asset_file(temp_dir, xblock, path, filename): static_path = get_static_file_path(filename) content = read_static_file(static_path) file_path = os.path.join(temp_dir, 'assets', filename) - except (ItemNotFoundError, NotFoundError): - log.info(f"Asset not found: {filename}") + except (FileNotFoundError, ItemNotFoundError, NotFoundError): + log.warning(f"Asset not found: {filename}, during offline content generation.") else: create_subdirectories_for_asset(file_path) diff --git a/openedx/features/offline_mode/constants.py b/openedx/features/offline_mode/constants.py index a1337a7029c1..771b341505aa 100644 --- a/openedx/features/offline_mode/constants.py +++ b/openedx/features/offline_mode/constants.py @@ -9,7 +9,7 @@ MATHJAX_CDN_URL = f'https://cdn.jsdelivr.net/npm/mathjax@{MATHJAX_VERSION}/MathJax.js' MATHJAX_STATIC_PATH = os.path.join('assets', 'js', f'MathJax-{MATHJAX_VERSION}.js') -DEFAULT_OFFLINE_SUPPORTED_XBLOCKS = ['html'] +DEFAULT_OFFLINE_SUPPORTED_XBLOCKS = ['html', 'problem'] OFFLINE_SUPPORTED_XBLOCKS = getattr(settings, 'OFFLINE_SUPPORTED_XBLOCKS', DEFAULT_OFFLINE_SUPPORTED_XBLOCKS) RETRY_BACKOFF_INITIAL_TIMEOUT = 60 # one minute diff --git a/openedx/features/offline_mode/renderer.py b/openedx/features/offline_mode/renderer.py index bb62792172bc..09258b4ef060 100644 --- a/openedx/features/offline_mode/renderer.py +++ b/openedx/features/offline_mode/renderer.py @@ -81,7 +81,6 @@ def render_xblock_from_lms(self): str(self.usage_key), disable_staff_debug_info=True, course=course, - will_recheck_access='1', ) enable_completion_on_view_service = False diff --git a/openedx/features/offline_mode/tasks.py b/openedx/features/offline_mode/tasks.py index bffbe0396a8f..31fc6dc1d0a6 100644 --- a/openedx/features/offline_mode/tasks.py +++ b/openedx/features/offline_mode/tasks.py @@ -3,6 +3,7 @@ """ from celery import shared_task from edx_django_utils.monitoring import set_code_owner_attribute +from django.http.response import Http404 from opaque_keys.edx.keys import CourseKey, UsageKey from xmodule.modulestore.django import modulestore @@ -17,16 +18,20 @@ def generate_offline_content_for_course(course_id): """ Generates offline content for all supported XBlocks in the course. + + Blocks that are closed to responses won't be processed. """ course_key = CourseKey.from_string(course_id) for offline_supported_block_type in OFFLINE_SUPPORTED_XBLOCKS: for xblock in modulestore().get_items(course_key, qualifiers={'category': offline_supported_block_type}): - html_data = XBlockRenderer(str(xblock.location)).render_xblock_from_lms() - generate_offline_content_for_block.apply_async([str(xblock.location), html_data]) + if not hasattr(xblock, 'closed') or not xblock.closed(): + block_id = str(xblock.location) + html_data = XBlockRenderer(block_id).render_xblock_from_lms() + generate_offline_content_for_block.apply_async([block_id, html_data]) @shared_task( - autoretry_for=(Exception,), + autoretry_for=(Exception, Http404), retry_backoff=RETRY_BACKOFF_INITIAL_TIMEOUT, retry_kwargs={'max_retries': MAX_RETRY_ATTEMPTS} ) diff --git a/openedx/features/offline_mode/utils.py b/openedx/features/offline_mode/utils.py index 55ac7c93d161..015ae6285996 100644 --- a/openedx/features/offline_mode/utils.py +++ b/openedx/features/offline_mode/utils.py @@ -8,6 +8,7 @@ from django.contrib.auth import get_user_model from django.core.files.storage import default_storage +from django.http.response import Http404 from zipfile import ZipFile @@ -36,6 +37,11 @@ def generate_offline_content(xblock, html_data): try: save_xblock_html(tmp_dir, xblock, html_data) create_zip_file(tmp_dir, base_path, f'{xblock.location.block_id}.zip') + except Http404: + log.error( + f'Block {xblock.location.block_id} cannot be fetched from course' + f' {xblock.location.course_key} during offline content generation.' + ) finally: shutil.rmtree(tmp_dir, ignore_errors=True)