From af84554e463db3158f83d91ac0abeb5b15dfd57f Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Thu, 13 Feb 2025 14:58:42 +0100 Subject: [PATCH 1/6] docs: address reviews of how-to docs Improve how-to docs based on reviews: - Remove duplicate event bus how-to - Add missing imports in sample code - Update in-line code docs to reflect latest updates - Fix broken links from event bus concrete implementation --- .../add-event-bus-support-to-an-event.rst | 2 +- ...-new-event-bus-concrete-implementation.rst | 4 +-- docs/how-tos/consume-an-event.rst | 3 +- docs/how-tos/create-a-new-event.rst | 14 ++++++--- docs/how-tos/index.rst | 1 - ...nt-bus-to-broadcast-and-consume-events.rst | 2 ++ .../in-line-code-annotations-for-an-event.rst | 31 +++++++++++++++++-- 7 files changed, 45 insertions(+), 12 deletions(-) diff --git a/docs/how-tos/add-event-bus-support-to-an-event.rst b/docs/how-tos/add-event-bus-support-to-an-event.rst index f0b76f0e..33c1eb0e 100644 --- a/docs/how-tos/add-event-bus-support-to-an-event.rst +++ b/docs/how-tos/add-event-bus-support-to-an-event.rst @@ -126,7 +126,7 @@ Run ``python manage.py generate_avro_schemas --help`` to see the available optio Step 5: Send the Event Across Services with the Event Bus ========================================================== -To validate that you can consume the event emitted by a service through the event bus, you can send the event across services. Here is an example of how you can send the event across services using the Redis event bus implementation following the `setup instructions in a Tutor environment`_. We recommend also following the :doc:`../how-tos/use-the-event-bus` to understand how to use the event bus in your environment. +To validate that you can consume the event emitted by a service through the event bus, you can send the event across services. Here is an example of how you can send the event across services using the Redis event bus implementation following the `setup instructions in a Tutor environment`_. We recommend also following :doc:`../how-tos/use-the-event-bus-to-broadcast-and-consume-events` to understand how to use the event bus in your environment. .. note:: If you implemented a custom serializer for a type in the :term:`Event Payload`, the custom serializer support must be included in both the producer and consumer sides before it can be used. diff --git a/docs/how-tos/add-new-event-bus-concrete-implementation.rst b/docs/how-tos/add-new-event-bus-concrete-implementation.rst index 7b22e26a..ec2400f1 100644 --- a/docs/how-tos/add-new-event-bus-concrete-implementation.rst +++ b/docs/how-tos/add-new-event-bus-concrete-implementation.rst @@ -25,14 +25,14 @@ At a high level, the consumer should be a process that takes the signals and eve The consumer class then needs to implement ``consume_indefinitely`` loop, which will stay running and listen to events as they come in. -We have included a utility function called `prepare_for_new_work_cycle <../../openedx_events/tooling.py#L323>`_ in openedx-events which needs to be called before processing any signal. Currently, it reconnects the db connection if required as well as clears RequestCache and there may be later, more comprehensive changes. These steps mimic some setup/teardown that is normally performed by Django in its request/response-based architecture. +We have included an utility function called `prepare_for_new_work_cycle `_ in openedx-events which needs to be called before processing any signal. Currently, it reconnects the db connection if required as well as clears RequestCache and there may be later, more comprehensive changes. These steps mimic some setup/teardown that is normally performed by Django in its request/response based architecture. Check out `consumer.py `_ in the event bus redis implementation. Abstraction Tickets ********************* -The known remaining work for a fully abstracted event bus is captured in the `Abstraction tickets `_ +The known remaining work for a fully abstracted event bus is captured in the `Abstraction tickets `_ **Maintenance chart** diff --git a/docs/how-tos/consume-an-event.rst b/docs/how-tos/consume-an-event.rst index 658bb75e..8ea10df3 100644 --- a/docs/how-tos/consume-an-event.rst +++ b/docs/how-tos/consume-an-event.rst @@ -88,7 +88,8 @@ Given the design of Open edX Events, you can include the events' definitions in .. code-block:: python - from openedx_events import send_event, COURSE_ENROLLMENT_CREATED + from openedx_events.learning.signals import COURSE_ENROLLMENT_CREATED + from openedx_events.learning.data import CourseData, CourseEnrollmentData, UserData, UserPersonalData def test_send_enrollment_data_to_webhook(self): # Trigger the event diff --git a/docs/how-tos/create-a-new-event.rst b/docs/how-tos/create-a-new-event.rst index 0be99d83..cab61916 100644 --- a/docs/how-tos/create-a-new-event.rst +++ b/docs/how-tos/create-a-new-event.rst @@ -177,8 +177,10 @@ The :term:`Event Definition` should be implemented in the corresponding subdomai # Location openedx_events/learning/signals.py # .. event_type: org.openedx.learning.course.enrollment.created.v1 # .. event_name: COURSE_ENROLLMENT_CREATED - # .. event_description: emitted when the user's enrollment process is completed. + # .. event_key_field: enrollment.course.course_key + # .. event_description: Emitted when the user enrolls in a course. # .. event_data: CourseEnrollmentData + # .. event_trigger_repository: openedx/edx-platform COURSE_ENROLLMENT_CREATED = OpenEdxPublicSignal( event_type="org.openedx.learning.course.enrollment.created.v1", data={ @@ -186,11 +188,13 @@ The :term:`Event Definition` should be implemented in the corresponding subdomai } ) -- The event definition should be documented using in-line documentation with at least ``event_type``, ``event_name``, ``event_description``, and ``event_data``. This will help consumers understand the event and react to it. See :doc:`../reference/in-line-code-annotations-for-an-event` for more information. +- The event definition should be documented using in-line documentation with at lest ``event_type``, ``event_name``, ``event_key_field``, ``event_description``, ``event_data`` and ``event_trigger_repository``. This will help consumers understand the event and react to it. See :doc:`../reference/in-line-code-annotations-for-an-event` for more information. - The :term:`Event Type` should be unique and follow the naming convention for event types specified in the :doc:`../decisions/0002-events-naming-and-versioning` ADR. This is used by consumers to identify the event. -- The ``event_name`` should be a constant that is used to identify the event in the code. See :doc:`../reference/naming-suggestions` for more information on naming events. +- The ``event_name`` should be a constant that is used to identify the event in the code. +- The ``event_key_field`` should be a field in the payload that uniquely identifies the event. This is used by consumers to identify the event. - The ``event_description`` should describe what the event is about and why it is triggered. - The ``event_data`` should be the payload class that is used to define the data that is included in the event. +- The ``event_trigger_repository`` should be the repository where the event is triggered. - The ``data`` dictionary should contain the payload class that is used to define the data that is included in the event. This will help consumers understand the event and react to it. Try using a descriptive name for the data field, but keep consistency with the payload class name. Avoid using suffixes like ``_data`` or ``_payload`` in the data field name. - The event should be an instance of the ``OpenEdxPublicSignal`` class to ensure that the event is consistent with the Open edX event framework. - Receivers should be able to access the event payload in their receivers to react to the event. @@ -204,7 +208,8 @@ Here is how the integration could look like: .. code-block:: python - # Location common/djangoapps/student/models.py + # Location common/djangoapps/student/models/course_enrollment.py + from openedx_events.learning.data import CourseData, CourseEnrollmentData, UserData, UserPersonalData from openedx_events.learning.signals import COURSE_ENROLLMENT_CREATED def enroll(cls, user, course_key, mode=None, **kwargs): @@ -214,6 +219,7 @@ Here is how the integration could look like: # Enrollment logic here ... # .. event_implemented_name: COURSE_ENROLLMENT_CREATED + # .. event_type: org.openedx.learning.course.enrollment.created.v1 COURSE_ENROLLMENT_CREATED.send_event( enrollment=CourseEnrollmentData( user=UserData( diff --git a/docs/how-tos/index.rst b/docs/how-tos/index.rst index 73f930c5..708ce3f9 100644 --- a/docs/how-tos/index.rst +++ b/docs/how-tos/index.rst @@ -9,5 +9,4 @@ How-tos consume-an-event add-event-bus-support-to-an-event use-the-event-bus-to-broadcast-and-consume-events - use-the-event-bus add-new-event-bus-concrete-implementation diff --git a/docs/how-tos/use-the-event-bus-to-broadcast-and-consume-events.rst b/docs/how-tos/use-the-event-bus-to-broadcast-and-consume-events.rst index a1fde367..d7b32d03 100644 --- a/docs/how-tos/use-the-event-bus-to-broadcast-and-consume-events.rst +++ b/docs/how-tos/use-the-event-bus-to-broadcast-and-consume-events.rst @@ -3,6 +3,8 @@ Use the Open edX Event Bus to Broadcast and Consume Events ========================================================== +.. note:: Be sure to check out how to make your Open edX Event event bus compatible in the :doc:`../how-tos/add-event-bus-support-to-an-event` guide. + After creating a new Open edX Event, you might need to send it across services instead of just within the same process. For this kind of use-cases, you might want to use the Open edX Event Bus. Here :doc:`../concepts/event-bus`, you can find useful information to start getting familiar with the Open edX Event Bus. The Open edX Event Bus is a key component of the Open edX architecture, enabling services to communicate without direct dependencies on each other. This guide provides an overview of how to use the event bus to broadcast Open edX Events to multiple services, allowing them to react to changes or actions in the system. diff --git a/docs/reference/in-line-code-annotations-for-an-event.rst b/docs/reference/in-line-code-annotations-for-an-event.rst index 7c79bb3f..1e9f35b1 100644 --- a/docs/reference/in-line-code-annotations-for-an-event.rst +++ b/docs/reference/in-line-code-annotations-for-an-event.rst @@ -21,11 +21,12 @@ Consider the following example: .. code-block:: python - # Location openedx_events/learning/signals.py # .. event_type: org.openedx.learning.course.enrollment.created.v1 # .. event_name: COURSE_ENROLLMENT_CREATED - # .. event_description: emitted when the user's enrollment process is completed. + # .. event_key_field: enrollment.course.course_key + # .. event_description: Emitted when the user enrolls in a course. # .. event_data: CourseEnrollmentData + # .. event_trigger_repository: openedx/edx-platform COURSE_ENROLLMENT_CREATED = OpenEdxPublicSignal( event_type="org.openedx.learning.course.enrollment.created.v1", data={ @@ -33,6 +34,31 @@ Consider the following example: } ) +When integrating this event into the service, add the following in-line code annotations to help developers find and understand the event: + +.. code-block:: python + + # .. event_implemented_name: COURSE_ENROLLMENT_CREATED + COURSE_ENROLLMENT_CREATED.send_event( + enrollment=CourseEnrollmentData( + user=UserData( + pii=UserPersonalData( + username=user.username, + email=user.email, + name=user.profile.name, + ), + id=user.id, + is_active=user.is_active, + ), + course=course_data, + mode=enrollment.mode, + is_active=enrollment.is_active, + creation_date=enrollment.created, + ) + ) + +Developers can refer to the in-line code annotations to understand the event's purpose and how it should be used. This makes it easier to work with the event and ensures that it is used correctly across services. + **Maintenance chart** +--------------+-------------------------------+----------------+--------------------------------+ @@ -40,4 +66,3 @@ Consider the following example: +--------------+-------------------------------+----------------+--------------------------------+ |2025-02-05 | Maria Grimaldi | Sumac |Pass. | +--------------+-------------------------------+----------------+--------------------------------+ - From 4d0fb4e1bb2d16faf5f9f40ed0ce1280289951de Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Fri, 14 Feb 2025 09:35:27 +0100 Subject: [PATCH 2/6] docs: add reference to new event annotations --- .../in-line-code-annotations-for-an-event.rst | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/docs/reference/in-line-code-annotations-for-an-event.rst b/docs/reference/in-line-code-annotations-for-an-event.rst index 1e9f35b1..81bebbf7 100644 --- a/docs/reference/in-line-code-annotations-for-an-event.rst +++ b/docs/reference/in-line-code-annotations-for-an-event.rst @@ -3,19 +3,23 @@ In-line Code Annotations for an Open edX Event When creating a new Open edX Event, you must document the event definition using in-line code annotations. These annotations provide a structured way to document the event's metadata, making it easier for developers to understand the event's purpose and how it should be used. -+----------------------------------+----------------------------------------------------------------------------------------------------------------------------------+ -| Annotation | Description | -+==================================+==================================================================================================================================+ -| event_type (Required) | Identifier across services of the event. Should follow the :doc:`../decisions/0002-events-naming-and-versioning` standard. | -+----------------------------------+----------------------------------------------------------------------------------------------------------------------------------+ -| event_name (Required) | Name of the variable storing the event instance. | -+----------------------------------+----------------------------------------------------------------------------------------------------------------------------------+ -| event_description (Required) | General description which includes when the event should be emitted. | -+----------------------------------+----------------------------------------------------------------------------------------------------------------------------------+ -| event_data (Required) | What type of class attribute the event sends. | -+----------------------------------+----------------------------------------------------------------------------------------------------------------------------------+ -| event_warnings (Optional) | Any warnings or considerations that should be taken into account when using the event. | -+----------------------------------+----------------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| Annotation | Description | ++=====================================+============================================================================================================================+ +| event_type (Required) | Identifier across services of the event. Should follow the :doc:`../decisions/0002-events-naming-and-versioning` standard. | ++-------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| event_name (Required) | Name of the variable storing the event instance. | ++-------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| event_key_field (Optional) | The field in the event data that uniquely identifies the event. | ++-------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| event_description (Required) | General description which includes when the event should be emitted. | ++-------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| event_data (Required) | What type of class attribute the event sends. | ++-------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| event_trigger_repository (Required) | The repository that triggers the event. This is useful to find the source of the event. | ++-------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| event_warnings (Optional) | Any warnings or considerations that should be taken into account when using the event. | ++-------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ Consider the following example: From 76d0c3e312d183460d379c82f3b8c098a9ee11e3 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Mon, 17 Feb 2025 09:14:09 +0100 Subject: [PATCH 3/6] docs: apply suggestions from code review Co-authored-by: Sarina Canelake --- docs/how-tos/add-new-event-bus-concrete-implementation.rst | 2 +- docs/how-tos/create-a-new-event.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/how-tos/add-new-event-bus-concrete-implementation.rst b/docs/how-tos/add-new-event-bus-concrete-implementation.rst index ec2400f1..e6502b4b 100644 --- a/docs/how-tos/add-new-event-bus-concrete-implementation.rst +++ b/docs/how-tos/add-new-event-bus-concrete-implementation.rst @@ -25,7 +25,7 @@ At a high level, the consumer should be a process that takes the signals and eve The consumer class then needs to implement ``consume_indefinitely`` loop, which will stay running and listen to events as they come in. -We have included an utility function called `prepare_for_new_work_cycle `_ in openedx-events which needs to be called before processing any signal. Currently, it reconnects the db connection if required as well as clears RequestCache and there may be later, more comprehensive changes. These steps mimic some setup/teardown that is normally performed by Django in its request/response based architecture. +We have included a utility function called `prepare_for_new_work_cycle `_ in openedx-events which needs to be called before processing any signal. Currently, it reconnects the db connection if required as well as clears RequestCache and there may be later, more comprehensive changes. These steps mimic some setup/teardown that is normally performed by Django in its request/response based architecture. Check out `consumer.py `_ in the event bus redis implementation. diff --git a/docs/how-tos/create-a-new-event.rst b/docs/how-tos/create-a-new-event.rst index cab61916..b7232fee 100644 --- a/docs/how-tos/create-a-new-event.rst +++ b/docs/how-tos/create-a-new-event.rst @@ -188,7 +188,7 @@ The :term:`Event Definition` should be implemented in the corresponding subdomai } ) -- The event definition should be documented using in-line documentation with at lest ``event_type``, ``event_name``, ``event_key_field``, ``event_description``, ``event_data`` and ``event_trigger_repository``. This will help consumers understand the event and react to it. See :doc:`../reference/in-line-code-annotations-for-an-event` for more information. +- The event definition should be documented using in-line documentation with at least ``event_type``, ``event_name``, ``event_key_field``, ``event_description``, ``event_data`` and ``event_trigger_repository``. This will help consumers understand the event and react to it. See :doc:`../reference/in-line-code-annotations-for-an-event` for more information. - The :term:`Event Type` should be unique and follow the naming convention for event types specified in the :doc:`../decisions/0002-events-naming-and-versioning` ADR. This is used by consumers to identify the event. - The ``event_name`` should be a constant that is used to identify the event in the code. - The ``event_key_field`` should be a field in the payload that uniquely identifies the event. This is used by consumers to identify the event. From 431217c7f750d685ea649a15ceda501a25786335 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Mon, 17 Feb 2025 09:16:30 +0100 Subject: [PATCH 4/6] refactor: add reference to in-line code annotation used in services --- .../in-line-code-annotations-for-an-event.rst | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/docs/reference/in-line-code-annotations-for-an-event.rst b/docs/reference/in-line-code-annotations-for-an-event.rst index 81bebbf7..fa340771 100644 --- a/docs/reference/in-line-code-annotations-for-an-event.rst +++ b/docs/reference/in-line-code-annotations-for-an-event.rst @@ -38,11 +38,19 @@ Consider the following example: } ) -When integrating this event into the service, add the following in-line code annotations to help developers find and understand the event: +In-line code annotations are also used when integrating the event into the service. + ++-------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ +| Annotation | Description | ++=====================================+============================================================================================================================+ +| event_implemented_name (Required) | Name of the event that is being implemented. Use the variable name of the event instance. | ++-------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ + +Consider the following example: .. code-block:: python - # .. event_implemented_name: COURSE_ENROLLMENT_CREATED + # .. event_implemented_name: COURSE_ENROLLMENT_CREATED COURSE_ENROLLMENT_CREATED.send_event( enrollment=CourseEnrollmentData( user=UserData( From d2031df9590adc613085a1df1fb7fb0e421592f1 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Tue, 18 Feb 2025 13:10:44 +0100 Subject: [PATCH 5/6] refactor: clarify where the event name usually comes from --- docs/how-tos/create-a-new-event.rst | 2 +- .../in-line-code-annotations-for-an-event.rst | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/how-tos/create-a-new-event.rst b/docs/how-tos/create-a-new-event.rst index b7232fee..6cd08fbc 100644 --- a/docs/how-tos/create-a-new-event.rst +++ b/docs/how-tos/create-a-new-event.rst @@ -190,7 +190,7 @@ The :term:`Event Definition` should be implemented in the corresponding subdomai - The event definition should be documented using in-line documentation with at least ``event_type``, ``event_name``, ``event_key_field``, ``event_description``, ``event_data`` and ``event_trigger_repository``. This will help consumers understand the event and react to it. See :doc:`../reference/in-line-code-annotations-for-an-event` for more information. - The :term:`Event Type` should be unique and follow the naming convention for event types specified in the :doc:`../decisions/0002-events-naming-and-versioning` ADR. This is used by consumers to identify the event. -- The ``event_name`` should be a constant that is used to identify the event in the code. +- The ``event_name`` should be the variable name storing the event instance used to trigger the event. The name of the variable usually matches the ``{Subject}_{Action}`` of the event type. See more about the name in the :doc:`../decisions/0002-events-naming-and-versioning` ADR. - The ``event_key_field`` should be a field in the payload that uniquely identifies the event. This is used by consumers to identify the event. - The ``event_description`` should describe what the event is about and why it is triggered. - The ``event_data`` should be the payload class that is used to define the data that is included in the event. diff --git a/docs/reference/in-line-code-annotations-for-an-event.rst b/docs/reference/in-line-code-annotations-for-an-event.rst index fa340771..8841c1d5 100644 --- a/docs/reference/in-line-code-annotations-for-an-event.rst +++ b/docs/reference/in-line-code-annotations-for-an-event.rst @@ -40,11 +40,11 @@ Consider the following example: In-line code annotations are also used when integrating the event into the service. -+-------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ -| Annotation | Description | -+=====================================+============================================================================================================================+ -| event_implemented_name (Required) | Name of the event that is being implemented. Use the variable name of the event instance. | -+-------------------------------------+----------------------------------------------------------------------------------------------------------------------------+ ++-----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Annotation | Description | ++===================================+============================================================================================================================================================+ +| event_implemented_name (Required) | Variable name storing the event instance used to trigger the event. The name of the variable usually matches the ``{Subject}_{Action}`` of the event type. | ++-----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+ Consider the following example: From 0988f47265a7a8cd6735c0513c86e1b132c3c75c Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Wed, 19 Feb 2025 17:54:22 +0100 Subject: [PATCH 6/6] refactor: remove duplicated doc about event bus --- docs/how-tos/use-the-event-bus.rst | 97 ------------------------------ 1 file changed, 97 deletions(-) delete mode 100644 docs/how-tos/use-the-event-bus.rst diff --git a/docs/how-tos/use-the-event-bus.rst b/docs/how-tos/use-the-event-bus.rst deleted file mode 100644 index d45fe1d9..00000000 --- a/docs/how-tos/use-the-event-bus.rst +++ /dev/null @@ -1,97 +0,0 @@ -.. include:: ../common_refs.rst - -Use the Open edX Event Bus -############################ - -.. note:: Be sure to check out how to make your Open edX Event event bus compatible in the :doc:`../how-tos/add-event-bus-support-to-an-event` guide. - -After creating a new Open edX Event, you might need to send it across services instead of just within the same process. For this kind of use case, you might want to use the Open edX Event Bus. Here :doc:`../concepts/event-bus`, you can find useful information to start getting familiar with the Open edX Event Bus. - -The Open edX Event Bus is a key component of the Open edX architecture, enabling services to communicate without direct dependencies on each other. This guide provides an overview of how to use the event bus to broadcast Open edX Events to multiple services, allowing them to react to changes or actions in the system. - -Setup -******* - -To start producing and consuming events using the Open edX Event Bus, follow these steps: - -Step 1: Install the Open edX Event Bus Plugin -============================================== - -First, you need to install the Open edX Event Bus plugin in both the producing and consuming services. The plugin is a Django app that provides the necessary tools and configurations to produce and consume events. You can install the Redis plugin by running the following: - -.. code-block:: bash - - pip install edx-event-bus-redis - -.. note:: There are currently two community-supported concrete implementations of the Open edX Events Bus, Redis (`event-bus-redis`_) and Kafka (`event-bus-kafka`_). Redis is the default plugin for the Open edX Event Bus, but you can also use Kafka depending on your requirements. If none of these implementations meet your needs, you can implement your own plugin by following the :doc:`../how-tos/add-new-event-bus-concrete-implementation` documentation. - -Step 2: Configure the Event Bus -================================ - -In :doc:`../reference/event-bus-configurations`, you can find the available configurations for the event bus that are used to set up the event bus in the Open edX platform. - -In both the producing and consuming services, you need to configure the event bus. This includes setting up the :term:`event types `, :term:`topics `, and other configurations for the :term:`Event Bus` to work with. In this step, you should configure the producer and consumer classes for the event bus implementation you are using: - -- In the :term:`producing ` service, configure the producer class by setting the ``EVENT_BUS_PRODUCER`` setting. E.g., ``edx_event_bus_redis.create_producer``. -- In the :term:`consuming ` service, configure the consumer class by setting the ``EVENT_BUS_CONSUMER`` setting. E.g., ``edx_event_bus_redis.RedisEventConsumer``. - -By configuring these settings, you are telling Open edX Events which concrete implementation to use for producing and consuming events. - -Step 3: Produce the Event -=========================== - -In the producing/host application, include ``openedx_events`` in ``INSTALLED_APPS`` settings if necessary and add ``EVENT_BUS_PRODUCER_CONFIG`` setting. This setting is a dictionary of :term:`event types `, and dictionaries for :term:`Topic`-related configuration. Each :term:`Topic` configuration dictionary uses the topic as a key and contains: - -- A flag called ``enabled`` denotes whether the event will be published. -- The ``event_key_field`` is a period-delimited string path to the event data field used as an event key. - -.. note:: The topic names should not include the environment prefix, as it will be dynamically added based on the ``EVENT_BUS_TOPIC_PREFIX`` setting. - -Here's an example of the producer configuration which will publish events for XBlock published and deleted events to the specified :term:`Topic`: - -.. code-block:: python - - EVENT_BUS_PRODUCER_CONFIG = { - 'org.openedx.content_authoring.xblock.published.v1': { - 'content-authoring-xblock-lifecycle': {'event_key_field': 'xblock_info.usage_key', 'enabled': True}, - 'content-authoring-xblock-published': {'event_key_field': 'xblock_info.usage_key', 'enabled': True} - }, - 'org.openedx.content_authoring.xblock.deleted.v1': { - 'content-authoring-xblock-lifecycle': {'event_key_field': 'xblock_info.usage_key', 'enabled': True}, - }, - } - -The ``EVENT_BUS_PRODUCER_CONFIG`` is read by ``openedx_events`` and a handler (`general_signal_handler`_) is attached, which does the leg work of reading the configuration again and pushing to appropriate handlers. - -Step 4: Consume the Event -========================== - -In the consuming service, include ``openedx_events`` in ``INSTALLED_APPS`` settings if necessary and add ``EVENT_BUS_CONSUMER_CONFIG`` setting. Then, you should implement a receiver for the event type you are interested in. In this example, we are interested in the XBlock deleted event: - -.. code-block:: python - - @receiver(XBLOCK_DELETED) - def update_some_data(sender, **kwargs): - ... do things with the data in kwargs ... - ... log the event for debugging purposes ... - -Step 5: Run the Consumer -========================= - -To consume events, Open edX Events provides a management command called `consume_events`_ which can be called from the command line, how to run this command will depend on your deployment strategy. This command will start a process that listens to the message broker for new messages, processes them, and emits the event. Here is an example of a `consumer using Tutor hosted in Kubernetes`_. - -You can find more concrete examples of how to produce and consume events in the `event-bus-redis`_ documentation. - -.. _consume_events: https://github.com/openedx/openedx-events/blob/main/openedx_events/management/commands/consume_events.py -.. _run the consumer locally without tutor: https://github.com/openedx/event-bus-redis/?tab=readme-ov-file#testing-locally -.. _run the consumer locally with tutor: https://github.com/openedx/event-bus-redis/blob/main/docs/tutor_installation.rst#setup-example-with-openedx-course-discovery-and-tutor -.. _general_signal_handler: https://github.com/openedx/openedx-events/blob/main/openedx_events/apps.py#L16-L44 -.. _consumer using Tutor hosted in Kubernetes: https://github.com/openedx/tutor-contrib-aspects/blob/master/tutoraspects/patches/k8s-deployments#L535-L588 - -**Maintenance chart** - -+--------------+-------------------------------+----------------+--------------------------------+ -| Review Date | Reviewer | Release |Test situation | -+--------------+-------------------------------+----------------+--------------------------------+ -|2025-02-10 | Maria Grimaldi | Sumac |Pass. | -+--------------+-------------------------------+----------------+--------------------------------+