From 87393cd91fdd902fd96791dca6c9156f3a16c9f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=86=D0=B2=D0=B0=D0=BD=20=D0=9D=D1=94=D0=B4=D1=94=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D1=96=D1=86=D0=B5=D0=B2?= Date: Mon, 17 Jun 2024 19:31:41 +0300 Subject: [PATCH 1/4] fix: fix problem block offline generations --- openedx/features/offline_mode/assets_management.py | 2 +- openedx/features/offline_mode/constants.py | 2 +- openedx/features/offline_mode/renderer.py | 2 +- openedx/features/offline_mode/tasks.py | 6 ++++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/openedx/features/offline_mode/assets_management.py b/openedx/features/offline_mode/assets_management.py index 3594d31c24c0..68d662168300 100644 --- a/openedx/features/offline_mode/assets_management.py +++ b/openedx/features/offline_mode/assets_management.py @@ -58,7 +58,7 @@ 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): + except (FileNotFoundError, ItemNotFoundError, NotFoundError): log.info(f"Asset not found: {filename}") else: 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..c0603b3c831e 100644 --- a/openedx/features/offline_mode/renderer.py +++ b/openedx/features/offline_mode/renderer.py @@ -81,7 +81,7 @@ def render_xblock_from_lms(self): str(self.usage_key), disable_staff_debug_info=True, course=course, - will_recheck_access='1', + will_recheck_access=False, ) enable_completion_on_view_service = False diff --git a/openedx/features/offline_mode/tasks.py b/openedx/features/offline_mode/tasks.py index bffbe0396a8f..36b81a7bd3ac 100644 --- a/openedx/features/offline_mode/tasks.py +++ b/openedx/features/offline_mode/tasks.py @@ -21,8 +21,10 @@ def generate_offline_content_for_course(course_id): 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 hasattr(xblock, 'closed') and 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( From 107292741af2c072a921c8dc9238d8ed30b824a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=86=D0=B2=D0=B0=D0=BD=20=D0=9D=D1=94=D0=B4=D1=94=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D1=96=D1=86=D0=B5=D0=B2?= Date: Mon, 17 Jun 2024 19:58:47 +0300 Subject: [PATCH 2/4] fix: add logs for 404 error on gettings xblock --- openedx/features/offline_mode/utils.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openedx/features/offline_mode/utils.py b/openedx/features/offline_mode/utils.py index 55ac7c93d161..c1ae7efa86b4 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,8 @@ 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} for course {xblock.location.course_key} not found.') finally: shutil.rmtree(tmp_dir, ignore_errors=True) From 1c30aeadbdd4e71fc53c973e5e5f076a4ac3347d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=86=D0=B2=D0=B0=D0=BD=20=D0=9D=D1=94=D0=B4=D1=94=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D1=96=D1=86=D0=B5=D0=B2?= Date: Mon, 17 Jun 2024 20:21:46 +0300 Subject: [PATCH 3/4] fix: fix xblock close checking for HTML xblock --- openedx/features/offline_mode/tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openedx/features/offline_mode/tasks.py b/openedx/features/offline_mode/tasks.py index 36b81a7bd3ac..d98b87384e6f 100644 --- a/openedx/features/offline_mode/tasks.py +++ b/openedx/features/offline_mode/tasks.py @@ -21,7 +21,7 @@ def generate_offline_content_for_course(course_id): 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}): - if hasattr(xblock, 'closed') and not xblock.closed(): + 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]) From 4de60bde47065848dd10f346b7907f910e31e448 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=86=D0=B2=D0=B0=D0=BD=20=D0=9D=D1=94=D0=B4=D1=94=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D1=96=D1=86=D0=B5=D0=B2?= Date: Wed, 19 Jun 2024 20:45:12 +0300 Subject: [PATCH 4/4] fix: [AXM-748] fix after review --- openedx/features/offline_mode/assets_management.py | 2 +- openedx/features/offline_mode/renderer.py | 1 - openedx/features/offline_mode/tasks.py | 5 ++++- openedx/features/offline_mode/utils.py | 5 ++++- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/openedx/features/offline_mode/assets_management.py b/openedx/features/offline_mode/assets_management.py index 68d662168300..95710dabd5ba 100644 --- a/openedx/features/offline_mode/assets_management.py +++ b/openedx/features/offline_mode/assets_management.py @@ -59,7 +59,7 @@ def save_asset_file(temp_dir, xblock, path, filename): content = read_static_file(static_path) file_path = os.path.join(temp_dir, 'assets', filename) except (FileNotFoundError, ItemNotFoundError, NotFoundError): - log.info(f"Asset not found: {filename}") + 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/renderer.py b/openedx/features/offline_mode/renderer.py index c0603b3c831e..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=False, ) enable_completion_on_view_service = False diff --git a/openedx/features/offline_mode/tasks.py b/openedx/features/offline_mode/tasks.py index d98b87384e6f..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,6 +18,8 @@ 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: @@ -28,7 +31,7 @@ def generate_offline_content_for_course(course_id): @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 c1ae7efa86b4..015ae6285996 100644 --- a/openedx/features/offline_mode/utils.py +++ b/openedx/features/offline_mode/utils.py @@ -38,7 +38,10 @@ def generate_offline_content(xblock, html_data): 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} for course {xblock.location.course_key} not found.') + 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)