feat: adding unenrollments to event bus (#33085)

* feat: adding unenrollments to event bus

* fix: quality fixes

* fix: tweaks to pass tests

* fix: more tweaks for testing

---------

Co-authored-by: John Nagro <jnagro@edx.org>
This commit is contained in:
Kira Miller
2023-08-28 09:08:49 -06:00
committed by GitHub
parent 2f8475c307
commit 776f4bf94e
4 changed files with 95 additions and 1 deletions

View File

@@ -303,11 +303,13 @@ CREDENTIALS_PUBLIC_SERVICE_URL = 'http://localhost:18150'
# in the LMS and CMS.
# .. 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://:password@edx.devstack.redis: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'
################# New settings must go ABOVE this line #################
########################################################################

View File

@@ -0,0 +1,25 @@
"""
Handlers for student
"""
from django.conf import settings
from django.dispatch import receiver
from openedx_events.event_bus import get_producer
from openedx_events.learning.signals import (
COURSE_UNENROLLMENT_COMPLETED,
)
@receiver(COURSE_UNENROLLMENT_COMPLETED)
def course_unenrollment_receiver(sender, signal, **kwargs):
"""
Removes user notification preference when user un-enrolls from the course
"""
if settings.FEATURES.get("ENABLE_SEND_ENROLLMENT_EVENTS_OVER_BUS"):
get_producer().send(
signal=COURSE_UNENROLLMENT_COMPLETED,
topic=getattr(settings, "EVENT_BUS_ENROLLMENT_LIFECYCLE_TOPIC", "course-unenrollment-lifecycle"),
event_key_field='enrollment.course.course_key',
event_data={'enrollment': kwargs.get('enrollment')},
event_metadata=kwargs.get('metadata')
)

View File

@@ -0,0 +1,67 @@
"""
Unit tests for event bus tests for course unenrollments
"""
import unittest
from datetime import datetime, timezone
from unittest import mock
from uuid import uuid4
from django.test.utils import override_settings
from common.djangoapps.student.handlers import course_unenrollment_receiver
from common.djangoapps.student.tests.factories import (
UserFactory,
CourseEnrollmentFactory,
)
from openedx_events.data import EventsMetadata
from openedx_events.learning.signals import COURSE_UNENROLLMENT_COMPLETED
from pytest import mark
@mark.django_db
class UnenrollmentEventBusTests(unittest.TestCase):
"""
Tests for unenrollment events that interact with the event bus.
"""
@override_settings(ENABLE_SEND_ENROLLMENT_EVENTS_OVER_BUS=False)
@mock.patch('common.djangoapps.student.handlers.get_producer', autospec=True)
def test_event_disabled(self, mock_producer):
"""
Test to verify that we do not push `CERTIFICATE_CREATED` events to the event bus if the
`SEND_CERTIFICATE_CREATED_SIGNAL` setting is disabled.
"""
course_unenrollment_receiver(None, None)
mock_producer.assert_not_called()
@override_settings(FEATURES={'ENABLE_SEND_ENROLLMENT_EVENTS_OVER_BUS': True})
@mock.patch('common.djangoapps.student.handlers.get_producer', autospec=True)
def test_event_enabled(self, mock_producer):
"""
Test to verify that we push `COURSE_UNENROLLMENT_COMPLETED` events to the event bus.
"""
user = UserFactory()
enrollment = CourseEnrollmentFactory(user=user)
event_metadata = EventsMetadata(
event_type=COURSE_UNENROLLMENT_COMPLETED.event_type,
id=uuid4(),
minorversion=0,
source='openedx/lms/web',
sourcehost='lms.test',
time=datetime.now(timezone.utc)
)
event_kwargs = {
'enrollment': enrollment,
'metadata': event_metadata
}
course_unenrollment_receiver(None, COURSE_UNENROLLMENT_COMPLETED, **event_kwargs)
# verify that the data sent to the event bus matches what we expect
print(mock_producer.return_value)
print(mock_producer.return_value.send.call_args)
data = mock_producer.return_value.send.call_args.kwargs
assert data['event_data']['enrollment'] == enrollment
assert data['topic'] == 'course-unenrollment-lifecycle'
assert data['event_key_field'] == 'enrollment.course.course_key'

View File

@@ -46,7 +46,7 @@ def on_user_course_unenrollment(enrollment, **kwargs):
preference = CourseNotificationPreference.objects.get(user__id=user_id, course_id=course_key)
preference.delete()
except ObjectDoesNotExist:
log.info(f'Notification Preference doesnot exist for {enrollment.user.pii.username} in {course_key}')
log.info(f'Notification Preference does not exist for {enrollment.user.pii.username} in {course_key}')
@receiver(USER_NOTIFICATION_REQUESTED)