From d0030eef0d48b0a8141b2c4dedc4e1b07eb12a56 Mon Sep 17 00:00:00 2001 From: Rebecca Graber Date: Tue, 10 Oct 2023 09:50:17 -0400 Subject: [PATCH 1/7] feat: use the new event bus producer configs --- .../contentstore/signals/handlers.py | 60 ++++++++++++- cms/envs/common.py | 78 ++++++++++++++++- cms/envs/devstack.py | 1 + cms/envs/production.py | 7 +- common/djangoapps/student/handlers.py | 40 ++++++++- lms/djangoapps/certificates/config.py | 2 + lms/djangoapps/certificates/signals.py | 44 ++++++++++ lms/envs/common.py | 85 ++++++++++++++++++- lms/envs/production.py | 5 ++ 9 files changed, 311 insertions(+), 11 deletions(-) diff --git a/cms/djangoapps/contentstore/signals/handlers.py b/cms/djangoapps/contentstore/signals/handlers.py index fec46b6b7484..8f2c27a8eb99 100644 --- a/cms/djangoapps/contentstore/signals/handlers.py +++ b/cms/djangoapps/contentstore/signals/handlers.py @@ -10,6 +10,7 @@ from django.core.cache import cache from django.db import transaction from django.dispatch import receiver +from edx_django_utils.monitoring import set_custom_attribute from edx_toggles.toggles import SettingToggle from opaque_keys.edx.keys import CourseKey from openedx_events.content_authoring.data import CourseCatalogData, CourseScheduleData @@ -159,11 +160,46 @@ def listen_for_course_publish(sender, course_key, **kwargs): # pylint: disable= transaction.on_commit(lambda: emit_catalog_info_changed_signal(course_key)) +def _determine_producer_config_for_signal_and_topic(signal, topic): + """ + Utility method to determine the setting for the given signal and topic in EVENT_BUS_PRODUCER_CONFIG + + Records to New Relic for later analysis. + + Parameters + signal (OpenEdxPublicSignal): The signal being sent to the event bus + topic (string): The topic to which the signal is being sent + + Returns + True if the signal is enabled for that topic in EVENT_BUS_PRODUCER_CONFIG + False if the signal is explicitly disabled for that topic in EVENT_BUS_PRODUCER_CONFIG + None if the signal/topic pair is not present in EVENT_BUS_PRODUCER_CONFIG + """ + event_type_producer_configs = getattr(settings, "EVENT_BUS_PRODUCER_CONFIG", + {}).get(signal.event_type, {}) + topic_config = event_type_producer_configs.get(topic, {}) + topic_setting = topic_config.get('enabled', None) + if topic_setting is True: + set_custom_attribute('producer_config_setting', 'True') + if topic_setting is False: + set_custom_attribute('producer_config_setting', 'False') + if topic_setting is None: + set_custom_attribute('producer_config_setting', 'Unset') + return topic_setting + + @receiver(COURSE_CATALOG_INFO_CHANGED) def listen_for_course_catalog_info_changed(sender, signal, **kwargs): """ Publish COURSE_CATALOG_INFO_CHANGED signals onto the event bus. """ + # temporary: defer to EVENT_BUS_PRODUCER_CONFIG if present + producer_config_setting = _determine_producer_config_for_signal_and_topic(COURSE_CATALOG_INFO_CHANGED, + 'course-catalog-info-changed') + if producer_config_setting is True: + log.info("Producing course-catalog-info-changed event via config") + return + log.info("Producing course-catalog-info-changed event via manual send") get_producer().send( signal=COURSE_CATALOG_INFO_CHANGED, topic='course-catalog-info-changed', event_key_field='catalog_info.course_key', event_data={'catalog_info': kwargs['catalog_info']}, @@ -176,8 +212,14 @@ def listen_for_xblock_published(sender, signal, **kwargs): """ Publish XBLOCK_PUBLISHED signals onto the event bus. """ + # temporary: defer to EVENT_BUS_PRODUCER_CONFIG if present + topic = getattr(settings, "EVENT_BUS_XBLOCK_LIFECYCLE_TOPIC", "course-authoring-xblock-lifecycle") + producer_config_setting = _determine_producer_config_for_signal_and_topic(XBLOCK_PUBLISHED, topic) + if producer_config_setting is True: + log.info("Producing xblock-published event via config") + return if settings.FEATURES.get("ENABLE_SEND_XBLOCK_EVENTS_OVER_BUS"): - topic = getattr(settings, "EVENT_BUS_XBLOCK_LIFECYCLE_TOPIC", "course-authoring-xblock-lifecycle") + log.info("Producing xblock-published event via manual send") get_producer().send( signal=XBLOCK_PUBLISHED, topic=topic, event_key_field='xblock_info.usage_key', event_data={'xblock_info': kwargs['xblock_info']}, @@ -190,8 +232,14 @@ def listen_for_xblock_deleted(sender, signal, **kwargs): """ Publish XBLOCK_DELETED signals onto the event bus. """ + # temporary: defer to EVENT_BUS_PRODUCER_CONFIG if present + topic = getattr(settings, "EVENT_BUS_XBLOCK_LIFECYCLE_TOPIC", "course-authoring-xblock-lifecycle") + producer_config_setting = _determine_producer_config_for_signal_and_topic(XBLOCK_DELETED, topic) + if producer_config_setting is True: + log.info("Producing xblock-deleted event via config") + return if settings.FEATURES.get("ENABLE_SEND_XBLOCK_EVENTS_OVER_BUS"): - topic = getattr(settings, "EVENT_BUS_XBLOCK_LIFECYCLE_TOPIC", "course-authoring-xblock-lifecycle") + log.info("Producing xblock-deleted event via manual send") get_producer().send( signal=XBLOCK_DELETED, topic=topic, event_key_field='xblock_info.usage_key', event_data={'xblock_info': kwargs['xblock_info']}, @@ -204,8 +252,14 @@ def listen_for_xblock_duplicated(sender, signal, **kwargs): """ Publish XBLOCK_DUPLICATED signals onto the event bus. """ + # temporary: defer to EVENT_BUS_PRODUCER_CONFIG if present + topic = getattr(settings, "EVENT_BUS_XBLOCK_LIFECYCLE_TOPIC", "course-authoring-xblock-lifecycle") + producer_config_setting = _determine_producer_config_for_signal_and_topic(XBLOCK_DUPLICATED, topic) + if producer_config_setting is True: + log.info("Producing xblock-duplicated event via config") + return if settings.FEATURES.get("ENABLE_SEND_XBLOCK_EVENTS_OVER_BUS"): - topic = getattr(settings, "EVENT_BUS_XBLOCK_LIFECYCLE_TOPIC", "course-authoring-xblock-lifecycle") + log.info("Producing xblock-duplicated event via manual send") get_producer().send( signal=XBLOCK_DUPLICATED, topic=topic, event_key_field='xblock_info.usage_key', event_data={'xblock_info': kwargs['xblock_info']}, diff --git a/cms/envs/common.py b/cms/envs/common.py index 40b5be678939..823ae4048286 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -531,6 +531,19 @@ # .. toggle_creation_date: 2023-03-31 # .. toggle_tickets: https://github.com/openedx/edx-platform/pull/32015 'DISABLE_ADVANCED_SETTINGS': False, + + # .. toggle_name: FEATURES['ENABLE_SEND_XBLOCK_LIFECYCLE_EVENTS_OVER_BUS'] + # .. toggle_implementation: DjangoSetting + # .. toggle_default: False + # .. toggle_description: Enables sending xblock lifecycle events over the event bus. Used to create the + # EVENT_BUS_PRODUCER_CONFIG setting + # .. toggle_use_cases: opt_in + # .. toggle_creation_date: 2023-10-10 + # .. toggle_target_removal_date: 2023-10-12 + # .. toggle_warning: The default may be changed in a later release. See + # https://github.com/openedx/openedx-events/issues/265 + # .. toggle_tickets: https://github.com/edx/edx-arch-experiments/issues/381 + 'ENABLE_SEND_XBLOCK_LIFECYCLE_EVENTS_OVER_BUS': False, } # .. toggle_name: ENABLE_COPPA_COMPLIANCE @@ -1795,6 +1808,7 @@ # alternative swagger generator for CMS API 'drf_spectacular', + 'openedx_events' ] @@ -2789,6 +2803,64 @@ 'PREPROCESSING_HOOKS': ['cms.lib.spectacular.cms_api_filter'], # restrict spectacular to CMS API endpoints } -#### Event bus publishing #### -## Will be more filled out as part of https://github.com/edx/edx-arch-experiments/issues/381 -EVENT_BUS_PRODUCER_CONFIG = {} + +#### Event bus producing #### +# .. setting_name: EVENT_BUS_PRODUCER_CONFIG +# .. setting_default: {} +# .. setting_description: Dictionary of event_types mapped to dictionaries of topic to topic-related configuration. +# Each topic configuration dictionary contains +# * `enabled`: a toggle denoting whether the event will be published to the topic. These should be annotated +# according to +# https://edx.readthedocs.io/projects/edx-toggles/en/latest/how_to/documenting_new_feature_toggles.html +# * `event_key_field` which is a period-delimited string path to event data field to use as event key. +# Note: The topic names should not include environment prefix as it will be dynamically added based on +# EVENT_BUS_TOPIC_PREFIX setting. +def _should_send_xblock_events(settings): + return settings.FEATURES['ENABLE_SEND_XBLOCK_LIFECYCLE_EVENTS_OVER_BUS'] + + +EVENT_BUS_PRODUCER_CONFIG = { + 'org.openedx.content_authoring.course.catalog_info.changed.v1': { + 'course-catalog-info-changed': + {'event_key_field': 'catalog_info.course_key', + # .. toggle_name: ENABLE_SEND_COURSE_CATALOG_INFO_CHANGED_EVENTS_OVER_BUS + # .. toggle_implementation: DjangoSetting + # .. toggle_default: False + # .. toggle_description: if enabled, will publish COURSE_CATALOG_INFO_CHANGED events to the event bus on + # the course-catalog-info-changed topics + # .. toggle_warning: The default may be changed in a later release. See + # https://github.com/openedx/openedx-events/issues/265 + # .. toggle_use_cases: opt_in + # .. toggle_creation_date: 2023-10-10 + 'enabled': False}, + }, + 'org.openedx.content_authoring.xblock.published.v1': { + 'course-authoring-xblock-lifecycle': + {'event_key_field': 'xblock_info.usage_key', 'enabled': _should_send_xblock_events}, + }, + 'org.openedx.content_authoring.xblock.deleted.v1': { + 'course-authoring-xblock-lifecycle': + {'event_key_field': 'xblock_info.usage_key', 'enabled': _should_send_xblock_events}, + }, + 'org.openedx.content_authoring.xblock.duplicated.v1': { + 'course-authoring-xblock-lifecycle': + {'event_key_field': 'xblock_info.usage_key', 'enabled': _should_send_xblock_events}, + }, + # LMS events. These have to be copied over here because lms.common adds some derived entries as well, + # and the derivation fails if the keys are missing. If we ever remove the import of lms.common, we can remove these. + 'org.openedx.learning.certificate.created.v1': { + 'learning-certificate-lifecycle': + {'event_key_field': 'certificate.course.course_key', 'enabled': False}, + }, + 'org.openedx.learning.certificate.revoked.v1': { + 'learning-certificate-lifecycle': + {'event_key_field': 'certificate.course.course_key', 'enabled': False}, + }, +} + +derived_collection_entry('EVENT_BUS_PRODUCER_CONFIG', 'org.openedx.content_authoring.xblock.published.v1', + 'course-authoring-xblock-lifecycle', 'enabled') +derived_collection_entry('EVENT_BUS_PRODUCER_CONFIG', 'org.openedx.content_authoring.xblock.duplicated.v1', + 'course-authoring-xblock-lifecycle', 'enabled') +derived_collection_entry('EVENT_BUS_PRODUCER_CONFIG', 'org.openedx.content_authoring.xblock.deleted.v1', + 'course-authoring-xblock-lifecycle', 'enabled') diff --git a/cms/envs/devstack.py b/cms/envs/devstack.py index 61359d0611f3..29c77701886e 100644 --- a/cms/envs/devstack.py +++ b/cms/envs/devstack.py @@ -309,6 +309,7 @@ def should_show_debug_toolbar(request): # lint-amnesty, pylint: disable=missing # .. toggle_creation_date: 2023-02-21 # .. toggle_warning: For consistency in user experience, keep the value in sync with the setting of the same name # in the LMS and CMS. +# This will be deprecated in favor of ENABLE_SEND_XBLOCK_LIFECYCLE_EVENTS_OVER_BUS # .. toggle_tickets: 'https://github.com/openedx/edx-platform/pull/31813' FEATURES['ENABLE_SEND_XBLOCK_EVENTS_OVER_BUS'] = True FEATURES['ENABLE_SEND_ENROLLMENT_EVENTS_OVER_BUS'] = True diff --git a/cms/envs/production.py b/cms/envs/production.py index 213243fa8237..7e635c402e23 100644 --- a/cms/envs/production.py +++ b/cms/envs/production.py @@ -18,9 +18,9 @@ from django.core.exceptions import ImproperlyConfigured from django.urls import reverse_lazy from edx_django_utils.plugins import add_plugins +from openedx_events.event_bus import merge_producer_configs from path import Path as path - from openedx.core.djangoapps.plugins.constants import ProjectType, SettingsType from .common import * @@ -85,6 +85,7 @@ def get_env_setting(setting): 'MKTG_URL_LINK_MAP', 'MKTG_URL_OVERRIDES', 'REST_FRAMEWORK', + 'EVENT_BUS_PRODUCER_CONFIG', ] for key in KEYS_WITH_MERGED_VALUES: if key in __config_copy__: @@ -670,3 +671,7 @@ def get_env_setting(setting): } INACTIVE_USER_URL = f'http{"s" if HTTPS == "on" else ""}://{CMS_BASE}' + +############## Event bus producer ############## +EVENT_BUS_PRODUCER_CONFIG = merge_producer_configs(EVENT_BUS_PRODUCER_CONFIG, + ENV_TOKENS.get('EVENT_BUS_PRODUCER_CONFIG', {})) diff --git a/common/djangoapps/student/handlers.py b/common/djangoapps/student/handlers.py index 6dc841f98fa0..c373524227f2 100644 --- a/common/djangoapps/student/handlers.py +++ b/common/djangoapps/student/handlers.py @@ -3,11 +3,43 @@ """ from django.conf import settings from django.dispatch import receiver +from edx_django_utils.monitoring import set_custom_attribute from openedx_events.event_bus import get_producer from openedx_events.learning.signals import ( COURSE_UNENROLLMENT_COMPLETED, ) +import logging +log = logging.getLogger(__name__) + + +def _determine_producer_config_for_signal_and_topic(signal, topic): + """ + Utility method to determine the setting for the given signal and topic in EVENT_BUS_PRODUCER_CONFIG + + Records to New Relic for later analysis. + + Parameters + signal (OpenEdxPublicSignal): The signal being sent to the event bus + topic (string): The topic to which the signal is being sent + + Returns + True if the signal is enabled for that topic in EVENT_BUS_PRODUCER_CONFIG + False if the signal is explicitly disabled for that topic in EVENT_BUS_PRODUCER_CONFIG + None if the signal/topic pair is not present in EVENT_BUS_PRODUCER_CONFIG + """ + event_type_producer_configs = getattr(settings, "EVENT_BUS_PRODUCER_CONFIG", + {}).get(signal.event_type, {}) + topic_config = event_type_producer_configs.get(topic, {}) + topic_setting = topic_config.get('enabled', None) + if topic_setting is True: + set_custom_attribute('producer_config_setting', 'True') + return + if topic_setting is False: + set_custom_attribute('producer_config_setting', 'False') + if topic_setting is None: + set_custom_attribute('producer_config_setting', 'Unset') + return topic_setting @receiver(COURSE_UNENROLLMENT_COMPLETED) @@ -15,10 +47,16 @@ def course_unenrollment_receiver(sender, signal, **kwargs): """ Removes user notification preference when user un-enrolls from the course """ + topic = getattr(settings, "EVENT_BUS_ENROLLMENT_LIFECYCLE_TOPIC", "course-unenrollment-lifecycle") + producer_config_setting = _determine_producer_config_for_signal_and_topic(COURSE_UNENROLLMENT_COMPLETED, topic) + if producer_config_setting is True: + log.info("Producing unenrollment-event event via config") + return if settings.FEATURES.get("ENABLE_SEND_ENROLLMENT_EVENTS_OVER_BUS"): + log.info("Producing unenrollment-event event via manual send") get_producer().send( signal=COURSE_UNENROLLMENT_COMPLETED, - topic=getattr(settings, "EVENT_BUS_ENROLLMENT_LIFECYCLE_TOPIC", "course-unenrollment-lifecycle"), + topic=topic, event_key_field='enrollment.course.course_key', event_data={'enrollment': kwargs.get('enrollment')}, event_metadata=kwargs.get('metadata') diff --git a/lms/djangoapps/certificates/config.py b/lms/djangoapps/certificates/config.py index 6df62ae563b1..92b20b17bb27 100644 --- a/lms/djangoapps/certificates/config.py +++ b/lms/djangoapps/certificates/config.py @@ -23,6 +23,7 @@ # .. toggle_description: When True, the system will publish `CERTIFICATE_CREATED` signals to the event bus. The # `CERTIFICATE_CREATED` signal is emit when a certificate has been awarded to a learner and the creation process has # completed. +# .. toggle_warning: Will be deprecated in favor of SEND_LEARNING_CERTIFICATE_LIFECYCLE_EVENTS_TO_BUS # .. toggle_use_cases: temporary # .. toggle_creation_date: 2023-04-11 # .. toggle_target_removal_date: 2023-07-31 @@ -36,6 +37,7 @@ # .. toggle_description: When True, the system will publish `CERTIFICATE_REVOKED` signals to the event bus. The # `CERTIFICATE_REVOKED` signal is emit when a certificate has been revoked from a learner and the revocation process # has completed. +# .. toggle_warning: Will be deprecated in favor of SEND_LEARNING_CERTIFICATE_LIFECYCLE_EVENTS_TO_BUS # .. toggle_use_cases: temporary # .. toggle_creation_date: 2023-09-15 # .. toggle_target_removal_date: 2024-01-01 diff --git a/lms/djangoapps/certificates/signals.py b/lms/djangoapps/certificates/signals.py index 4d43f0ed4983..fad7946cc8c3 100644 --- a/lms/djangoapps/certificates/signals.py +++ b/lms/djangoapps/certificates/signals.py @@ -3,10 +3,12 @@ """ import logging +from django.conf import settings from django.db.models.signals import post_save from django.dispatch import receiver from openedx_events.event_bus import get_producer +from edx_django_utils.monitoring import set_custom_attribute from common.djangoapps.course_modes import api as modes_api from common.djangoapps.student.models import CourseEnrollment @@ -161,12 +163,47 @@ def _listen_for_enrollment_mode_change(sender, user, course_key, mode, **kwargs) return False +def _determine_producer_config_for_signal_and_topic(signal, topic): + """ + Utility method to determine the setting for the given signal and topic in EVENT_BUS_PRODUCER_CONFIG + + Records to New Relic for later analysis. + + Parameters + signal (OpenEdxPublicSignal): The signal being sent to the event bus + topic (string): The topic to which the signal is being sent + + Returns + True if the signal is enabled for that topic in EVENT_BUS_PRODUCER_CONFIG + False if the signal is explicitly disabled for that topic in EVENT_BUS_PRODUCER_CONFIG + None if the signal/topic pair is not present in EVENT_BUS_PRODUCER_CONFIG + """ + event_type_producer_configs = getattr(settings, "EVENT_BUS_PRODUCER_CONFIG", + {}).get(signal.event_type, {}) + topic_config = event_type_producer_configs.get(topic, {}) + topic_setting = topic_config.get('enabled', None) + if topic_setting is True: + set_custom_attribute('producer_config_setting', 'True') + if topic_setting is False: + set_custom_attribute('producer_config_setting', 'False') + if topic_setting is None: + set_custom_attribute('producer_config_setting', 'Unset') + return topic_setting + + @receiver(CERTIFICATE_CREATED) def listen_for_certificate_created_event(sender, signal, **kwargs): # pylint: disable=unused-argument """ Publish `CERTIFICATE_CREATED` events to the event bus. """ + # temporary: defer to EVENT_BUS_PRODUCER_CONFIG if present + producer_config_setting = _determine_producer_config_for_signal_and_topic(CERTIFICATE_CREATED, + 'learning-certificate-lifecycle') + if producer_config_setting is True: + log.info("Producing certificate-created event via config") + return if SEND_CERTIFICATE_CREATED_SIGNAL.is_enabled(): + log.info("Producing certificate-created event via manual send") get_producer().send( signal=CERTIFICATE_CREATED, topic='learning-certificate-lifecycle', @@ -181,7 +218,14 @@ def listen_for_certificate_revoked_event(sender, signal, **kwargs): # pylint: d """ Publish `CERTIFICATE_REVOKED` events to the event bus. """ + # temporary: defer to EVENT_BUS_PRODUCER_CONFIG if present + producer_config_setting = _determine_producer_config_for_signal_and_topic(CERTIFICATE_REVOKED, + 'learning-certificate-lifecycle') + if producer_config_setting is True: + log.info("Producing certificate-revoked event via config") + return if SEND_CERTIFICATE_REVOKED_SIGNAL.is_enabled(): + log.info("Producing certificate-revoked event via manual send") get_producer().send( signal=CERTIFICATE_REVOKED, topic='learning-certificate-lifecycle', diff --git a/lms/envs/common.py b/lms/envs/common.py index 0907b3f8a451..e3ee4e630670 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -1039,6 +1039,18 @@ # .. toggle_creation_date: 2022-06-06 # .. toggle_tickets: 'https://github.com/edx/edx-platform/pull/29538' 'DISABLE_ALLOWED_ENROLLMENT_IF_ENROLLMENT_CLOSED': False, + + # .. toggle_name: SEND_LEARNING_CERTIFICATE_LIFECYCLE_EVENTS_TO_BUS + # .. toggle_implementation: SettingToggle + # .. toggle_default: False + # .. toggle_description: When True, the system will publish certificate lifecycle signals to the event bus. + # This toggle is used to create the EVENT_BUS_PRODUCER_CONFIG setting. + # .. toggle_warning: The default may be changed in a later release. See + # https://github.com/openedx/openedx-events/issues/265 + # .. toggle_use_cases: opt_in + # .. toggle_creation_date: 2023-10-10 + # .. toggle_tickets: https://github.com/openedx/openedx-events/issues/210 + 'SEND_LEARNING_CERTIFICATE_LIFECYCLE_EVENTS_TO_BUS': False } # Specifies extra XBlock fields that should available when requested via the Course Blocks API @@ -5386,6 +5398,73 @@ def _make_locale_paths(settings): # pylint: disable=missing-function-docstring # disable indexing on date field its coming from django-simple-history. SIMPLE_HISTORY_DATE_INDEX = False -#### Event bus publishing #### -## Will be more filled out as part of https://github.com/edx/edx-arch-experiments/issues/381 -EVENT_BUS_PRODUCER_CONFIG = {} + +def _should_send_certificate_events(settings): + return settings.FEATURES['SEND_LEARNING_CERTIFICATE_LIFECYCLE_EVENTS_TO_BUS'] +#### Event bus producing #### +# .. setting_name: EVENT_BUS_PRODUCER_CONFIG +# .. setting_default: {} +# .. setting_description: Dictionary of event_types mapped to dictionaries of topic to topic-related configuration. +# Each topic configuration dictionary contains +# * `enabled`: a toggle denoting whether the event will be published to the topic. These should be annotated +# according to +# https://edx.readthedocs.io/projects/edx-toggles/en/latest/how_to/documenting_new_feature_toggles.html +# * `event_key_field` which is a period-delimited string path to event data field to use as event key. +# Note: The topic names should not include environment prefix as it will be dynamically added based on +# EVENT_BUS_TOPIC_PREFIX setting. +EVENT_BUS_PRODUCER_CONFIG = { + 'org.openedx.learning.certificate.created.v1': { + 'learning-certificate-lifecycle': + {'event_key_field': 'certificate.course.course_key', 'enabled': _should_send_certificate_events}, + }, + 'org.openedx.learning.certificate.revoked.v1': { + 'learning-certificate-lifecycle': + {'event_key_field': 'certificate.course.course_key', 'enabled': _should_send_certificate_events}, + }, + 'org.openedx.learning.course.unenrollment.completed.v1': { + 'course-unenrollment-lifecycle': + {'event_key_field': 'enrollment.course.course_key', + # .. toggle_name: ENABLE_SEND_COURSE_UNENROLLMENT_COMPLETED_EVENTS_OVER_BUS + # .. toggle_implementation: DjangoSetting + # .. toggle_default: False + # .. toggle_description: Enables sending COURSE_UNENROLLMENT_COMPLETED events over the event bus. + # .. toggle_use_cases: opt_in + # .. toggle_creation_date: 2023-09-18 + # .. toggle_warning: The default may be changed in a later release. See + # https://github.com/openedx/openedx-events/issues/265 + # .. toggle_tickets: https://github.com/openedx/openedx-events/issues/210 + 'enabled': False}, + }, + 'org.openedx.learning.xblock.skill.verified.v1': { + 'learning-xblock-skill-verified': + {'event_key_field': 'xblock_info.usage_key', + # .. toggle_name: ENABLE_SEND_XBLOCK_SKILL_VERIFIED_EVENTS_OVER_BUS + # .. toggle_implementation: DjangoSetting + # .. toggle_default: False + # .. toggle_description: Enables sending xblock_skill_verified events over the event bus. + # .. toggle_use_cases: opt_in + # .. toggle_creation_date: 2023-09-18 + # .. toggle_warning: The default may be changed in a later release. See + # https://github.com/openedx/openedx-events/issues/265 + # .. toggle_tickets: https://github.com/openedx/openedx-events/issues/210 + 'enabled': False} + }, + # CMS events. These have to be copied over here because cms.common adds some derived entries as well, + # and the derivation fails if the keys are missing. If we ever remove the import of cms.common, we can remove these. + 'org.openedx.content_authoring.xblock.published.v1': { + 'course-authoring-xblock-lifecycle': + {'event_key_field': 'xblock_info.usage_key', 'enabled': False}, + }, + 'org.openedx.content_authoring.xblock.deleted.v1': { + 'course-authoring-xblock-lifecycle': + {'event_key_field': 'xblock_info.usage_key', 'enabled': False}, + }, + 'org.openedx.content_authoring.xblock.duplicated.v1': { + 'course-authoring-xblock-lifecycle': + {'event_key_field': 'xblock_info.usage_key', 'enabled': False}, + }, +} +derived_collection_entry('EVENT_BUS_PRODUCER_CONFIG', 'org.openedx.learning.certificate.created.v1', + 'learning-certificate-lifecycle', 'enabled') +derived_collection_entry('EVENT_BUS_PRODUCER_CONFIG', 'org.openedx.learning.certificate.revoked.v1', + 'learning-certificate-lifecycle', 'enabled') diff --git a/lms/envs/production.py b/lms/envs/production.py index 0b48d461bb13..794a7534a882 100644 --- a/lms/envs/production.py +++ b/lms/envs/production.py @@ -26,6 +26,7 @@ import django from django.core.exceptions import ImproperlyConfigured from edx_django_utils.plugins import add_plugins +from openedx_events.event_bus import merge_producer_configs from path import Path as path from openedx.core.djangoapps.plugins.constants import ProjectType, SettingsType @@ -1133,3 +1134,7 @@ def get_env_setting(setting): ############## NOTIFICATIONS EXPIRY ############## NOTIFICATIONS_EXPIRY = ENV_TOKENS.get('NOTIFICATIONS_EXPIRY', NOTIFICATIONS_EXPIRY) + +############## Event bus producer ############## +EVENT_BUS_PRODUCER_CONFIG = merge_producer_configs(EVENT_BUS_PRODUCER_CONFIG, + ENV_TOKENS.get('EVENT_BUS_PRODUCER_CONFIG', {})) From ed1369089d7b00d597f2584c88f25c60f9e881cb Mon Sep 17 00:00:00 2001 From: Rebecca Graber Date: Thu, 12 Oct 2023 13:54:43 -0400 Subject: [PATCH 2/7] fixup!: changes from review --- cms/djangoapps/contentstore/signals/handlers.py | 10 +++------- cms/envs/common.py | 13 +++++++------ common/djangoapps/student/handlers.py | 12 +++--------- lms/djangoapps/certificates/signals.py | 10 +++------- lms/envs/common.py | 11 +++++++---- 5 files changed, 23 insertions(+), 33 deletions(-) diff --git a/cms/djangoapps/contentstore/signals/handlers.py b/cms/djangoapps/contentstore/signals/handlers.py index 8f2c27a8eb99..b51a999b8171 100644 --- a/cms/djangoapps/contentstore/signals/handlers.py +++ b/cms/djangoapps/contentstore/signals/handlers.py @@ -168,7 +168,7 @@ def _determine_producer_config_for_signal_and_topic(signal, topic): Parameters signal (OpenEdxPublicSignal): The signal being sent to the event bus - topic (string): The topic to which the signal is being sent + topic (string): The topic to which the signal is being sent (without environment prefix) Returns True if the signal is enabled for that topic in EVENT_BUS_PRODUCER_CONFIG @@ -179,12 +179,8 @@ def _determine_producer_config_for_signal_and_topic(signal, topic): {}).get(signal.event_type, {}) topic_config = event_type_producer_configs.get(topic, {}) topic_setting = topic_config.get('enabled', None) - if topic_setting is True: - set_custom_attribute('producer_config_setting', 'True') - if topic_setting is False: - set_custom_attribute('producer_config_setting', 'False') - if topic_setting is None: - set_custom_attribute('producer_config_setting', 'Unset') + set_custom_attribute(f'producer_config_setting_{topic}_{signal.event_type}', + topic_setting if topic_setting is not None else 'Unset') return topic_setting diff --git a/cms/envs/common.py b/cms/envs/common.py index 823ae4048286..80cee91d3fdc 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -1808,7 +1808,7 @@ # alternative swagger generator for CMS API 'drf_spectacular', - 'openedx_events' + 'openedx_events', ] @@ -2805,8 +2805,10 @@ #### Event bus producing #### +def _should_send_xblock_events(settings): + return settings.FEATURES['ENABLE_SEND_XBLOCK_LIFECYCLE_EVENTS_OVER_BUS'] + # .. setting_name: EVENT_BUS_PRODUCER_CONFIG -# .. setting_default: {} # .. setting_description: Dictionary of event_types mapped to dictionaries of topic to topic-related configuration. # Each topic configuration dictionary contains # * `enabled`: a toggle denoting whether the event will be published to the topic. These should be annotated @@ -2815,15 +2817,13 @@ # * `event_key_field` which is a period-delimited string path to event data field to use as event key. # Note: The topic names should not include environment prefix as it will be dynamically added based on # EVENT_BUS_TOPIC_PREFIX setting. -def _should_send_xblock_events(settings): - return settings.FEATURES['ENABLE_SEND_XBLOCK_LIFECYCLE_EVENTS_OVER_BUS'] - EVENT_BUS_PRODUCER_CONFIG = { 'org.openedx.content_authoring.course.catalog_info.changed.v1': { 'course-catalog-info-changed': {'event_key_field': 'catalog_info.course_key', - # .. toggle_name: ENABLE_SEND_COURSE_CATALOG_INFO_CHANGED_EVENTS_OVER_BUS + # .. toggle_name: EVENT_BUS_PRODUCER_CONFIG['org.openedx.content_authoring.course.catalog_info.changed.v1'] + # ['course-catalog-info-changed']['enabled'] # .. toggle_implementation: DjangoSetting # .. toggle_default: False # .. toggle_description: if enabled, will publish COURSE_CATALOG_INFO_CHANGED events to the event bus on @@ -2858,6 +2858,7 @@ def _should_send_xblock_events(settings): }, } + derived_collection_entry('EVENT_BUS_PRODUCER_CONFIG', 'org.openedx.content_authoring.xblock.published.v1', 'course-authoring-xblock-lifecycle', 'enabled') derived_collection_entry('EVENT_BUS_PRODUCER_CONFIG', 'org.openedx.content_authoring.xblock.duplicated.v1', diff --git a/common/djangoapps/student/handlers.py b/common/djangoapps/student/handlers.py index c373524227f2..c712b8cf8a9d 100644 --- a/common/djangoapps/student/handlers.py +++ b/common/djangoapps/student/handlers.py @@ -21,7 +21,7 @@ def _determine_producer_config_for_signal_and_topic(signal, topic): Parameters signal (OpenEdxPublicSignal): The signal being sent to the event bus - topic (string): The topic to which the signal is being sent + topic (string): The topic to which the signal is being sent (without environment prefix) Returns True if the signal is enabled for that topic in EVENT_BUS_PRODUCER_CONFIG @@ -32,16 +32,10 @@ def _determine_producer_config_for_signal_and_topic(signal, topic): {}).get(signal.event_type, {}) topic_config = event_type_producer_configs.get(topic, {}) topic_setting = topic_config.get('enabled', None) - if topic_setting is True: - set_custom_attribute('producer_config_setting', 'True') - return - if topic_setting is False: - set_custom_attribute('producer_config_setting', 'False') - if topic_setting is None: - set_custom_attribute('producer_config_setting', 'Unset') + set_custom_attribute(f'producer_config_setting_{topic}_{signal.event_type}', + topic_setting if topic_setting is not None else 'Unset') return topic_setting - @receiver(COURSE_UNENROLLMENT_COMPLETED) def course_unenrollment_receiver(sender, signal, **kwargs): """ diff --git a/lms/djangoapps/certificates/signals.py b/lms/djangoapps/certificates/signals.py index fad7946cc8c3..d848afbcb66a 100644 --- a/lms/djangoapps/certificates/signals.py +++ b/lms/djangoapps/certificates/signals.py @@ -171,7 +171,7 @@ def _determine_producer_config_for_signal_and_topic(signal, topic): Parameters signal (OpenEdxPublicSignal): The signal being sent to the event bus - topic (string): The topic to which the signal is being sent + topic (string): The topic to which the signal is being sent (without environment prefix) Returns True if the signal is enabled for that topic in EVENT_BUS_PRODUCER_CONFIG @@ -182,12 +182,8 @@ def _determine_producer_config_for_signal_and_topic(signal, topic): {}).get(signal.event_type, {}) topic_config = event_type_producer_configs.get(topic, {}) topic_setting = topic_config.get('enabled', None) - if topic_setting is True: - set_custom_attribute('producer_config_setting', 'True') - if topic_setting is False: - set_custom_attribute('producer_config_setting', 'False') - if topic_setting is None: - set_custom_attribute('producer_config_setting', 'Unset') + set_custom_attribute(f'producer_config_setting_{topic}_{signal.event_type}', + topic_setting if topic_setting is not None else 'Unset') return topic_setting diff --git a/lms/envs/common.py b/lms/envs/common.py index e3ee4e630670..79ff6f927b1b 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -5401,9 +5401,9 @@ def _make_locale_paths(settings): # pylint: disable=missing-function-docstring def _should_send_certificate_events(settings): return settings.FEATURES['SEND_LEARNING_CERTIFICATE_LIFECYCLE_EVENTS_TO_BUS'] + #### Event bus producing #### # .. setting_name: EVENT_BUS_PRODUCER_CONFIG -# .. setting_default: {} # .. setting_description: Dictionary of event_types mapped to dictionaries of topic to topic-related configuration. # Each topic configuration dictionary contains # * `enabled`: a toggle denoting whether the event will be published to the topic. These should be annotated @@ -5424,7 +5424,8 @@ def _should_send_certificate_events(settings): 'org.openedx.learning.course.unenrollment.completed.v1': { 'course-unenrollment-lifecycle': {'event_key_field': 'enrollment.course.course_key', - # .. toggle_name: ENABLE_SEND_COURSE_UNENROLLMENT_COMPLETED_EVENTS_OVER_BUS + # .. toggle_name: EVENT_BUS_PRODUCER_CONFIG['org.openedx.learning.course.unenrollment.completed.v1'] + # ['course-unenrollment-lifecycle']['enabled'] # .. toggle_implementation: DjangoSetting # .. toggle_default: False # .. toggle_description: Enables sending COURSE_UNENROLLMENT_COMPLETED events over the event bus. @@ -5438,7 +5439,8 @@ def _should_send_certificate_events(settings): 'org.openedx.learning.xblock.skill.verified.v1': { 'learning-xblock-skill-verified': {'event_key_field': 'xblock_info.usage_key', - # .. toggle_name: ENABLE_SEND_XBLOCK_SKILL_VERIFIED_EVENTS_OVER_BUS + # .. toggle_name: EVENT_BUS_PRODUCER_CONFIG['org.openedx.learning.xblock.skill.verified.v1'] + # ['learning-xblock-skill-verified']['enabled'] # .. toggle_implementation: DjangoSetting # .. toggle_default: False # .. toggle_description: Enables sending xblock_skill_verified events over the event bus. @@ -5450,7 +5452,8 @@ def _should_send_certificate_events(settings): 'enabled': False} }, # CMS events. These have to be copied over here because cms.common adds some derived entries as well, - # and the derivation fails if the keys are missing. If we ever remove the import of cms.common, we can remove these. + # and the derivation fails if the keys are missing. If we ever fully decouple the lms and cms settings, + # we can remove these. 'org.openedx.content_authoring.xblock.published.v1': { 'course-authoring-xblock-lifecycle': {'event_key_field': 'xblock_info.usage_key', 'enabled': False}, From 8ffa831a23294c3ed1236af1be896bd652a65d91 Mon Sep 17 00:00:00 2001 From: Rebecca Graber Date: Thu, 12 Oct 2023 14:39:25 -0400 Subject: [PATCH 3/7] fixup!: changes from review --- .../contentstore/signals/handlers.py | 36 ++++--------------- common/djangoapps/student/handlers.py | 27 ++------------ lms/djangoapps/certificates/signals.py | 9 ++--- openedx/core/lib/events.py | 27 ++++++++++++++ 4 files changed, 40 insertions(+), 59 deletions(-) create mode 100644 openedx/core/lib/events.py diff --git a/cms/djangoapps/contentstore/signals/handlers.py b/cms/djangoapps/contentstore/signals/handlers.py index b51a999b8171..88458742612f 100644 --- a/cms/djangoapps/contentstore/signals/handlers.py +++ b/cms/djangoapps/contentstore/signals/handlers.py @@ -10,7 +10,6 @@ from django.core.cache import cache from django.db import transaction from django.dispatch import receiver -from edx_django_utils.monitoring import set_custom_attribute from edx_toggles.toggles import SettingToggle from opaque_keys.edx.keys import CourseKey from openedx_events.content_authoring.data import CourseCatalogData, CourseScheduleData @@ -20,6 +19,7 @@ XBLOCK_DUPLICATED, XBLOCK_PUBLISHED, ) +from openedx.core.lib.events import determine_producer_config_for_signal_and_topic from openedx_events.event_bus import get_producer from pytz import UTC @@ -160,38 +160,14 @@ def listen_for_course_publish(sender, course_key, **kwargs): # pylint: disable= transaction.on_commit(lambda: emit_catalog_info_changed_signal(course_key)) -def _determine_producer_config_for_signal_and_topic(signal, topic): - """ - Utility method to determine the setting for the given signal and topic in EVENT_BUS_PRODUCER_CONFIG - - Records to New Relic for later analysis. - - Parameters - signal (OpenEdxPublicSignal): The signal being sent to the event bus - topic (string): The topic to which the signal is being sent (without environment prefix) - - Returns - True if the signal is enabled for that topic in EVENT_BUS_PRODUCER_CONFIG - False if the signal is explicitly disabled for that topic in EVENT_BUS_PRODUCER_CONFIG - None if the signal/topic pair is not present in EVENT_BUS_PRODUCER_CONFIG - """ - event_type_producer_configs = getattr(settings, "EVENT_BUS_PRODUCER_CONFIG", - {}).get(signal.event_type, {}) - topic_config = event_type_producer_configs.get(topic, {}) - topic_setting = topic_config.get('enabled', None) - set_custom_attribute(f'producer_config_setting_{topic}_{signal.event_type}', - topic_setting if topic_setting is not None else 'Unset') - return topic_setting - - @receiver(COURSE_CATALOG_INFO_CHANGED) def listen_for_course_catalog_info_changed(sender, signal, **kwargs): """ Publish COURSE_CATALOG_INFO_CHANGED signals onto the event bus. """ # temporary: defer to EVENT_BUS_PRODUCER_CONFIG if present - producer_config_setting = _determine_producer_config_for_signal_and_topic(COURSE_CATALOG_INFO_CHANGED, - 'course-catalog-info-changed') + producer_config_setting = determine_producer_config_for_signal_and_topic(COURSE_CATALOG_INFO_CHANGED, + 'course-catalog-info-changed') if producer_config_setting is True: log.info("Producing course-catalog-info-changed event via config") return @@ -210,7 +186,7 @@ def listen_for_xblock_published(sender, signal, **kwargs): """ # temporary: defer to EVENT_BUS_PRODUCER_CONFIG if present topic = getattr(settings, "EVENT_BUS_XBLOCK_LIFECYCLE_TOPIC", "course-authoring-xblock-lifecycle") - producer_config_setting = _determine_producer_config_for_signal_and_topic(XBLOCK_PUBLISHED, topic) + producer_config_setting = determine_producer_config_for_signal_and_topic(XBLOCK_PUBLISHED, topic) if producer_config_setting is True: log.info("Producing xblock-published event via config") return @@ -230,7 +206,7 @@ def listen_for_xblock_deleted(sender, signal, **kwargs): """ # temporary: defer to EVENT_BUS_PRODUCER_CONFIG if present topic = getattr(settings, "EVENT_BUS_XBLOCK_LIFECYCLE_TOPIC", "course-authoring-xblock-lifecycle") - producer_config_setting = _determine_producer_config_for_signal_and_topic(XBLOCK_DELETED, topic) + producer_config_setting = determine_producer_config_for_signal_and_topic(XBLOCK_DELETED, topic) if producer_config_setting is True: log.info("Producing xblock-deleted event via config") return @@ -250,7 +226,7 @@ def listen_for_xblock_duplicated(sender, signal, **kwargs): """ # temporary: defer to EVENT_BUS_PRODUCER_CONFIG if present topic = getattr(settings, "EVENT_BUS_XBLOCK_LIFECYCLE_TOPIC", "course-authoring-xblock-lifecycle") - producer_config_setting = _determine_producer_config_for_signal_and_topic(XBLOCK_DUPLICATED, topic) + producer_config_setting = determine_producer_config_for_signal_and_topic(XBLOCK_DUPLICATED, topic) if producer_config_setting is True: log.info("Producing xblock-duplicated event via config") return diff --git a/common/djangoapps/student/handlers.py b/common/djangoapps/student/handlers.py index c712b8cf8a9d..d7d5eeee3ce0 100644 --- a/common/djangoapps/student/handlers.py +++ b/common/djangoapps/student/handlers.py @@ -3,46 +3,23 @@ """ from django.conf import settings from django.dispatch import receiver -from edx_django_utils.monitoring import set_custom_attribute from openedx_events.event_bus import get_producer from openedx_events.learning.signals import ( COURSE_UNENROLLMENT_COMPLETED, ) +from openedx.core.lib.events import determine_producer_config_for_signal_and_topic import logging log = logging.getLogger(__name__) -def _determine_producer_config_for_signal_and_topic(signal, topic): - """ - Utility method to determine the setting for the given signal and topic in EVENT_BUS_PRODUCER_CONFIG - - Records to New Relic for later analysis. - - Parameters - signal (OpenEdxPublicSignal): The signal being sent to the event bus - topic (string): The topic to which the signal is being sent (without environment prefix) - - Returns - True if the signal is enabled for that topic in EVENT_BUS_PRODUCER_CONFIG - False if the signal is explicitly disabled for that topic in EVENT_BUS_PRODUCER_CONFIG - None if the signal/topic pair is not present in EVENT_BUS_PRODUCER_CONFIG - """ - event_type_producer_configs = getattr(settings, "EVENT_BUS_PRODUCER_CONFIG", - {}).get(signal.event_type, {}) - topic_config = event_type_producer_configs.get(topic, {}) - topic_setting = topic_config.get('enabled', None) - set_custom_attribute(f'producer_config_setting_{topic}_{signal.event_type}', - topic_setting if topic_setting is not None else 'Unset') - return topic_setting - @receiver(COURSE_UNENROLLMENT_COMPLETED) def course_unenrollment_receiver(sender, signal, **kwargs): """ Removes user notification preference when user un-enrolls from the course """ topic = getattr(settings, "EVENT_BUS_ENROLLMENT_LIFECYCLE_TOPIC", "course-unenrollment-lifecycle") - producer_config_setting = _determine_producer_config_for_signal_and_topic(COURSE_UNENROLLMENT_COMPLETED, topic) + producer_config_setting = determine_producer_config_for_signal_and_topic(COURSE_UNENROLLMENT_COMPLETED, topic) if producer_config_setting is True: log.info("Producing unenrollment-event event via config") return diff --git a/lms/djangoapps/certificates/signals.py b/lms/djangoapps/certificates/signals.py index d848afbcb66a..b6858c144597 100644 --- a/lms/djangoapps/certificates/signals.py +++ b/lms/djangoapps/certificates/signals.py @@ -29,6 +29,7 @@ from lms.djangoapps.certificates.api import auto_certificate_generation_enabled from lms.djangoapps.verify_student.services import IDVerificationService from openedx.core.djangoapps.content.course_overviews.signals import COURSE_PACING_CHANGED +from openedx.core.lib.events import determine_producer_config_for_signal_and_topic from openedx.core.djangoapps.signals.signals import ( COURSE_GRADE_NOW_FAILED, COURSE_GRADE_NOW_PASSED, @@ -193,8 +194,8 @@ def listen_for_certificate_created_event(sender, signal, **kwargs): # pylint: d Publish `CERTIFICATE_CREATED` events to the event bus. """ # temporary: defer to EVENT_BUS_PRODUCER_CONFIG if present - producer_config_setting = _determine_producer_config_for_signal_and_topic(CERTIFICATE_CREATED, - 'learning-certificate-lifecycle') + producer_config_setting = determine_producer_config_for_signal_and_topic(CERTIFICATE_CREATED, + 'learning-certificate-lifecycle') if producer_config_setting is True: log.info("Producing certificate-created event via config") return @@ -215,8 +216,8 @@ def listen_for_certificate_revoked_event(sender, signal, **kwargs): # pylint: d Publish `CERTIFICATE_REVOKED` events to the event bus. """ # temporary: defer to EVENT_BUS_PRODUCER_CONFIG if present - producer_config_setting = _determine_producer_config_for_signal_and_topic(CERTIFICATE_REVOKED, - 'learning-certificate-lifecycle') + producer_config_setting = determine_producer_config_for_signal_and_topic(CERTIFICATE_REVOKED, + 'learning-certificate-lifecycle') if producer_config_setting is True: log.info("Producing certificate-revoked event via config") return diff --git a/openedx/core/lib/events.py b/openedx/core/lib/events.py new file mode 100644 index 000000000000..5301d5cfeb44 --- /dev/null +++ b/openedx/core/lib/events.py @@ -0,0 +1,27 @@ +"""Temporary method for use in rolling out a new event producer configuration.""" + +from django.conf import settings +from edx_django_utils.monitoring import set_custom_attribute + + +def determine_producer_config_for_signal_and_topic(signal, topic): + """ + Utility method to determine the setting for the given signal and topic in EVENT_BUS_PRODUCER_CONFIG + + Records to New Relic for later analysis. + + Parameters + signal (OpenEdxPublicSignal): The signal being sent to the event bus + topic (string): The topic to which the signal is being sent (without environment prefix) + + Returns + True if the signal is enabled for that topic in EVENT_BUS_PRODUCER_CONFIG + False if the signal is explicitly disabled for that topic in EVENT_BUS_PRODUCER_CONFIG + None if the signal/topic pair is not present in EVENT_BUS_PRODUCER_CONFIG + """ + event_type_producer_configs = getattr(settings, "EVENT_BUS_PRODUCER_CONFIG", + {}).get(signal.event_type, {}) + topic_config = event_type_producer_configs.get(topic, {}) + topic_setting = topic_config.get('enabled', None) + set_custom_attribute(f'producer_config_setting_{topic}_{signal.event_type}', + topic_setting if topic_setting is not None else 'Unset') From 9f3999be79f2b851ed6ddd294e7c2655592c2370 Mon Sep 17 00:00:00 2001 From: Rebecca Graber Date: Thu, 12 Oct 2023 15:05:47 -0400 Subject: [PATCH 4/7] fixup!: changes from review --- openedx/core/lib/events.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openedx/core/lib/events.py b/openedx/core/lib/events.py index 5301d5cfeb44..76015aa34aa6 100644 --- a/openedx/core/lib/events.py +++ b/openedx/core/lib/events.py @@ -25,3 +25,4 @@ def determine_producer_config_for_signal_and_topic(signal, topic): topic_setting = topic_config.get('enabled', None) set_custom_attribute(f'producer_config_setting_{topic}_{signal.event_type}', topic_setting if topic_setting is not None else 'Unset') + return topic_config From af4921fbca438c61fe5d0252ae8ed0520801e337 Mon Sep 17 00:00:00 2001 From: Rebecca Graber Date: Thu, 12 Oct 2023 15:08:47 -0400 Subject: [PATCH 5/7] fixup!: oops --- openedx/core/lib/events.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openedx/core/lib/events.py b/openedx/core/lib/events.py index 76015aa34aa6..bc90824d5119 100644 --- a/openedx/core/lib/events.py +++ b/openedx/core/lib/events.py @@ -25,4 +25,4 @@ def determine_producer_config_for_signal_and_topic(signal, topic): topic_setting = topic_config.get('enabled', None) set_custom_attribute(f'producer_config_setting_{topic}_{signal.event_type}', topic_setting if topic_setting is not None else 'Unset') - return topic_config + return topic_setting From 52a7705876698c0ea09611cc3f273307a0359e3a Mon Sep 17 00:00:00 2001 From: Rebecca Graber Date: Thu, 12 Oct 2023 15:36:33 -0400 Subject: [PATCH 6/7] fixup!: default --- cms/envs/common.py | 1 + lms/envs/common.py | 1 + 2 files changed, 2 insertions(+) diff --git a/cms/envs/common.py b/cms/envs/common.py index 80cee91d3fdc..a446a698fc26 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -2809,6 +2809,7 @@ def _should_send_xblock_events(settings): return settings.FEATURES['ENABLE_SEND_XBLOCK_LIFECYCLE_EVENTS_OVER_BUS'] # .. setting_name: EVENT_BUS_PRODUCER_CONFIG +# .. setting_default: all events disabled # .. setting_description: Dictionary of event_types mapped to dictionaries of topic to topic-related configuration. # Each topic configuration dictionary contains # * `enabled`: a toggle denoting whether the event will be published to the topic. These should be annotated diff --git a/lms/envs/common.py b/lms/envs/common.py index 79ff6f927b1b..99e79975ecaa 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -5404,6 +5404,7 @@ def _should_send_certificate_events(settings): #### Event bus producing #### # .. setting_name: EVENT_BUS_PRODUCER_CONFIG +# .. setting_default: all events disabled # .. setting_description: Dictionary of event_types mapped to dictionaries of topic to topic-related configuration. # Each topic configuration dictionary contains # * `enabled`: a toggle denoting whether the event will be published to the topic. These should be annotated From b5c74f846ae7a3bfd7df406ca665d081b21f2ed1 Mon Sep 17 00:00:00 2001 From: Rebecca Graber Date: Mon, 16 Oct 2023 08:17:50 -0400 Subject: [PATCH 7/7] fixup!: cleaning --- lms/envs/common.py | 3 ++- lms/envs/production.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lms/envs/common.py b/lms/envs/common.py index 99e79975ecaa..543eca533b8b 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -1040,7 +1040,7 @@ # .. toggle_tickets: 'https://github.com/edx/edx-platform/pull/29538' 'DISABLE_ALLOWED_ENROLLMENT_IF_ENROLLMENT_CLOSED': False, - # .. toggle_name: SEND_LEARNING_CERTIFICATE_LIFECYCLE_EVENTS_TO_BUS + # .. toggle_name: FEATURES['SEND_LEARNING_CERTIFICATE_LIFECYCLE_EVENTS_TO_BUS'] # .. toggle_implementation: SettingToggle # .. toggle_default: False # .. toggle_description: When True, the system will publish certificate lifecycle signals to the event bus. @@ -3316,6 +3316,7 @@ def _make_locale_paths(settings): # pylint: disable=missing-function-docstring # Notifications 'openedx.core.djangoapps.notifications', + 'openedx_events', ] ######################### CSRF ######################################### diff --git a/lms/envs/production.py b/lms/envs/production.py index 794a7534a882..1d7d4a5657c2 100644 --- a/lms/envs/production.py +++ b/lms/envs/production.py @@ -85,6 +85,7 @@ def get_env_setting(setting): 'MKTG_URL_LINK_MAP', 'MKTG_URL_OVERRIDES', 'REST_FRAMEWORK', + 'EVENT_BUS_PRODUCER_CONFIG', ] for key in KEYS_WITH_MERGED_VALUES: if key in __config_copy__: