diff --git a/cms/djangoapps/api/v1/serializers/course_runs.py b/cms/djangoapps/api/v1/serializers/course_runs.py index 9f82de3928..cbd4d09e21 100644 --- a/cms/djangoapps/api/v1/serializers/course_runs.py +++ b/cms/djangoapps/api/v1/serializers/course_runs.py @@ -11,7 +11,6 @@ from rest_framework.fields import empty from cms.djangoapps.contentstore.views.assets import update_course_run_asset from cms.djangoapps.contentstore.views.course import create_new_course, get_course_and_check_access, rerun_course from common.djangoapps.student.models import CourseAccessRole -from openedx.core.djangoapps.discussions.tasks import update_unit_discussion_state_from_discussion_blocks from openedx.core.lib.courses import course_image_url from xmodule.modulestore.django import modulestore # lint-amnesty, pylint: disable=wrong-import-order @@ -203,5 +202,4 @@ class CourseRunRerunSerializer(CourseRunSerializerCommonFieldsMixin, CourseRunTe course_run = get_course_and_check_access(new_course_run_key, user) self.update_team(course_run, team) - update_unit_discussion_state_from_discussion_blocks(course_run.id, user.id) return course_run diff --git a/cms/djangoapps/contentstore/tasks.py b/cms/djangoapps/contentstore/tasks.py index 4374eacdb9..fa6a2b725c 100644 --- a/cms/djangoapps/contentstore/tasks.py +++ b/cms/djangoapps/contentstore/tasks.py @@ -121,7 +121,6 @@ def rerun_course(source_course_key_string, destination_course_key_string, user_i store = modulestore() with store.default_store('split'): store.clone_course(source_course_key, destination_course_key, user_id, fields=fields) - update_unit_discussion_state_from_discussion_blocks(destination_course_key, user_id) # set initial permissions for the user to access the course. initialize_permissions(destination_course_key, User.objects.get(id=user_id)) @@ -129,6 +128,8 @@ def rerun_course(source_course_key_string, destination_course_key_string, user_i # update state: Succeeded CourseRerunState.objects.succeeded(course_key=destination_course_key) + update_unit_discussion_state_from_discussion_blocks(destination_course_key, user_id) + # call edxval to attach videos to the rerun copy_course_videos(source_course_key, destination_course_key) @@ -342,7 +343,8 @@ def create_export_tarball(course_block, course_key, context, status=None): Updates the context with any error information if applicable. """ name = course_block.url_name - export_file = NamedTemporaryFile(prefix=name + '.', suffix=".tar.gz") # lint-amnesty, pylint: disable=consider-using-with + export_file = NamedTemporaryFile(prefix=name + '.', + suffix=".tar.gz") # lint-amnesty, pylint: disable=consider-using-with root_dir = path(mkdtemp()) try: diff --git a/openedx/core/djangoapps/discussions/tasks.py b/openedx/core/djangoapps/discussions/tasks.py index ffa8e3c2f1..5384b2887a 100644 --- a/openedx/core/djangoapps/discussions/tasks.py +++ b/openedx/core/djangoapps/discussions/tasks.py @@ -8,9 +8,13 @@ from edx_django_utils.monitoring import set_code_owner_attribute from opaque_keys.edx.keys import CourseKey from openedx_events.learning.data import CourseDiscussionConfigurationData, DiscussionTopicContext from openedx_events.learning.signals import COURSE_DISCUSSIONS_CHANGED + +from common.djangoapps.course_action_state.managers import CourseActionStateItemNotFoundError, CourseRerunUIStateManager from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.django import modulestore +from xmodule.modulestore.exceptions import ItemNotFoundError from .config.waffle import ENABLE_NEW_STRUCTURE_DISCUSSIONS +from common.djangoapps.course_action_state.models import CourseRerunState from .models import DiscussionsConfiguration, Provider, DiscussionTopicLink from .utils import get_accessible_discussion_xblocks_by_course_id @@ -28,6 +32,17 @@ def update_discussions_settings_from_course_task(course_key_str: str, discussabl course_key_str (str): course key string discussable_units (List[UsageKey]): list of discussable units """ + try: + course_run_state = CourseRerunState.objects.find_first(course_key=course_key_str) + except (ItemNotFoundError, CourseActionStateItemNotFoundError): + course_run_state = None + + if course_run_state: + if course_run_state.action == 'rerun' and course_run_state.state != CourseRerunUIStateManager.State.SUCCEEDED: + log.info(f"Skipping task because course rerun is not completed yet for course: {course_key_str}") + return + + log.info(f"Continuing task, course rerun is completed for course: {course_key_str}") course_key = CourseKey.from_string(course_key_str) config_data = update_discussions_settings_from_course(course_key, discussable_units) COURSE_DISCUSSIONS_CHANGED.send_event(configuration=config_data) @@ -195,7 +210,7 @@ def update_unit_discussion_state_from_discussion_blocks(course_key: CourseKey, u log.info(f"Migrating legacy discussion config for {course_key}") - with store.bulk_operations(course_key): + with store.bulk_operations(course_key, emit_signals=False): discussion_blocks = get_accessible_discussion_xblocks_by_course_id(course_key, include_all=True) discussable_units = { discussion_block.parent @@ -240,7 +255,8 @@ def update_unit_discussion_state_from_discussion_blocks(course_key: CourseKey, u course.discussions_settings['provider_type'] = provider course.discussions_settings['enable_graded_units'] = enable_graded_subsections course.discussions_settings['unit_level_visibility'] = True - store.update_item(course, user_id) + with store.bulk_operations(course_key, emit_signals=False): + store.update_item(course, user_id) discussion_config = DiscussionsConfiguration.get(course_key) discussion_config.provider_type = provider discussion_config.enable_graded_units = enable_graded_subsections