Skip to content

Commit

Permalink
feat: remove manual sends of events (#33642)
Browse files Browse the repository at this point in the history
  • Loading branch information
Rebecca Graber authored Nov 3, 2023
1 parent 9ba9935 commit ddabba4
Show file tree
Hide file tree
Showing 9 changed files with 19 additions and 450 deletions.
88 changes: 1 addition & 87 deletions cms/djangoapps/contentstore/signals/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,7 @@
from edx_toggles.toggles import SettingToggle
from opaque_keys.edx.keys import CourseKey
from openedx_events.content_authoring.data import CourseCatalogData, CourseScheduleData
from openedx_events.content_authoring.signals import (
COURSE_CATALOG_INFO_CHANGED,
XBLOCK_DELETED,
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 openedx_events.content_authoring.signals import COURSE_CATALOG_INFO_CHANGED
from pytz import UTC

from cms.djangoapps.contentstore.courseware_index import (
Expand Down Expand Up @@ -160,85 +153,6 @@ def listen_for_course_publish(sender, course_key, **kwargs): # pylint: disable=
transaction.on_commit(lambda: emit_catalog_info_changed_signal(course_key))


@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']},
event_metadata=kwargs['metadata'],
)


@receiver(XBLOCK_PUBLISHED)
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"):
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']},
event_metadata=kwargs['metadata'],
)


@receiver(XBLOCK_DELETED)
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"):
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']},
event_metadata=kwargs['metadata'],
)


@receiver(XBLOCK_DUPLICATED)
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"):
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']},
event_metadata=kwargs['metadata'],
)


@receiver(SignalHandler.course_deleted)
def listen_for_course_delete(sender, course_key, **kwargs): # pylint: disable=unused-argument
"""
Expand Down
26 changes: 12 additions & 14 deletions cms/envs/devstack.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,24 +301,22 @@ def should_show_debug_toolbar(request): # lint-amnesty, pylint: disable=missing
CREDENTIALS_PUBLIC_SERVICE_URL = 'http://localhost:18150'

#################### Event bus backend ########################
# .. toggle_name: FEATURES['ENABLE_SEND_XBLOCK_EVENTS_OVER_BUS']
# .. toggle_implementation: DjangoSetting
# .. toggle_default: False
# .. toggle_description: Temporary configuration which enables sending xblock events over the event bus.
# .. toggle_use_cases: open_edx
# .. 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

EVENT_BUS_PRODUCER = 'edx_event_bus_redis.create_producer'
EVENT_BUS_REDIS_CONNECTION_URL = 'redis://:[email protected]:6379/'
EVENT_BUS_TOPIC_PREFIX = 'dev'
EVENT_BUS_CONSUMER = 'edx_event_bus_redis.RedisEventConsumer'
EVENT_BUS_XBLOCK_LIFECYCLE_TOPIC = 'course-authoring-xblock-lifecycle'
EVENT_BUS_ENROLLMENT_LIFECYCLE_TOPIC = 'course-authoring-enrollment-lifecycle'

course_catalog_event_setting = EVENT_BUS_PRODUCER_CONFIG['org.openedx.content_authoring.course.catalog_info.changed.v1']
course_catalog_event_setting['course-catalog-info-changed']['enabled'] = True

xblock_published_event_setting = EVENT_BUS_PRODUCER_CONFIG['org.openedx.content_authoring.xblock.published.v1']
xblock_published_event_setting['course-authoring-xblock-lifecycle']['enabled'] = True
xblock_deleted_event_setting = EVENT_BUS_PRODUCER_CONFIG['org.openedx.content_authoring.xblock.deleted.v1']
xblock_deleted_event_setting['course-authoring-xblock-lifecycle']['enabled'] = True
xblock_duplicated_event_setting = EVENT_BUS_PRODUCER_CONFIG['org.openedx.content_authoring.xblock.duplicated.v1']
xblock_duplicated_event_setting['course-authoring-xblock-lifecycle']['enabled'] = True


################# New settings must go ABOVE this line #################
########################################################################
Expand Down
34 changes: 0 additions & 34 deletions common/djangoapps/student/handlers.py

This file was deleted.

67 changes: 0 additions & 67 deletions common/djangoapps/student/tests/test_handlers.py

This file was deleted.

31 changes: 1 addition & 30 deletions lms/djangoapps/certificates/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
This module contains various configuration settings via
waffle switches for the Certificates app.
"""

from edx_toggles.toggles import SettingToggle, WaffleSwitch
from edx_toggles.toggles import WaffleSwitch

# Namespace
WAFFLE_NAMESPACE = 'certificates'
Expand All @@ -15,31 +14,3 @@
# .. toggle_use_cases: open_edx
# .. toggle_creation_date: 2017-09-14
AUTO_CERTIFICATE_GENERATION = WaffleSwitch(f"{WAFFLE_NAMESPACE}.auto_certificate_generation", __name__)


# .. toggle_name: SEND_CERTIFICATE_CREATED_SIGNAL
# .. toggle_implementation: SettingToggle
# .. toggle_default: False
# .. 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
# .. toggle_tickets: TODO
SEND_CERTIFICATE_CREATED_SIGNAL = SettingToggle('SEND_CERTIFICATE_CREATED_SIGNAL', default=False, module_name=__name__)


# .. toggle_name: SEND_CERTIFICATE_REVOKED_SIGNAL
# .. toggle_implementation: SettingToggle
# .. toggle_default: False
# .. 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
# .. toggle_tickets: TODO
SEND_CERTIFICATE_REVOKED_SIGNAL = SettingToggle('SEND_CERTIFICATE_REVOKED_SIGNAL', default=False, module_name=__name__)
74 changes: 0 additions & 74 deletions lms/djangoapps/certificates/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,13 @@
"""

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
from common.djangoapps.student.signals import ENROLLMENT_TRACK_UPDATED
from lms.djangoapps.certificates.config import SEND_CERTIFICATE_CREATED_SIGNAL, SEND_CERTIFICATE_REVOKED_SIGNAL
from lms.djangoapps.certificates.generation_handler import (
CertificateGenerationNotAllowed,
generate_allowlist_certificate_task,
Expand All @@ -29,13 +25,11 @@
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,
LEARNER_NOW_VERIFIED
)
from openedx_events.learning.signals import CERTIFICATE_CREATED, CERTIFICATE_REVOKED

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -162,71 +156,3 @@ def _listen_for_enrollment_mode_change(sender, user, course_key, mode, **kwargs)
course_key,
)
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 (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(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',
event_key_field='certificate.course.course_key',
event_data={'certificate': kwargs['certificate']},
event_metadata=kwargs['metadata']
)


@receiver(CERTIFICATE_REVOKED)
def listen_for_certificate_revoked_event(sender, signal, **kwargs): # pylint: disable=unused-argument
"""
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',
event_key_field='certificate.course.course_key',
event_data={'certificate': kwargs['certificate']},
event_metadata=kwargs['metadata']
)
Loading

0 comments on commit ddabba4

Please sign in to comment.