From 9b5a636d21df8a9ac09b7c24f4b893fd6d282f98 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Wed, 25 Dec 2024 17:54:45 +0100 Subject: [PATCH] docs: use example from openedx-events-2-zapier plugin --- docs/how-tos/consume-an-event.rst | 31 +++++++++++++++++------------ docs/how-tos/create-a-new-event.rst | 2 +- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/docs/how-tos/consume-an-event.rst b/docs/how-tos/consume-an-event.rst index d876ce68..8e1bdba2 100644 --- a/docs/how-tos/consume-an-event.rst +++ b/docs/how-tos/consume-an-event.rst @@ -21,7 +21,12 @@ Steps To consume an event within the same service, follow these steps: -Step 1: Install Open edX Events +Step 1: Understand the Use Case +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Before you start consuming an event, you should understand the use case and the event you want to consume. In this case, we want to send the enrollment data to a webhook when a user enrolls in a course. You should review the event definition and payload to understand the data that is being passed to the event receiver and how you can use it to implement the custom logic. + +Step 2: Install Open edX Events ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ First, add the ``openedx-events`` plugin into your dependencies so the library's environment recognizes the event you want to consume. You can install ``openedx-events`` by running: @@ -32,7 +37,7 @@ First, add the ``openedx-events`` plugin into your dependencies so the library's This will mainly make the events available for your CI/CD pipeline and local development environment. If you are using the Open edX platform, the library should be already be installed in the environment so no need to install it. -Step 2: Create a Event Receiver and Connect it to the Event +Step 3: Create a Event Receiver and Connect it to the Event ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ An :term:`Event Receiver` is simply a function that listens for a specific event and executes custom logic in response to the event being triggered. You can create an event receiver by using the Django signal receivers decorator. Here's an example of an event receiver that listens for the ``COURSE_ENROLLMENT_CREATED`` event and creates a notification preference for the user: @@ -43,11 +48,11 @@ An :term:`Event Receiver` is simply a function that listens for a specific event from django.dispatch import receiver @receiver(COURSE_ENROLLMENT_CREATED) - def create_notification_preference(signal, sender, enrollment, metadata, **kwargs): - # Custom logic to create a notification preference for the user + def send_enrollment_data_to_webhook(signal, sender, enrollment, metadata, **kwargs): + # Custom logic to send enrollment data to a webhook pass -- The Django dispatcher will call the ``create_notification_preference`` function when the ``COURSE_ENROLLMENT_CREATED`` event is triggered by using the ``receiver`` decorator. In this case, that would be every time a user enrolls in a course. +- The Django dispatcher will call the ``send_enrollment_data_to_webhook`` function when the ``COURSE_ENROLLMENT_CREATED`` event is triggered by using the ``receiver`` decorator. In this case, that would be every time a user enrolls in a course. - Consider using asynchronous tasks to handle the event processing to avoid blocking the main thread and improve performance. Also, make sure to handle exceptions and errors gracefully to avoid silent failures and improve debugging. You should also consider not creating a tight coupling between receivers and other services, if doing so is necessary consider using the event bus to broadcast the event. - When implementing the receiver, inspect the event payload to understand the data that is being passed to the event receiver by reviewing the ``data.py`` file of the event you are consuming. For example, the ``COURSE_ENROLLMENT_CREATED`` event has the following payload: @@ -64,7 +69,7 @@ An :term:`Event Receiver` is simply a function that listens for a specific event - This event has a single field called ``enrollment`` which is an instance of the ``CourseEnrollmentData`` class. You can review the ``CourseEnrollmentData`` class to understand the data that is available to you and how you can use it to implement the custom logic. - The ``metadata`` parameter contains the Open edX-specific metadata for the event, such as the event version and timestamp when the event was sent. You can use this metadata to understand more about the event and its context. -Step 3: Test the Event Receiver +Step 4: Test the Event Receiver ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Given the design of Open edX Events, you can include the events definitions in your test suite to ensure that the event receiver is working as expected. You can use the ``send_event`` method to trigger the event and test the event receiver. Here's an example of how you can test the event receiver: @@ -73,7 +78,7 @@ Given the design of Open edX Events, you can include the events definitions in y from openedx_events import send_event, COURSE_ENROLLMENT_CREATED - def test_create_notification_preference(): + def test_send_enrollment_data_to_webhook(self): # Trigger the event enrollment_data = CourseEnrollmentData( user=UserData( @@ -93,20 +98,20 @@ Given the design of Open edX Events, you can include the events definitions in y is_active=self.course_enrollment.is_active, creation_date=self.course_enrollment.created, ) + COURSE_ENROLLMENT_CREATED.send_event( enrollment=enrollment_data ) - # Assert that CourseNotificationPreference object was created with correct attributes - notification_preferences = CourseNotificationPreference.objects.all() - - self.assertEqual(notification_preferences.count(), 1) - self.assertEqual(notification_preferences[0].user, self.user) + # Assert that the request was sent to the webhook with the correct data - In the test suite, you can use the ``send_event`` method to trigger the event and pass the necessary data to the event receiver. In this case, we are passing the user, course and enrollment data to the event receiver as the triggering logic would do. -- After triggering the event, you can assert that the event receiver executed the custom logic as expected. In this case, we are checking that a ``CourseNotificationPreference`` object was created with the correct attributes. +- After triggering the event, you can assert that the event receiver executed the custom logic as expected. In this case, we are checking that the request was sent to the webhook with the correct data. + +You can review this example to understand how you can test the event receiver and ensure that the custom logic is executed when the event is triggered in the openedx-events-2-zapier plugin. This way you can ensure that the event receiver is working as expected and that the custom logic is executed when the event is triggered. If the event definition or payload changes in any way, you can catch the error in the test suite instead of in production. .. _Tutor: https://docs.tutor.edly.io/ .. _Django Signals Documentation: https://docs.djangoproject.com/en/4.2/topics/signals/ +.. _openedx-events-2-zapier: https://github.com/eduNEXT/openedx-events-2-zapier diff --git a/docs/how-tos/create-a-new-event.rst b/docs/how-tos/create-a-new-event.rst index 78ac041d..8c609817 100644 --- a/docs/how-tos/create-a-new-event.rst +++ b/docs/how-tos/create-a-new-event.rst @@ -56,7 +56,7 @@ Before contributing a new event, it is important to propose the event to the com In our example our use case proposal could be: - I want to add an event that will be triggered when a user enrolls in a course from the course about page. This event will be useful for services that need to send notifications to the user when they enroll in a course. + I want to add an event that will be triggered when a user enrolls in a course from the course about page. This event will be useful for services that need to send the enrollment data to external services for further processing. If you are confident that the event is beneficial to the community, you can proceed to the next steps and implement the event.