From 7a96f5719e07d1d9222992872dc6dc00d0414014 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Thu, 10 Oct 2024 19:23:35 +0200 Subject: [PATCH 01/26] docs: update documentation references --- docs/concepts/events-vs-filters.rst | 80 +++++++++++++++++++++ docs/concepts/hooks-extension-framework.rst | 50 +++++++------ docs/concepts/index.rst | 2 + docs/concepts/openedx-events.rst | 75 +++++++++++++++++++ 4 files changed, 181 insertions(+), 26 deletions(-) create mode 100644 docs/concepts/events-vs-filters.rst create mode 100644 docs/concepts/openedx-events.rst diff --git a/docs/concepts/events-vs-filters.rst b/docs/concepts/events-vs-filters.rst new file mode 100644 index 00000000..8d2b1882 --- /dev/null +++ b/docs/concepts/events-vs-filters.rst @@ -0,0 +1,80 @@ +Events vs Filters +================= + +Open edX Events and Filters are two types of hooks that allow developers to +extend the functionality of the Open edX platform. They are defined in the +`openedx-events`_ and `openedx-filters`_ libraries respectively. + +.. _openedx-events: https://github.com/openedx/openedx-events +.. _openedx-filters: https://github.com/openedx/openedx-filters + +Events +------ + +Events are Open edX specific Django signals sent in specific places in the Open edX +platform. They allow external functions, known as signal handlers in the Django world, +to be executed when the event is triggered. These functions can extend the functionality of the platform or perform additional +processing based on the event data. + +For a more detailed explanation of Open edX Events, see the `Open edX Events`_ document. + +Filters +------- + +Filters are functions that can modify the behavior of the application by +altering input data or halting execution based on specific conditions. They +allow developers to implement application flow control based on their business +login or requirements without directly modifying the application code. + +For a more detailed explanation of Open edX Filters, see the `Open edX Filters`_ documentation. + +Differences between Events and Filters +-------------------------------------- + +Here are some key differences between Open edX Events and Filters: + ++-----------------+------------------------------------------------------------------------+-------------------------------------------------------------+-----+ +| | Events | Filters | | ++=================+========================================================================+=============================================================+=====+ +|| Purpose || Trigger custom actions or processing in response to || Modify the behavior of the application by intercepting and || | +|| || specific events or actions within the platform, || altering the data or parameters passed to a specific || | +|| || without affecting the application's flow. || function or method. || | ++-----------------+------------------------------------------------------------------------+-------------------------------------------------------------+-----+ +|| Usage || Used to **extend** functionality via signal handlers when an event is || Used to intercept and **modify** the input or output of a || | +|| || triggered. || component without directly modifying the component itself. || | ++-----------------+------------------------------------------------------------------------+-------------------------------------------------------------+-----+ +|| Definition || Defined using the `OpenEdxPublicSignal` class, which || Defined using the `OpenEdxFilter` class, which provides a || | +|| || provides a structured way to define the data and || way to define the filter function and the parameters it || | +|| || metadata associated with the event. || should receive. || | ++-----------------+------------------------------------------------------------------------+-------------------------------------------------------------+-----+ +|| Implementation || Implemented using Django signals, which allow || Implemented using an accumulative pipeline mechanism which || | +|| || developers to send and receive notifications within || takes a set of arguments and returns a modified set of || | +|| || a Django application. || arguments to the caller or raises exceptions during || | +|| || || processing. || | ++-----------------+------------------------------------------------------------------------+-------------------------------------------------------------+-----+ +|| Example || A custom event that triggers an email notification || A filter that modifies the data returned by a specific || | +|| || when a user enrolls in a course. || API endpoint to include additional information. || | ++-----------------+------------------------------------------------------------------------+-------------------------------------------------------------+-----+ + +When to use an Open edX Event? +------------------------------ + +Use an Open edX Event when you need to: + +- Trigger custom actions or processing in response to specific events or actions within the platform. +- Communicate or coordinate with other components or services based on specific events or actions. +- Synchronize data between different services or systems in response to specific events or actions. +- Notify users or external systems about specific events or actions within the platform. +- Integrate with external systems or services based on specific events or actions within the platform. + +When to use an Open edX Filter? +------------------------------- + +Use an Open edX Filter when: + +- Modify the input or output of a specific function or method without directly modifying the function itself. +- Intercept and modify the data or parameters passed to a specific component or service. +- Apply a series of transformations or validations to the input or output of a specific function or method. +- Enforce specific constraints or business rules on the input or output of a specific function or method. +- Handle exceptions or errors that occur during the processing of a specific function or method. +- Apply a set of filters to the input or output of a specific function or method based on specific conditions or criteria. diff --git a/docs/concepts/hooks-extension-framework.rst b/docs/concepts/hooks-extension-framework.rst index d298f319..b218d3ad 100644 --- a/docs/concepts/hooks-extension-framework.rst +++ b/docs/concepts/hooks-extension-framework.rst @@ -1,34 +1,38 @@ -Openedx Hooks Extension Framework -================================= +Hooks Extension Framework +========================= + +Overview +-------- To sustain the growth of the Open edX ecosystem, the business rules of the platform must be open for extension following the open-closed principle. This framework allows developers to do just that without needing to fork and modify -the main Open edX platform. +Open edX platform. + +Hooks: Open edX Events and Filters +---------------------------------- -Context -------- +Hooks are predefined places in the Open edX platform where externally defined +functions can take place. These functions may alter what the user +sees or experiences on the platform, while in other cases, they are purely informative. All +hooks are designed to be extended through Open edX plugins and configurations. -Hooks are predefined places in the Open edX project core where externally defined -functions can take place. In some cases, those functions can alter what the user -sees or experiences in the platform. Other cases are informative only. All cases -are meant to be extended using Open edX plugins and configuration. +Hooks can be of two types, events and filters. Events are, in essence, signals +sent in specific places whose listeners can extend functionality. While filters +are functions that can modify the behavior of the application. -Hooks can be of two types, events and filters. Events are in essence signals, in -that they are sent in specific application places and whose listeners can extend -functionality. On the other hand Filters can be used to act on data before -it is put back in the original application flow. In order to allow -extension developers to use the Events and Filters definitions on their plugins, -both kinds of hooks are defined in lightweight external libraries. +To allow extension developers to use the framework's definitions in their +implementations, both kinds of hooks are defined in lightweight external +libraries: * `openedx-filters`_ * `openedx-events`_ -Hooks are designed with stability in mind. The main goal is that developers can -use them to change the functionality of the platform as needed and still be able -to migrate to newer open releases with very little to no development effort. In -the case of the events, this is detailed in the `versioning ADR`_ and the -`payload ADR`_. +The main goal of the framework is that developers can use them to change the +functionality of the platform as needed and still be able to migrate to newer +open releases with very little to no development effort, so they're designed +with stability in mind, meaning that they are versioned and backward compatible +as much as possible. A longer description of the framework and its history can be found in `OEP 50`_. @@ -37,9 +41,3 @@ A longer description of the framework and its history can be found in `OEP 50`_. .. _payload ADR: https://github.com/eduNEXT/openedx-events/blob/main/docs/decisions/0003-events-payload.rst .. _openedx-filters: https://github.com/eduNEXT/openedx-filters .. _openedx-events: https://github.com/eduNEXT/openedx-events - -On the technical side events are implemented through django signals which makes -them run in the same python process as the service where this library is installed. -Furthermore, events block the running process. Listeners of an event are encouraged -to monitor the performance or use alternative arch patterns such as receiving the -event and defer to launching async tasks than do the slow processing. diff --git a/docs/concepts/index.rst b/docs/concepts/index.rst index cade1612..38a13d0f 100644 --- a/docs/concepts/index.rst +++ b/docs/concepts/index.rst @@ -6,3 +6,5 @@ Concepts :caption: Contents: hooks-extension-framework + openedx-events + events-vs-filters diff --git a/docs/concepts/openedx-events.rst b/docs/concepts/openedx-events.rst new file mode 100644 index 00000000..c6f82ccc --- /dev/null +++ b/docs/concepts/openedx-events.rst @@ -0,0 +1,75 @@ +Open edX Events +=============== + +In the context of Open edX, events provide a mechanism for extending the platform +by enabling developers to listen to specific Django signals emitted by various +services and respond accordingly. This allows for customized reactions to key +actions or changes within the platform, without requiring direct modifications +to the Open edX platform codebase. + +What are Open edX Events? +------------------------- + +An Open edX Event is a Open edX specific Django signal that is emitted by a service +when a specific action or event occurs. These signals are used to notify other +services or components of the platform that an event has taken place, allowing them +to respond accordingly. Events are defined using the ``OpenEdxPublicSignal`` class, +which provides a structured way to define the data and metadata associated with +the event along with other relevant information. + +Why are Open edX Events important? +---------------------------------- + +Open edX Events are a key component of the Hooks Extension Framework, which allows +developers to extend the functionality of the platform in a stable and maintainable +way. By triggering events for specific actions or changes within the platform, developers +can create event handlers that respond to these events and perform additional +actions or processing as needed. This enables a wide range of use cases, from +integrating with external systems to implementing custom business logic. + +How are Open edX Events used? +----------------------------- + +Developers can create handlers for Open edX Events by implementing Django signal +handlers that respond to specific events emitted by the platform. These signal +handlers can be registered using Django's signal mechanism, allowing them to +listen for events and execute custom logic in response. By defining events and +handlers in this way, developers can create modular, reusable components that +extend the functionality of the platform without requiring direct modifications +to the core codebase. + +How do Open edX Events work? +---------------------------- + +Open edX Events are implemented using Django signals, which provide a way to +send and receive notifications within a Django application. Due to this design, +Open edX Events closely follow the Django signal pattern, allowing developers to +leverage their existing knowledge of Django signals. + +The lifecycle of an Open edX Event can be summarized as follows: + +1. A service emits an Open edX Event (Open edX specific Django signal) triggered by a specific action or event. The event data includes information about the event, such as the event name, timestamp, and any additional metadata. +2. Registered signal handlers listening for the event are called in response to the signal being emitted. +3. The signal handler performs additional processing or trigger other actions based on the event data. +4. The event is considered complete once all registered signal handlers have executed. + +Here is an example of how that might look like with an existing event: + +1. A user enrolls in a course, `triggering the COURSE_ENROLLMENT_CREATED event`_. This event includes information about the user, course, and enrollment details. +2. A `signal handler listening`_ for the ``COURSE_ENROLLMENT_CREATED`` event is called and processes the event data. +3. The signal handler sends a notification to the user confirming their enrollment in the course. +4. The event is considered complete once the signal handler has finished processing the event. + +For a more detailed explanation of how Django signals work, refer to the `Django Signals Documentation`_. + +For more details on the following topics, see the corresponding links: + +- `Hooks Extension Framework`_: Overview of the Hooks Extension Framework. +- `Open edX Events Naming and Versioning`_: ADR defining the rules for naming and versioning Open edX Events. +- `Open edX Events Payload`_: ADR defining the payload structure for Open edX Events. +- `External Event Bus and Django Signal Events`_: ADR defining the relationship between internal and external events. + +.. _Hooks Extension Framework: https://open-edx-proposals.readthedocs.io/en/latest/oep-0050-hooks-extension-framework.html +.. _Django Signals Documentation: https://docs.djangoproject.com/en/4.2/topics/signals/ +.. _triggering the COURSE_ENROLLMENT_CREATED event: https://github.com/openedx/edx-platform/blob/master/common/djangoapps/student/models/course_enrollment.py#L777-L795 +.. _signal handler listening: https://github.com/openedx/edx-platform/blob/master/common/djangoapps/student/models/course_enrollment.py#L777-L795 From ffb64da7f09a47ca9dfe1d1043b3d82c5c245216 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Tue, 15 Oct 2024 10:59:11 +0200 Subject: [PATCH 02/26] fix: add missing references for links --- docs/concepts/events-vs-filters.rst | 4 +++- docs/concepts/openedx-events.rst | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/concepts/events-vs-filters.rst b/docs/concepts/events-vs-filters.rst index 8d2b1882..d0b7871d 100644 --- a/docs/concepts/events-vs-filters.rst +++ b/docs/concepts/events-vs-filters.rst @@ -16,7 +16,7 @@ platform. They allow external functions, known as signal handlers in the Django to be executed when the event is triggered. These functions can extend the functionality of the platform or perform additional processing based on the event data. -For a more detailed explanation of Open edX Events, see the `Open edX Events`_ document. +For a more detailed explanation of Open edX Events, see the rest of the Open edX Events documentation. Filters ------- @@ -28,6 +28,8 @@ login or requirements without directly modifying the application code. For a more detailed explanation of Open edX Filters, see the `Open edX Filters`_ documentation. +.. _Open edX Filters: https://docs.openedx.org/projects/openedx-filters/en/latest/ + Differences between Events and Filters -------------------------------------- diff --git a/docs/concepts/openedx-events.rst b/docs/concepts/openedx-events.rst index c6f82ccc..9e14bfda 100644 --- a/docs/concepts/openedx-events.rst +++ b/docs/concepts/openedx-events.rst @@ -73,3 +73,6 @@ For more details on the following topics, see the corresponding links: .. _Django Signals Documentation: https://docs.djangoproject.com/en/4.2/topics/signals/ .. _triggering the COURSE_ENROLLMENT_CREATED event: https://github.com/openedx/edx-platform/blob/master/common/djangoapps/student/models/course_enrollment.py#L777-L795 .. _signal handler listening: https://github.com/openedx/edx-platform/blob/master/common/djangoapps/student/models/course_enrollment.py#L777-L795 +.. _Open edX Events Naming and Versioning: https://github.com/openedx/openedx-events/blob/main/docs/decisions/0002-events-naming-and-versioning.rst +.. _Open edX Events Payload: https://github.com/openedx/openedx-events/blob/main/docs/decisions/0003-events-payload.rst +.. _External Event Bus and Django Signal Events: https://github.com/openedx/openedx-events/blob/main/docs/decisions/0004-external-event-bus-and-django-signal-events.rst From 9dfd3a3208e81e9887f8b3061f7b0db7d2362e35 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Tue, 15 Oct 2024 05:55:49 -0400 Subject: [PATCH 03/26] docs: clarify events-vs-filters.rst --- docs/concepts/events-vs-filters.rst | 75 ++++++++++++++--------------- 1 file changed, 36 insertions(+), 39 deletions(-) diff --git a/docs/concepts/events-vs-filters.rst b/docs/concepts/events-vs-filters.rst index d0b7871d..d157ae65 100644 --- a/docs/concepts/events-vs-filters.rst +++ b/docs/concepts/events-vs-filters.rst @@ -11,20 +11,18 @@ extend the functionality of the Open edX platform. They are defined in the Events ------ -Events are Open edX specific Django signals sent in specific places in the Open edX -platform. They allow external functions, known as signal handlers in the Django world, -to be executed when the event is triggered. These functions can extend the functionality of the platform or perform additional -processing based on the event data. +Events are Open edX-specific Django signals sent in specific places in the Open edX +platform. Signal handlers can then be hooked into these signals to perform additional processing based on the event data. For a more detailed explanation of Open edX Events, see the rest of the Open edX Events documentation. Filters ------- -Filters are functions that can modify the behavior of the application by +Filters are functions that can modify the application's behavior by altering input data or halting execution based on specific conditions. They allow developers to implement application flow control based on their business -login or requirements without directly modifying the application code. +logic or requirements without directly modifying the application code. For a more detailed explanation of Open edX Filters, see the `Open edX Filters`_ documentation. @@ -35,48 +33,47 @@ Differences between Events and Filters Here are some key differences between Open edX Events and Filters: -+-----------------+------------------------------------------------------------------------+-------------------------------------------------------------+-----+ -| | Events | Filters | | -+=================+========================================================================+=============================================================+=====+ -|| Purpose || Trigger custom actions or processing in response to || Modify the behavior of the application by intercepting and || | -|| || specific events or actions within the platform, || altering the data or parameters passed to a specific || | -|| || without affecting the application's flow. || function or method. || | -+-----------------+------------------------------------------------------------------------+-------------------------------------------------------------+-----+ -|| Usage || Used to **extend** functionality via signal handlers when an event is || Used to intercept and **modify** the input or output of a || | -|| || triggered. || component without directly modifying the component itself. || | -+-----------------+------------------------------------------------------------------------+-------------------------------------------------------------+-----+ -|| Definition || Defined using the `OpenEdxPublicSignal` class, which || Defined using the `OpenEdxFilter` class, which provides a || | -|| || provides a structured way to define the data and || way to define the filter function and the parameters it || | -|| || metadata associated with the event. || should receive. || | -+-----------------+------------------------------------------------------------------------+-------------------------------------------------------------+-----+ -|| Implementation || Implemented using Django signals, which allow || Implemented using an accumulative pipeline mechanism which || | -|| || developers to send and receive notifications within || takes a set of arguments and returns a modified set of || | -|| || a Django application. || arguments to the caller or raises exceptions during || | -|| || || processing. || | -+-----------------+------------------------------------------------------------------------+-------------------------------------------------------------+-----+ -|| Example || A custom event that triggers an email notification || A filter that modifies the data returned by a specific || | -|| || when a user enrolls in a course. || API endpoint to include additional information. || | -+-----------------+------------------------------------------------------------------------+-------------------------------------------------------------+-----+ ++--------------------+------------------------------------------------------------------------+-------------------------------------------------------------+ +| | Events | Filters | ++====================+========================================================================+=============================================================+ +| **Purpose** | Notify when an action occurs in a specific part of the | Alter the application flow control. | +| | application. | | ++--------------------+------------------------------------------------------------------------+-------------------------------------------------------------+ +| **Usage** | Used to **extend** functionality via signal handlers when an event is | Used to intercept and **modify** the data used within a | +| | triggered. | component without directly modifying the application | +| | | itself. | ++--------------------+------------------------------------------------------------------------+-------------------------------------------------------------+ +| **Definition** | Defined using the `OpenEdxPublicSignal` class, which | Defined using the `OpenEdxFilter` class, which provides a | +| | provides a structured way to define the data and | way to define the filter function and the parameters it | +| | metadata associated with the event. | should receive. | ++--------------------+------------------------------------------------------------------------+-------------------------------------------------------------+ +| **Implementation** | Implemented using Django signals, which allow | Implemented using an accumulative pipeline mechanism which | +| | developers to send and receive notifications within | takes a set of arguments and returns a modified set | +| | a Django application. | to the caller or raises exceptions during | +| | | processing. | ++--------------------+------------------------------------------------------------------------+-------------------------------------------------------------+ +| **Example** | A custom event that triggers an email notification | A filter that modifies the data returned by a specific | +| | when a user enrolls in a course. | API endpoint to include additional information. | ++--------------------+------------------------------------------------------------------------+-------------------------------------------------------------+ When to use an Open edX Event? ------------------------------ Use an Open edX Event when you need to: -- Trigger custom actions or processing in response to specific events or actions within the platform. -- Communicate or coordinate with other components or services based on specific events or actions. -- Synchronize data between different services or systems in response to specific events or actions. -- Notify users or external systems about specific events or actions within the platform. -- Integrate with external systems or services based on specific events or actions within the platform. +- Trigger custom logic or processing in response to specific actions within the platform, e.g., updating a search index after a course block is modified. +- Communicate, synchronize, or coordinate with other components or services based on specific events or actions, e.g., send certificate data from LMS to credentials service to keep models up to date. +- Integrate with external systems or services based on specific events or actions within the platform, e.g., send user data to third-party services upon registration for marketing purposes. + +In summary, events can be used to integrate application components with each other or with external services, allowing them to communicate, synchronize, and perform additional actions when specific triggers occur. When to use an Open edX Filter? ------------------------------- Use an Open edX Filter when: -- Modify the input or output of a specific function or method without directly modifying the function itself. -- Intercept and modify the data or parameters passed to a specific component or service. -- Apply a series of transformations or validations to the input or output of a specific function or method. -- Enforce specific constraints or business rules on the input or output of a specific function or method. -- Handle exceptions or errors that occur during the processing of a specific function or method. -- Apply a set of filters to the input or output of a specific function or method based on specific conditions or criteria. +- Enrich the data or parameters passed to a specific component, e.g., fetch reusable LTI configurations from external plugins. +- Intercept and modify the input of a specific component, e.g., modify block structure so it renders additional data. +- Enforce specific constraints or business rules on the input or output of a specific function or method, e.g., prevent enrollment for non-authorized users. + +In summary, filters can be used when implementing application flow control that modifies the application's behavior, navigation, or user interaction flow during runtime. From 36f6aa85c575030638ac24ab0d0538ecd6a335be Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Tue, 15 Oct 2024 06:11:17 -0400 Subject: [PATCH 04/26] docs: remove unused references --- docs/concepts/hooks-extension-framework.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/concepts/hooks-extension-framework.rst b/docs/concepts/hooks-extension-framework.rst index b218d3ad..2b35853e 100644 --- a/docs/concepts/hooks-extension-framework.rst +++ b/docs/concepts/hooks-extension-framework.rst @@ -37,7 +37,5 @@ as much as possible. A longer description of the framework and its history can be found in `OEP 50`_. .. _OEP 50: https://open-edx-proposals.readthedocs.io/en/latest/oep-0050-hooks-extension-framework.html -.. _versioning ADR: https://github.com/eduNEXT/openedx-events/blob/main/docs/decisions/0002-events-naming-and-versioning.rst -.. _payload ADR: https://github.com/eduNEXT/openedx-events/blob/main/docs/decisions/0003-events-payload.rst .. _openedx-filters: https://github.com/eduNEXT/openedx-filters .. _openedx-events: https://github.com/eduNEXT/openedx-events From 27bf39225e0c8f17d2bc1c4e3041440789ecc888 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Tue, 15 Oct 2024 06:17:46 -0400 Subject: [PATCH 05/26] docs: Update openedx-events.rst --- docs/concepts/openedx-events.rst | 41 ++++++++++---------------------- 1 file changed, 13 insertions(+), 28 deletions(-) diff --git a/docs/concepts/openedx-events.rst b/docs/concepts/openedx-events.rst index 9e14bfda..40d5b4d2 100644 --- a/docs/concepts/openedx-events.rst +++ b/docs/concepts/openedx-events.rst @@ -4,27 +4,26 @@ Open edX Events In the context of Open edX, events provide a mechanism for extending the platform by enabling developers to listen to specific Django signals emitted by various services and respond accordingly. This allows for customized reactions to key -actions or changes within the platform, without requiring direct modifications -to the Open edX platform codebase. +actions or changes within the platform without modifying the Open edX platform codebase. What are Open edX Events? ------------------------- -An Open edX Event is a Open edX specific Django signal that is emitted by a service -when a specific action or event occurs. These signals are used to notify other +An Open edX Event is an Open edX-specific Django signal emitted by a service +when a specific action or event occurs. These signals notify other services or components of the platform that an event has taken place, allowing them to respond accordingly. Events are defined using the ``OpenEdxPublicSignal`` class, which provides a structured way to define the data and metadata associated with -the event along with other relevant information. +the event and other relevant information. Why are Open edX Events important? ---------------------------------- Open edX Events are a key component of the Hooks Extension Framework, which allows -developers to extend the functionality of the platform in a stable and maintainable +developers to extend the platform's functionality in a stable and maintainable way. By triggering events for specific actions or changes within the platform, developers can create event handlers that respond to these events and perform additional -actions or processing as needed. This enables a wide range of use cases, from +actions or processing as needed. This enables many use cases, from integrating with external systems to implementing custom business logic. How are Open edX Events used? @@ -33,10 +32,7 @@ How are Open edX Events used? Developers can create handlers for Open edX Events by implementing Django signal handlers that respond to specific events emitted by the platform. These signal handlers can be registered using Django's signal mechanism, allowing them to -listen for events and execute custom logic in response. By defining events and -handlers in this way, developers can create modular, reusable components that -extend the functionality of the platform without requiring direct modifications -to the core codebase. +listen for events and execute custom logic in response. How do Open edX Events work? ---------------------------- @@ -44,35 +40,24 @@ How do Open edX Events work? Open edX Events are implemented using Django signals, which provide a way to send and receive notifications within a Django application. Due to this design, Open edX Events closely follow the Django signal pattern, allowing developers to -leverage their existing knowledge of Django signals. +leverage their existing knowledge of the framework. The lifecycle of an Open edX Event can be summarized as follows: -1. A service emits an Open edX Event (Open edX specific Django signal) triggered by a specific action or event. The event data includes information about the event, such as the event name, timestamp, and any additional metadata. -2. Registered signal handlers listening for the event are called in response to the signal being emitted. -3. The signal handler performs additional processing or trigger other actions based on the event data. +1. A service emits an Open edX Event (an Open edX-specific Django signal) triggered by a specific action or event. The event data includes information about the event, such as the event name, timestamp, and other additional metadata. +2. Registered signal handlers listening to the event are called in response to the signal being emitted. +3. The signal handler performs additional processing or triggers other actions based on the event data. 4. The event is considered complete once all registered signal handlers have executed. Here is an example of how that might look like with an existing event: 1. A user enrolls in a course, `triggering the COURSE_ENROLLMENT_CREATED event`_. This event includes information about the user, course, and enrollment details. 2. A `signal handler listening`_ for the ``COURSE_ENROLLMENT_CREATED`` event is called and processes the event data. -3. The signal handler sends a notification to the user confirming their enrollment in the course. +3. The signal handler sends a notification to the user's email confirming their enrollment in the course. 4. The event is considered complete once the signal handler has finished processing the event. -For a more detailed explanation of how Django signals work, refer to the `Django Signals Documentation`_. +The `Django Signals Documentation`_ provides a more detailed explanation of how Django signals work. -For more details on the following topics, see the corresponding links: - -- `Hooks Extension Framework`_: Overview of the Hooks Extension Framework. -- `Open edX Events Naming and Versioning`_: ADR defining the rules for naming and versioning Open edX Events. -- `Open edX Events Payload`_: ADR defining the payload structure for Open edX Events. -- `External Event Bus and Django Signal Events`_: ADR defining the relationship between internal and external events. - -.. _Hooks Extension Framework: https://open-edx-proposals.readthedocs.io/en/latest/oep-0050-hooks-extension-framework.html .. _Django Signals Documentation: https://docs.djangoproject.com/en/4.2/topics/signals/ .. _triggering the COURSE_ENROLLMENT_CREATED event: https://github.com/openedx/edx-platform/blob/master/common/djangoapps/student/models/course_enrollment.py#L777-L795 .. _signal handler listening: https://github.com/openedx/edx-platform/blob/master/common/djangoapps/student/models/course_enrollment.py#L777-L795 -.. _Open edX Events Naming and Versioning: https://github.com/openedx/openedx-events/blob/main/docs/decisions/0002-events-naming-and-versioning.rst -.. _Open edX Events Payload: https://github.com/openedx/openedx-events/blob/main/docs/decisions/0003-events-payload.rst -.. _External Event Bus and Django Signal Events: https://github.com/openedx/openedx-events/blob/main/docs/decisions/0004-external-event-bus-and-django-signal-events.rst From 49ae1afe552b48b211828b0bc78d0cde3bec44b7 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Tue, 15 Oct 2024 12:34:26 +0200 Subject: [PATCH 06/26] fix: remove trailing spaces --- docs/concepts/events-vs-filters.rst | 4 ++-- docs/concepts/openedx-events.rst | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/concepts/events-vs-filters.rst b/docs/concepts/events-vs-filters.rst index d157ae65..b805e02b 100644 --- a/docs/concepts/events-vs-filters.rst +++ b/docs/concepts/events-vs-filters.rst @@ -41,7 +41,7 @@ Here are some key differences between Open edX Events and Filters: +--------------------+------------------------------------------------------------------------+-------------------------------------------------------------+ | **Usage** | Used to **extend** functionality via signal handlers when an event is | Used to intercept and **modify** the data used within a | | | triggered. | component without directly modifying the application | -| | | itself. | +| | | itself. | +--------------------+------------------------------------------------------------------------+-------------------------------------------------------------+ | **Definition** | Defined using the `OpenEdxPublicSignal` class, which | Defined using the `OpenEdxFilter` class, which provides a | | | provides a structured way to define the data and | way to define the filter function and the parameters it | @@ -63,7 +63,7 @@ Use an Open edX Event when you need to: - Trigger custom logic or processing in response to specific actions within the platform, e.g., updating a search index after a course block is modified. - Communicate, synchronize, or coordinate with other components or services based on specific events or actions, e.g., send certificate data from LMS to credentials service to keep models up to date. -- Integrate with external systems or services based on specific events or actions within the platform, e.g., send user data to third-party services upon registration for marketing purposes. +- Integrate with external systems or services based on specific events or actions within the platform, e.g., send user data to third-party services upon registration for marketing purposes. In summary, events can be used to integrate application components with each other or with external services, allowing them to communicate, synchronize, and perform additional actions when specific triggers occur. diff --git a/docs/concepts/openedx-events.rst b/docs/concepts/openedx-events.rst index 40d5b4d2..bf61a906 100644 --- a/docs/concepts/openedx-events.rst +++ b/docs/concepts/openedx-events.rst @@ -32,7 +32,7 @@ How are Open edX Events used? Developers can create handlers for Open edX Events by implementing Django signal handlers that respond to specific events emitted by the platform. These signal handlers can be registered using Django's signal mechanism, allowing them to -listen for events and execute custom logic in response. +listen for events and execute custom logic in response. How do Open edX Events work? ---------------------------- From a6c3e639a3b5fb2498fc40cd402a5487e8da18c5 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Tue, 15 Oct 2024 12:40:25 +0200 Subject: [PATCH 07/26] docs: remove linebreaks to improve rendering --- docs/concepts/events-vs-filters.rst | 12 +++------ docs/concepts/hooks-extension-framework.rst | 24 ++++------------- docs/concepts/openedx-events.rst | 29 ++++----------------- 3 files changed, 13 insertions(+), 52 deletions(-) diff --git a/docs/concepts/events-vs-filters.rst b/docs/concepts/events-vs-filters.rst index b805e02b..63e7b475 100644 --- a/docs/concepts/events-vs-filters.rst +++ b/docs/concepts/events-vs-filters.rst @@ -1,9 +1,7 @@ Events vs Filters ================= -Open edX Events and Filters are two types of hooks that allow developers to -extend the functionality of the Open edX platform. They are defined in the -`openedx-events`_ and `openedx-filters`_ libraries respectively. +Open edX Events and Filters are two types of hooks that allow developers to extend the functionality of the Open edX platform. They are defined in the `openedx-events`_ and `openedx-filters`_ libraries respectively. .. _openedx-events: https://github.com/openedx/openedx-events .. _openedx-filters: https://github.com/openedx/openedx-filters @@ -11,18 +9,14 @@ extend the functionality of the Open edX platform. They are defined in the Events ------ -Events are Open edX-specific Django signals sent in specific places in the Open edX -platform. Signal handlers can then be hooked into these signals to perform additional processing based on the event data. +Events are Open edX-specific Django signals sent in specific places in the Open edX platform. Signal handlers can then be hooked into these signals to perform additional processing based on the event data. For a more detailed explanation of Open edX Events, see the rest of the Open edX Events documentation. Filters ------- -Filters are functions that can modify the application's behavior by -altering input data or halting execution based on specific conditions. They -allow developers to implement application flow control based on their business -logic or requirements without directly modifying the application code. +Filters are functions that can modify the application's behavior by altering input data or halting execution based on specific conditions. They allow developers to implement application flow control based on their business logic or requirements without directly modifying the application code. For a more detailed explanation of Open edX Filters, see the `Open edX Filters`_ documentation. diff --git a/docs/concepts/hooks-extension-framework.rst b/docs/concepts/hooks-extension-framework.rst index 2b35853e..b19d2547 100644 --- a/docs/concepts/hooks-extension-framework.rst +++ b/docs/concepts/hooks-extension-framework.rst @@ -4,35 +4,21 @@ Hooks Extension Framework Overview -------- -To sustain the growth of the Open edX ecosystem, the business rules of the -platform must be open for extension following the open-closed principle. This -framework allows developers to do just that without needing to fork and modify -Open edX platform. +To sustain the growth of the Open edX ecosystem, the business rules of the platform must be open for extension following the open-closed principle. This framework allows developers to do just that without needing to fork and modify Open edX platform. Hooks: Open edX Events and Filters ---------------------------------- -Hooks are predefined places in the Open edX platform where externally defined -functions can take place. These functions may alter what the user -sees or experiences on the platform, while in other cases, they are purely informative. All -hooks are designed to be extended through Open edX plugins and configurations. +Hooks are predefined places in the Open edX platform where externally defined functions can take place. These functions may alter what the user sees or experiences on the platform, while in other cases, they are purely informative. All hooks are designed to be extended through Open edX plugins and configurations. -Hooks can be of two types, events and filters. Events are, in essence, signals -sent in specific places whose listeners can extend functionality. While filters -are functions that can modify the behavior of the application. +Hooks can be of two types, events and filters. Events are, in essence, signals sent in specific places whose listeners can extend functionality. While filters are functions that can modify the behavior of the application. -To allow extension developers to use the framework's definitions in their -implementations, both kinds of hooks are defined in lightweight external -libraries: +To allow extension developers to use the framework's definitions in their implementations, both kinds of hooks are defined in lightweight external libraries: * `openedx-filters`_ * `openedx-events`_ -The main goal of the framework is that developers can use them to change the -functionality of the platform as needed and still be able to migrate to newer -open releases with very little to no development effort, so they're designed -with stability in mind, meaning that they are versioned and backward compatible -as much as possible. +The main goal of the framework is that developers can use them to change the functionality of the platform as needed and still be able to migrate to newer open releases with very little to no development effort, so they're designed with stability in mind, meaning that they are versioned and backward compatible as much as possible. A longer description of the framework and its history can be found in `OEP 50`_. diff --git a/docs/concepts/openedx-events.rst b/docs/concepts/openedx-events.rst index bf61a906..1a3efdad 100644 --- a/docs/concepts/openedx-events.rst +++ b/docs/concepts/openedx-events.rst @@ -1,46 +1,27 @@ Open edX Events =============== -In the context of Open edX, events provide a mechanism for extending the platform -by enabling developers to listen to specific Django signals emitted by various -services and respond accordingly. This allows for customized reactions to key -actions or changes within the platform without modifying the Open edX platform codebase. +In the context of Open edX, events provide a mechanism for extending the platform by enabling developers to listen to specific Django signals emitted by various services and respond accordingly. This allows for customized reactions to key actions or changes within the platform without modifying the Open edX platform codebase. What are Open edX Events? ------------------------- -An Open edX Event is an Open edX-specific Django signal emitted by a service -when a specific action or event occurs. These signals notify other -services or components of the platform that an event has taken place, allowing them -to respond accordingly. Events are defined using the ``OpenEdxPublicSignal`` class, -which provides a structured way to define the data and metadata associated with -the event and other relevant information. +An Open edX Event is an Open edX-specific Django signal emitted by a service when a specific action or event occurs. These signals notify other services or components of the platform that an event has taken place, allowing them to respond accordingly. Events are defined using the ``OpenEdxPublicSignal`` class, which provides a structured way to define the data and metadata associated with the event and other relevant information. Why are Open edX Events important? ---------------------------------- -Open edX Events are a key component of the Hooks Extension Framework, which allows -developers to extend the platform's functionality in a stable and maintainable -way. By triggering events for specific actions or changes within the platform, developers -can create event handlers that respond to these events and perform additional -actions or processing as needed. This enables many use cases, from -integrating with external systems to implementing custom business logic. +Open edX Events are a key component of the Hooks Extension Framework, which allows developers to extend the platform's functionality in a stable and maintainable way. By triggering events for specific actions or changes within the platform, developers can create event handlers that respond to these events and perform additional actions or processing as needed. This enables many use cases, from integrating with external systems to implementing custom business logic. How are Open edX Events used? ----------------------------- -Developers can create handlers for Open edX Events by implementing Django signal -handlers that respond to specific events emitted by the platform. These signal -handlers can be registered using Django's signal mechanism, allowing them to -listen for events and execute custom logic in response. +Developers can create handlers for Open edX Events by implementing Django signal handlers that respond to specific events emitted by the platform. These signal handlers can be registered using Django's signal mechanism, allowing them to listen for events and execute custom logic in response. How do Open edX Events work? ---------------------------- -Open edX Events are implemented using Django signals, which provide a way to -send and receive notifications within a Django application. Due to this design, -Open edX Events closely follow the Django signal pattern, allowing developers to -leverage their existing knowledge of the framework. +Open edX Events are implemented using Django signals, which provide a way to send and receive notifications within a Django application. Due to this design, Open edX Events closely follow the Django signal pattern, allowing developers to leverage their existing knowledge of the framework. The lifecycle of an Open edX Event can be summarized as follows: From a4c55a7167bdaa715074018b3ff491dfe155e92c Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Tue, 15 Oct 2024 12:44:17 +0200 Subject: [PATCH 08/26] fix: use correct reference for signal handler --- docs/concepts/openedx-events.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/concepts/openedx-events.rst b/docs/concepts/openedx-events.rst index 1a3efdad..cab8368c 100644 --- a/docs/concepts/openedx-events.rst +++ b/docs/concepts/openedx-events.rst @@ -41,4 +41,4 @@ The `Django Signals Documentation`_ provides a more detailed explanation of how .. _Django Signals Documentation: https://docs.djangoproject.com/en/4.2/topics/signals/ .. _triggering the COURSE_ENROLLMENT_CREATED event: https://github.com/openedx/edx-platform/blob/master/common/djangoapps/student/models/course_enrollment.py#L777-L795 -.. _signal handler listening: https://github.com/openedx/edx-platform/blob/master/common/djangoapps/student/models/course_enrollment.py#L777-L795 +.. _signal handler listening: https://github.com/openedx/edx-platform/blob/master/openedx/core/djangoapps/notifications/handlers.py#L38-L53 From e415b700198b29072649a82ae5a6c24c7379e3c0 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Tue, 15 Oct 2024 13:18:39 +0200 Subject: [PATCH 09/26] docs: add reference to how-to use open edx events --- docs/concepts/openedx-events.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/concepts/openedx-events.rst b/docs/concepts/openedx-events.rst index cab8368c..f11bd9eb 100644 --- a/docs/concepts/openedx-events.rst +++ b/docs/concepts/openedx-events.rst @@ -16,7 +16,9 @@ Open edX Events are a key component of the Hooks Extension Framework, which allo How are Open edX Events used? ----------------------------- -Developers can create handlers for Open edX Events by implementing Django signal handlers that respond to specific events emitted by the platform. These signal handlers can be registered using Django's signal mechanism, allowing them to listen for events and execute custom logic in response. +Developers can create handlers for Open edX Events by implementing Django signal handlers that respond to these events emitted by the platform. These signal handlers can be registered using Django's signal mechanism, allowing them to listen for events and execute custom logic in response. + +For more information on using Open edX Events, refer to the `Using Open edX Events`_ how-to guide. How do Open edX Events work? ---------------------------- @@ -39,6 +41,7 @@ Here is an example of how that might look like with an existing event: The `Django Signals Documentation`_ provides a more detailed explanation of how Django signals work. +.. _Using Open edX Events: how-tos/using-events .. _Django Signals Documentation: https://docs.djangoproject.com/en/4.2/topics/signals/ .. _triggering the COURSE_ENROLLMENT_CREATED event: https://github.com/openedx/edx-platform/blob/master/common/djangoapps/student/models/course_enrollment.py#L777-L795 .. _signal handler listening: https://github.com/openedx/edx-platform/blob/master/openedx/core/djangoapps/notifications/handlers.py#L38-L53 From 9791b5b584c1cd46b9382a76ab5741c3038688f8 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Tue, 15 Oct 2024 13:24:54 +0200 Subject: [PATCH 10/26] fix: use relative path for how-tos folder --- docs/concepts/openedx-events.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/concepts/openedx-events.rst b/docs/concepts/openedx-events.rst index f11bd9eb..2b196722 100644 --- a/docs/concepts/openedx-events.rst +++ b/docs/concepts/openedx-events.rst @@ -41,7 +41,7 @@ Here is an example of how that might look like with an existing event: The `Django Signals Documentation`_ provides a more detailed explanation of how Django signals work. -.. _Using Open edX Events: how-tos/using-events +.. _Using Open edX Events: ../how-tos/using-events .. _Django Signals Documentation: https://docs.djangoproject.com/en/4.2/topics/signals/ .. _triggering the COURSE_ENROLLMENT_CREATED event: https://github.com/openedx/edx-platform/blob/master/common/djangoapps/student/models/course_enrollment.py#L777-L795 .. _signal handler listening: https://github.com/openedx/edx-platform/blob/master/openedx/core/djangoapps/notifications/handlers.py#L38-L53 From b58de5681c0a2bedd0e9d26d8510fb112db4e0eb Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Tue, 15 Oct 2024 13:28:15 +0200 Subject: [PATCH 11/26] fix: use html file extension for reference --- docs/concepts/openedx-events.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/concepts/openedx-events.rst b/docs/concepts/openedx-events.rst index 2b196722..a4a7146e 100644 --- a/docs/concepts/openedx-events.rst +++ b/docs/concepts/openedx-events.rst @@ -41,7 +41,7 @@ Here is an example of how that might look like with an existing event: The `Django Signals Documentation`_ provides a more detailed explanation of how Django signals work. -.. _Using Open edX Events: ../how-tos/using-events +.. _Using Open edX Events: ../how-tos/using-events.html .. _Django Signals Documentation: https://docs.djangoproject.com/en/4.2/topics/signals/ .. _triggering the COURSE_ENROLLMENT_CREATED event: https://github.com/openedx/edx-platform/blob/master/common/djangoapps/student/models/course_enrollment.py#L777-L795 .. _signal handler listening: https://github.com/openedx/edx-platform/blob/master/openedx/core/djangoapps/notifications/handlers.py#L38-L53 From 6b1197630dd2dd3bf5c86c2b5b5cb172acb8d347 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Mon, 21 Oct 2024 09:07:34 -0400 Subject: [PATCH 12/26] docs: address PR reviews --- docs/concepts/events-vs-filters.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/concepts/events-vs-filters.rst b/docs/concepts/events-vs-filters.rst index 63e7b475..7804830a 100644 --- a/docs/concepts/events-vs-filters.rst +++ b/docs/concepts/events-vs-filters.rst @@ -9,7 +9,7 @@ Open edX Events and Filters are two types of hooks that allow developers to exte Events ------ -Events are Open edX-specific Django signals sent in specific places in the Open edX platform. Signal handlers can then be hooked into these signals to perform additional processing based on the event data. +Events are Open edX-specific Django signals sent in specific places on the Open edX platform. They allow developers to listen to these signals and perform additional processing based on the event data. For a more detailed explanation of Open edX Events, see the rest of the Open edX Events documentation. @@ -37,17 +37,17 @@ Here are some key differences between Open edX Events and Filters: | | triggered. | component without directly modifying the application | | | | itself. | +--------------------+------------------------------------------------------------------------+-------------------------------------------------------------+ -| **Definition** | Defined using the `OpenEdxPublicSignal` class, which | Defined using the `OpenEdxFilter` class, which provides a | -| | provides a structured way to define the data and | way to define the filter function and the parameters it | -| | metadata associated with the event. | should receive. | +| **Definition** | Defined using the `OpenEdxPublicSignal` class, which | Defined using the ``OpenEdxPublicFilter`` class, | +| | provides a structured way to define the data and | which provides a way to define the filter function | +| | metadata associated with the event. | and the parameters it should receive. | +--------------------+------------------------------------------------------------------------+-------------------------------------------------------------+ | **Implementation** | Implemented using Django signals, which allow | Implemented using an accumulative pipeline mechanism which | -| | developers to send and receive notifications within | takes a set of arguments and returns a modified set | -| | a Django application. | to the caller or raises exceptions during | +| | developers to send and receive notifications that an action happened | takes a set of arguments and returns a modified set | +| | within a Django application. | to the caller or raises exceptions during | | | | processing. | +--------------------+------------------------------------------------------------------------+-------------------------------------------------------------+ -| **Example** | A custom event that triggers an email notification | A filter that modifies the data returned by a specific | -| | when a user enrolls in a course. | API endpoint to include additional information. | +| **Use cases** | Send an email notification when a user enrolls in a course. | Include additional information in an API endpoint response.| +| | an email notification. | | +--------------------+------------------------------------------------------------------------+-------------------------------------------------------------+ When to use an Open edX Event? @@ -67,7 +67,7 @@ When to use an Open edX Filter? Use an Open edX Filter when: - Enrich the data or parameters passed to a specific component, e.g., fetch reusable LTI configurations from external plugins. -- Intercept and modify the input of a specific component, e.g., modify block structure so it renders additional data. +- Intercept and modify the input of a specific component, e.g., include "Edit" link to an HTML block if certain conditions are met. - Enforce specific constraints or business rules on the input or output of a specific function or method, e.g., prevent enrollment for non-authorized users. In summary, filters can be used when implementing application flow control that modifies the application's behavior, navigation, or user interaction flow during runtime. From 95d72d414aa02cbf73ba54f06ee6394080980b94 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Mon, 21 Oct 2024 09:24:24 -0400 Subject: [PATCH 13/26] docs: Update hooks-extension-framework.rst --- docs/concepts/hooks-extension-framework.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/concepts/hooks-extension-framework.rst b/docs/concepts/hooks-extension-framework.rst index b19d2547..434ac9bf 100644 --- a/docs/concepts/hooks-extension-framework.rst +++ b/docs/concepts/hooks-extension-framework.rst @@ -4,24 +4,25 @@ Hooks Extension Framework Overview -------- -To sustain the growth of the Open edX ecosystem, the business rules of the platform must be open for extension following the open-closed principle. This framework allows developers to do just that without needing to fork and modify Open edX platform. +Based on the `open-closed principle`_, this framework seeks to extend the platform in a maintainable way instead of modifying its core. The main objective of this framework is to leverage the existing extension capabilities provided by the plugin architecture, allowing developers to implement new features without making maintenance overwhelming. Hooks: Open edX Events and Filters ---------------------------------- -Hooks are predefined places in the Open edX platform where externally defined functions can take place. These functions may alter what the user sees or experiences on the platform, while in other cases, they are purely informative. All hooks are designed to be extended through Open edX plugins and configurations. +Hooks are a list of places in the Open edX platform where externally defined functions can take place. These functions may alter what the user sees or experiences on the platform, while in other cases, they are purely informative. All hooks are designed to be extended through Open edX plugins and configurations. -Hooks can be of two types, events and filters. Events are, in essence, signals sent in specific places whose listeners can extend functionality. While filters are functions that can modify the behavior of the application. +Hooks can be of two types: events and filters. Events are signals sent in specific places whose listeners can extend functionality, while filters are functions that can modify the application's behavior. To allow extension developers to use the framework's definitions in their implementations, both kinds of hooks are defined in lightweight external libraries: * `openedx-filters`_ * `openedx-events`_ -The main goal of the framework is that developers can use them to change the functionality of the platform as needed and still be able to migrate to newer open releases with very little to no development effort, so they're designed with stability in mind, meaning that they are versioned and backward compatible as much as possible. +The main goal of the framework is that developers can use it to change the platform's functionality as needed and still migrate to newer Open edX releases with little to no development effort. So, the framework is designed with stability in mind, meaning it is versioned and backward compatible as much as possible. A longer description of the framework and its history can be found in `OEP 50`_. .. _OEP 50: https://open-edx-proposals.readthedocs.io/en/latest/oep-0050-hooks-extension-framework.html .. _openedx-filters: https://github.com/eduNEXT/openedx-filters .. _openedx-events: https://github.com/eduNEXT/openedx-events +.. _open-closed principle: https://docs.openedx.org/projects/edx-platform/en/open-release-quince.master/concepts/extension_points.html From 88640cc267bbc4cd226362afb6e44c898bc26ad1 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Mon, 21 Oct 2024 09:31:13 -0400 Subject: [PATCH 14/26] docs: Update hooks-extension-framework.rst --- docs/concepts/hooks-extension-framework.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/concepts/hooks-extension-framework.rst b/docs/concepts/hooks-extension-framework.rst index 434ac9bf..3a3758eb 100644 --- a/docs/concepts/hooks-extension-framework.rst +++ b/docs/concepts/hooks-extension-framework.rst @@ -4,7 +4,7 @@ Hooks Extension Framework Overview -------- -Based on the `open-closed principle`_, this framework seeks to extend the platform in a maintainable way instead of modifying its core. The main objective of this framework is to leverage the existing extension capabilities provided by the plugin architecture, allowing developers to implement new features without making maintenance overwhelming. +Based on the `open-closed principle`_, this framework aims to extend the platform in a maintainable way without modifying its core. The main goal is to leverage the existing extension capabilities provided by the plugin architecture, allowing developers to implement new features to fit customer needs while reducing the need for core modifications and minimizing maintenance efforts. Hooks: Open edX Events and Filters ---------------------------------- From 9869fb71e75fe01e502fb0a5705dc74cf0febe3f Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Mon, 21 Oct 2024 11:58:32 -0400 Subject: [PATCH 15/26] docs: Update openedx-events.rst --- docs/concepts/openedx-events.rst | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/docs/concepts/openedx-events.rst b/docs/concepts/openedx-events.rst index a4a7146e..d48add7c 100644 --- a/docs/concepts/openedx-events.rst +++ b/docs/concepts/openedx-events.rst @@ -1,29 +1,20 @@ Open edX Events =============== -In the context of Open edX, events provide a mechanism for extending the platform by enabling developers to listen to specific Django signals emitted by various services and respond accordingly. This allows for customized reactions to key actions or changes within the platform without modifying the Open edX platform codebase. +Overview +-------- + +In the context of Open edX, events provide a mechanism for extending the platform by enabling developers to listen to Open edX-specific Django signals emitted by various services and respond accordingly. This allows for customized reactions to key actions or changes within the platform without modifying the Open edX platform codebase. What are Open edX Events? ------------------------- -An Open edX Event is an Open edX-specific Django signal emitted by a service when a specific action or event occurs. These signals notify other services or components of the platform that an event has taken place, allowing them to respond accordingly. Events are defined using the ``OpenEdxPublicSignal`` class, which provides a structured way to define the data and metadata associated with the event and other relevant information. - -Why are Open edX Events important? ----------------------------------- - -Open edX Events are a key component of the Hooks Extension Framework, which allows developers to extend the platform's functionality in a stable and maintainable way. By triggering events for specific actions or changes within the platform, developers can create event handlers that respond to these events and perform additional actions or processing as needed. This enables many use cases, from integrating with external systems to implementing custom business logic. - -How are Open edX Events used? ------------------------------ - -Developers can create handlers for Open edX Events by implementing Django signal handlers that respond to these events emitted by the platform. These signal handlers can be registered using Django's signal mechanism, allowing them to listen for events and execute custom logic in response. - -For more information on using Open edX Events, refer to the `Using Open edX Events`_ how-to guide. +An Open edX Event is an Open edX-specific Django signal emitted by a service when a specific action or event occurs. These signals notify other services or components of the platform that an event has taken place, allowing them to respond accordingly. How do Open edX Events work? ---------------------------- -Open edX Events are implemented using Django signals, which provide a way to send and receive notifications within a Django application. Due to this design, Open edX Events closely follow the Django signal pattern, allowing developers to leverage their existing knowledge of the framework. +Events are defined using the ``OpenEdxPublicSignal`` class, which provides a structured way to define the data and metadata associated with the event and other relevant information. This class is built on top of the ``Signal`` Django class, which provides a way to send and receive notifications when an action takes place within the Open edX ecosystem. Due to this design, Open edX Events follow the Django signal pattern, allowing developers to leverage their existing knowledge of the framework. The lifecycle of an Open edX Event can be summarized as follows: @@ -41,6 +32,13 @@ Here is an example of how that might look like with an existing event: The `Django Signals Documentation`_ provides a more detailed explanation of how Django signals work. +How are Open edX Events used? +----------------------------- + +Developers can create handlers for Open edX Events by implementing Django signal handlers that respond to these events emitted by the Open edX platform. These signal handlers can be registered using Django's signal mechanism, allowing them to listen for events and execute custom logic in response. + +For more information on using Open edX Events, refer to the `Using Open edX Events`_ how-to guide. + .. _Using Open edX Events: ../how-tos/using-events.html .. _Django Signals Documentation: https://docs.djangoproject.com/en/4.2/topics/signals/ .. _triggering the COURSE_ENROLLMENT_CREATED event: https://github.com/openedx/edx-platform/blob/master/common/djangoapps/student/models/course_enrollment.py#L777-L795 From a455a1eebc396258646888e9f14e526441caa962 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Mon, 21 Oct 2024 12:21:40 -0400 Subject: [PATCH 16/26] docs: Update openedx-events.rst --- docs/concepts/openedx-events.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/concepts/openedx-events.rst b/docs/concepts/openedx-events.rst index d48add7c..984b10c0 100644 --- a/docs/concepts/openedx-events.rst +++ b/docs/concepts/openedx-events.rst @@ -4,12 +4,12 @@ Open edX Events Overview -------- -In the context of Open edX, events provide a mechanism for extending the platform by enabling developers to listen to Open edX-specific Django signals emitted by various services and respond accordingly. This allows for customized reactions to key actions or changes within the platform without modifying the Open edX platform codebase. +In the context of Open edX, events provide a mechanism for extending the platform by enabling developers to listen to Open edX-specific Django signals emitted by various services and respond accordingly. This allows for customized reactions to key actions or changes within the platform without modifying the Open edX platform codebase. What are Open edX Events? ------------------------- -An Open edX Event is an Open edX-specific Django signal emitted by a service when a specific action or event occurs. These signals notify other services or components of the platform that an event has taken place, allowing them to respond accordingly. +An Open edX Event is an Open edX-specific Django signal emitted by a service when a specific action or event occurs. These signals notify other services or components of the platform that an event has taken place, allowing them to respond accordingly. Open edX Events are the current standard for communication between components and services within the Open edX ecosystem. How do Open edX Events work? ---------------------------- From f6b9640f2728a2ac1d5432758e2dd8ef8280a356 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Mon, 21 Oct 2024 13:05:15 -0400 Subject: [PATCH 17/26] docs: Update openedx-events.rst --- docs/concepts/openedx-events.rst | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/concepts/openedx-events.rst b/docs/concepts/openedx-events.rst index 984b10c0..8b3af78b 100644 --- a/docs/concepts/openedx-events.rst +++ b/docs/concepts/openedx-events.rst @@ -4,17 +4,23 @@ Open edX Events Overview -------- -In the context of Open edX, events provide a mechanism for extending the platform by enabling developers to listen to Open edX-specific Django signals emitted by various services and respond accordingly. This allows for customized reactions to key actions or changes within the platform without modifying the Open edX platform codebase. +Open edX Events provide a mechanism for extending the platform by enabling developers to listen to Open edX-specific Django signals emitted by various services and respond accordingly. This allows for customized reactions to actions or changes within the platform without modifying the Open edX platform codebase, with the main goal of minimizing maintenance efforts for the Open edX project and plugin maintainers. What are Open edX Events? ------------------------- -An Open edX Event is an Open edX-specific Django signal emitted by a service when a specific action or event occurs. These signals notify other services or components of the platform that an event has taken place, allowing them to respond accordingly. Open edX Events are the current standard for communication between components and services within the Open edX ecosystem. +Open edX Events are signals emitted by a service (e.g., LMS, CMS, or others) within the Open edX ecosystem to notify that an action has occurred. For example, a user may have registered, logged in, or created a course. + +These events are built on top of Django signals, inheriting their behavior while also incorporating metadata and actions specific to the Open edX ecosystem, making them uniquely suited for Open edX. Since they are essentially Django signals tailored to Open edX's specific needs, we can refer to `Django Signals Documentation`_ for a more detailed understanding of Open edX Events: + +Django includes a “signal dispatcher” which helps decoupled applications get notified when actions occur elsewhere in the framework. In a nutshell, signals allow certain senders to notify a set of receivers that some action has taken place. They’re especially useful when many pieces of code may be interested in the same events. + +Events are primarily used as a communication method between components within the same application process or with external services using the Event Bus technology, making them the standard communication mechanism within the Open edX ecosystem. How do Open edX Events work? ---------------------------- -Events are defined using the ``OpenEdxPublicSignal`` class, which provides a structured way to define the data and metadata associated with the event and other relevant information. This class is built on top of the ``Signal`` Django class, which provides a way to send and receive notifications when an action takes place within the Open edX ecosystem. Due to this design, Open edX Events follow the Django signal pattern, allowing developers to leverage their existing knowledge of the framework. +Open edX Events are implemented by a class called ``OpenEdxPublicSignal``, which inherits from Django’s ``Signals`` class and adds behaviors specific to the Open edX ecosystem. Thanks to this design, ``OpenEdxPublicSignal`` leverages the functionality of Django signals, allowing developers to apply their existing knowledge of the Django framework. The lifecycle of an Open edX Event can be summarized as follows: @@ -23,7 +29,7 @@ The lifecycle of an Open edX Event can be summarized as follows: 3. The signal handler performs additional processing or triggers other actions based on the event data. 4. The event is considered complete once all registered signal handlers have executed. -Here is an example of how that might look like with an existing event: +Here is an example of how that might look with an existing event: 1. A user enrolls in a course, `triggering the COURSE_ENROLLMENT_CREATED event`_. This event includes information about the user, course, and enrollment details. 2. A `signal handler listening`_ for the ``COURSE_ENROLLMENT_CREATED`` event is called and processes the event data. From cb44992f6aa5721120ab20d8a6edc5ddc98ef6b6 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Mon, 28 Oct 2024 13:06:57 +0100 Subject: [PATCH 18/26] refactor: address reviews --- docs/concepts/openedx-events.rst | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/docs/concepts/openedx-events.rst b/docs/concepts/openedx-events.rst index 8b3af78b..99a9f483 100644 --- a/docs/concepts/openedx-events.rst +++ b/docs/concepts/openedx-events.rst @@ -22,26 +22,28 @@ How do Open edX Events work? Open edX Events are implemented by a class called ``OpenEdxPublicSignal``, which inherits from Django’s ``Signals`` class and adds behaviors specific to the Open edX ecosystem. Thanks to this design, ``OpenEdxPublicSignal`` leverages the functionality of Django signals, allowing developers to apply their existing knowledge of the Django framework. -The lifecycle of an Open edX Event can be summarized as follows: +The event execution process follows these steps: -1. A service emits an Open edX Event (an Open edX-specific Django signal) triggered by a specific action or event. The event data includes information about the event, such as the event name, timestamp, and other additional metadata. -2. Registered signal handlers listening to the event are called in response to the signal being emitted. -3. The signal handler performs additional processing or triggers other actions based on the event data. -4. The event is considered complete once all registered signal handlers have executed. +1. An application component emits an event by calling the ``send_event`` method implemented by ``OpenEdxPublicEvents``, which calls the Django signal ``send`` method under the hood. +2. The class generates Open edX-specific metadata for the event on the fly, like the event version or the timestamp when the event was sent. The event receivers use this metadata during their processing. +3. We call the ``send`` method from Django signals, which allows us to use the same Django signals registry for receiver management. +4. The event receivers registered by the Django signals registry mechanism for the emitted event are executed. +5. Each event receivers performs additional processing or triggers other actions based on the event data. +6. The event is considered complete once all registered signal receivers have executed. -Here is an example of how that might look with an existing event: +Here is an example of an event in action: 1. A user enrolls in a course, `triggering the COURSE_ENROLLMENT_CREATED event`_. This event includes information about the user, course, and enrollment details. -2. A `signal handler listening`_ for the ``COURSE_ENROLLMENT_CREATED`` event is called and processes the event data. -3. The signal handler sends a notification to the user's email confirming their enrollment in the course. -4. The event is considered complete once the signal handler has finished processing the event. +2. A `signal receiver listening`_ for the ``COURSE_ENROLLMENT_CREATED`` event is called and processes the event data. +3. The signal receiver sends a notification to the user's email confirming their enrollment in the course. +4. The event is considered complete once the signal receiver has finished processing the event. The `Django Signals Documentation`_ provides a more detailed explanation of how Django signals work. How are Open edX Events used? ----------------------------- -Developers can create handlers for Open edX Events by implementing Django signal handlers that respond to these events emitted by the Open edX platform. These signal handlers can be registered using Django's signal mechanism, allowing them to listen for events and execute custom logic in response. +Developers can create receivers for Open edX Events by implementing Django signal receivers that respond to these events emitted by the Open edX platform. These signal receivers can be registered using Django's signal mechanism, allowing them to listen for events and execute custom logic in response. For more information on using Open edX Events, refer to the `Using Open edX Events`_ how-to guide. From 4b33fe2575240cf263b28a1e02c65cfc2aa4ad04 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Mon, 28 Oct 2024 08:55:15 -0400 Subject: [PATCH 19/26] docs: add why using the framework section --- docs/concepts/hooks-extension-framework.rst | 33 ++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/docs/concepts/hooks-extension-framework.rst b/docs/concepts/hooks-extension-framework.rst index 3a3758eb..3a36af49 100644 --- a/docs/concepts/hooks-extension-framework.rst +++ b/docs/concepts/hooks-extension-framework.rst @@ -11,7 +11,7 @@ Hooks: Open edX Events and Filters Hooks are a list of places in the Open edX platform where externally defined functions can take place. These functions may alter what the user sees or experiences on the platform, while in other cases, they are purely informative. All hooks are designed to be extended through Open edX plugins and configurations. -Hooks can be of two types: events and filters. Events are signals sent in specific places whose listeners can extend functionality, while filters are functions that can modify the application's behavior. +Hooks can be of two types: events and filters. Events are signals sent in specific places whose receivers can extend functionality, while filters are functions that can modify the application's behavior. To allow extension developers to use the framework's definitions in their implementations, both kinds of hooks are defined in lightweight external libraries: @@ -22,6 +22,37 @@ The main goal of the framework is that developers can use it to change the platf A longer description of the framework and its history can be found in `OEP 50`_. +Why use Open edX Hooks? +-------------------------------------- + +#. Stable and Maintainable Extensions + +The Hooks Extension Framework allows developers to extend the platform's functionality in a stable, maintainable, and decoupled way ensuring easier upgrades and long-term stability by removing the need to modify the core in an significant way. + +#. Contained Solution Implementation + +By avoiding core modifications, the framework promotes self-contained solutions, eliminating the need for custom code to coexist with core logic which lowers maintenance costs for extension developers. + +#. Leveraging the Open edX Plugin Extension Mechanism + +The framework allows developers to implement custom business logic and integrations directly in plugins. This keeps core modifications minimal, focusing maintenance and development efforts on plugins, where solutions can be built and maintained independently of the core platform. + +#. Standardization + +Both filters and events implementations implement an approach for adding additional features, such as communication between components or services, or backend flow control. With these standards in place, it’s easy to identify when and how to use the framework as a solution, ensuring a consistent and predictable approach to extending the platform. + +#. Reduce Fork Modifications + +The need to modify logic in forks is minimized, as most extensions can now be implementing using the framework, keeping forks closer to the core and easier to manage. + +#. Community Compatibility + +The framework allows for shorter and more agile contribution cycles. By adding standardized extension points, contributors avoid creating customer-specific logic, making development more community-friendly. + +#. Backward Compatibility + +Hooks are designed to be backward compatible, guaranteeing stability across releases and making it easier to upgrade without breaking existing functionality. + .. _OEP 50: https://open-edx-proposals.readthedocs.io/en/latest/oep-0050-hooks-extension-framework.html .. _openedx-filters: https://github.com/eduNEXT/openedx-filters .. _openedx-events: https://github.com/eduNEXT/openedx-events From 4550d6dd9d5969181bb1386a21a2ecd321c290b6 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Mon, 28 Oct 2024 09:25:51 -0400 Subject: [PATCH 20/26] docs: be consistent with framework name --- docs/concepts/hooks-extension-framework.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/concepts/hooks-extension-framework.rst b/docs/concepts/hooks-extension-framework.rst index 3a36af49..d90353ca 100644 --- a/docs/concepts/hooks-extension-framework.rst +++ b/docs/concepts/hooks-extension-framework.rst @@ -22,8 +22,8 @@ The main goal of the framework is that developers can use it to change the platf A longer description of the framework and its history can be found in `OEP 50`_. -Why use Open edX Hooks? --------------------------------------- +Why adopt the Hooks Extension Framework? +------------------------------------------- #. Stable and Maintainable Extensions From 44f930d5bed6819e7d4ddbf8ef325e7756e70767 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Mon, 28 Oct 2024 17:44:50 +0100 Subject: [PATCH 21/26] fix: add correct reference to handler --- docs/concepts/openedx-events.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/concepts/openedx-events.rst b/docs/concepts/openedx-events.rst index 99a9f483..4b0b62c1 100644 --- a/docs/concepts/openedx-events.rst +++ b/docs/concepts/openedx-events.rst @@ -50,4 +50,4 @@ For more information on using Open edX Events, refer to the `Using Open edX Even .. _Using Open edX Events: ../how-tos/using-events.html .. _Django Signals Documentation: https://docs.djangoproject.com/en/4.2/topics/signals/ .. _triggering the COURSE_ENROLLMENT_CREATED event: https://github.com/openedx/edx-platform/blob/master/common/djangoapps/student/models/course_enrollment.py#L777-L795 -.. _signal handler listening: https://github.com/openedx/edx-platform/blob/master/openedx/core/djangoapps/notifications/handlers.py#L38-L53 +.. _signal receiver listening: https://github.com/openedx/edx-platform/blob/master/openedx/core/djangoapps/notifications/handlers.py#L38-L53 From 83816cc7339c90c237409aa9bfb2a457d64af887 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Mon, 28 Oct 2024 18:29:54 +0100 Subject: [PATCH 22/26] fix: remove trailing space --- docs/concepts/hooks-extension-framework.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/concepts/hooks-extension-framework.rst b/docs/concepts/hooks-extension-framework.rst index d90353ca..a312c572 100644 --- a/docs/concepts/hooks-extension-framework.rst +++ b/docs/concepts/hooks-extension-framework.rst @@ -27,7 +27,7 @@ Why adopt the Hooks Extension Framework? #. Stable and Maintainable Extensions -The Hooks Extension Framework allows developers to extend the platform's functionality in a stable, maintainable, and decoupled way ensuring easier upgrades and long-term stability by removing the need to modify the core in an significant way. +The Hooks Extension Framework allows developers to extend the platform's functionality in a stable, maintainable, and decoupled way ensuring easier upgrades and long-term stability by removing the need to modify the core in an significant way. #. Contained Solution Implementation From 7428b891eb2a745757c829ac8ac7c97db4965824 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Thu, 31 Oct 2024 13:23:04 +0100 Subject: [PATCH 23/26] refactor!: drop duplicated documents in favor of centralized docs --- docs/concepts/events-vs-filters.rst | 73 --------------------- docs/concepts/hooks-extension-framework.rst | 59 ----------------- docs/concepts/index.rst | 2 - 3 files changed, 134 deletions(-) delete mode 100644 docs/concepts/events-vs-filters.rst delete mode 100644 docs/concepts/hooks-extension-framework.rst diff --git a/docs/concepts/events-vs-filters.rst b/docs/concepts/events-vs-filters.rst deleted file mode 100644 index 7804830a..00000000 --- a/docs/concepts/events-vs-filters.rst +++ /dev/null @@ -1,73 +0,0 @@ -Events vs Filters -================= - -Open edX Events and Filters are two types of hooks that allow developers to extend the functionality of the Open edX platform. They are defined in the `openedx-events`_ and `openedx-filters`_ libraries respectively. - -.. _openedx-events: https://github.com/openedx/openedx-events -.. _openedx-filters: https://github.com/openedx/openedx-filters - -Events ------- - -Events are Open edX-specific Django signals sent in specific places on the Open edX platform. They allow developers to listen to these signals and perform additional processing based on the event data. - -For a more detailed explanation of Open edX Events, see the rest of the Open edX Events documentation. - -Filters -------- - -Filters are functions that can modify the application's behavior by altering input data or halting execution based on specific conditions. They allow developers to implement application flow control based on their business logic or requirements without directly modifying the application code. - -For a more detailed explanation of Open edX Filters, see the `Open edX Filters`_ documentation. - -.. _Open edX Filters: https://docs.openedx.org/projects/openedx-filters/en/latest/ - -Differences between Events and Filters --------------------------------------- - -Here are some key differences between Open edX Events and Filters: - -+--------------------+------------------------------------------------------------------------+-------------------------------------------------------------+ -| | Events | Filters | -+====================+========================================================================+=============================================================+ -| **Purpose** | Notify when an action occurs in a specific part of the | Alter the application flow control. | -| | application. | | -+--------------------+------------------------------------------------------------------------+-------------------------------------------------------------+ -| **Usage** | Used to **extend** functionality via signal handlers when an event is | Used to intercept and **modify** the data used within a | -| | triggered. | component without directly modifying the application | -| | | itself. | -+--------------------+------------------------------------------------------------------------+-------------------------------------------------------------+ -| **Definition** | Defined using the `OpenEdxPublicSignal` class, which | Defined using the ``OpenEdxPublicFilter`` class, | -| | provides a structured way to define the data and | which provides a way to define the filter function | -| | metadata associated with the event. | and the parameters it should receive. | -+--------------------+------------------------------------------------------------------------+-------------------------------------------------------------+ -| **Implementation** | Implemented using Django signals, which allow | Implemented using an accumulative pipeline mechanism which | -| | developers to send and receive notifications that an action happened | takes a set of arguments and returns a modified set | -| | within a Django application. | to the caller or raises exceptions during | -| | | processing. | -+--------------------+------------------------------------------------------------------------+-------------------------------------------------------------+ -| **Use cases** | Send an email notification when a user enrolls in a course. | Include additional information in an API endpoint response.| -| | an email notification. | | -+--------------------+------------------------------------------------------------------------+-------------------------------------------------------------+ - -When to use an Open edX Event? ------------------------------- - -Use an Open edX Event when you need to: - -- Trigger custom logic or processing in response to specific actions within the platform, e.g., updating a search index after a course block is modified. -- Communicate, synchronize, or coordinate with other components or services based on specific events or actions, e.g., send certificate data from LMS to credentials service to keep models up to date. -- Integrate with external systems or services based on specific events or actions within the platform, e.g., send user data to third-party services upon registration for marketing purposes. - -In summary, events can be used to integrate application components with each other or with external services, allowing them to communicate, synchronize, and perform additional actions when specific triggers occur. - -When to use an Open edX Filter? -------------------------------- - -Use an Open edX Filter when: - -- Enrich the data or parameters passed to a specific component, e.g., fetch reusable LTI configurations from external plugins. -- Intercept and modify the input of a specific component, e.g., include "Edit" link to an HTML block if certain conditions are met. -- Enforce specific constraints or business rules on the input or output of a specific function or method, e.g., prevent enrollment for non-authorized users. - -In summary, filters can be used when implementing application flow control that modifies the application's behavior, navigation, or user interaction flow during runtime. diff --git a/docs/concepts/hooks-extension-framework.rst b/docs/concepts/hooks-extension-framework.rst deleted file mode 100644 index a312c572..00000000 --- a/docs/concepts/hooks-extension-framework.rst +++ /dev/null @@ -1,59 +0,0 @@ -Hooks Extension Framework -========================= - -Overview --------- - -Based on the `open-closed principle`_, this framework aims to extend the platform in a maintainable way without modifying its core. The main goal is to leverage the existing extension capabilities provided by the plugin architecture, allowing developers to implement new features to fit customer needs while reducing the need for core modifications and minimizing maintenance efforts. - -Hooks: Open edX Events and Filters ----------------------------------- - -Hooks are a list of places in the Open edX platform where externally defined functions can take place. These functions may alter what the user sees or experiences on the platform, while in other cases, they are purely informative. All hooks are designed to be extended through Open edX plugins and configurations. - -Hooks can be of two types: events and filters. Events are signals sent in specific places whose receivers can extend functionality, while filters are functions that can modify the application's behavior. - -To allow extension developers to use the framework's definitions in their implementations, both kinds of hooks are defined in lightweight external libraries: - -* `openedx-filters`_ -* `openedx-events`_ - -The main goal of the framework is that developers can use it to change the platform's functionality as needed and still migrate to newer Open edX releases with little to no development effort. So, the framework is designed with stability in mind, meaning it is versioned and backward compatible as much as possible. - -A longer description of the framework and its history can be found in `OEP 50`_. - -Why adopt the Hooks Extension Framework? -------------------------------------------- - -#. Stable and Maintainable Extensions - -The Hooks Extension Framework allows developers to extend the platform's functionality in a stable, maintainable, and decoupled way ensuring easier upgrades and long-term stability by removing the need to modify the core in an significant way. - -#. Contained Solution Implementation - -By avoiding core modifications, the framework promotes self-contained solutions, eliminating the need for custom code to coexist with core logic which lowers maintenance costs for extension developers. - -#. Leveraging the Open edX Plugin Extension Mechanism - -The framework allows developers to implement custom business logic and integrations directly in plugins. This keeps core modifications minimal, focusing maintenance and development efforts on plugins, where solutions can be built and maintained independently of the core platform. - -#. Standardization - -Both filters and events implementations implement an approach for adding additional features, such as communication between components or services, or backend flow control. With these standards in place, it’s easy to identify when and how to use the framework as a solution, ensuring a consistent and predictable approach to extending the platform. - -#. Reduce Fork Modifications - -The need to modify logic in forks is minimized, as most extensions can now be implementing using the framework, keeping forks closer to the core and easier to manage. - -#. Community Compatibility - -The framework allows for shorter and more agile contribution cycles. By adding standardized extension points, contributors avoid creating customer-specific logic, making development more community-friendly. - -#. Backward Compatibility - -Hooks are designed to be backward compatible, guaranteeing stability across releases and making it easier to upgrade without breaking existing functionality. - -.. _OEP 50: https://open-edx-proposals.readthedocs.io/en/latest/oep-0050-hooks-extension-framework.html -.. _openedx-filters: https://github.com/eduNEXT/openedx-filters -.. _openedx-events: https://github.com/eduNEXT/openedx-events -.. _open-closed principle: https://docs.openedx.org/projects/edx-platform/en/open-release-quince.master/concepts/extension_points.html diff --git a/docs/concepts/index.rst b/docs/concepts/index.rst index 38a13d0f..25dc09c9 100644 --- a/docs/concepts/index.rst +++ b/docs/concepts/index.rst @@ -5,6 +5,4 @@ Concepts :maxdepth: 1 :caption: Contents: - hooks-extension-framework openedx-events - events-vs-filters From baff2183a0725999d03ccb5c11b71e97c66a3793 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Mon, 4 Nov 2024 19:24:58 +0100 Subject: [PATCH 24/26] refactor: address PR reviews --- docs/concepts/openedx-events.rst | 48 +++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/docs/concepts/openedx-events.rst b/docs/concepts/openedx-events.rst index 4b0b62c1..6c2d7b8d 100644 --- a/docs/concepts/openedx-events.rst +++ b/docs/concepts/openedx-events.rst @@ -13,41 +13,57 @@ Open edX Events are signals emitted by a service (e.g., LMS, CMS, or others) wit These events are built on top of Django signals, inheriting their behavior while also incorporating metadata and actions specific to the Open edX ecosystem, making them uniquely suited for Open edX. Since they are essentially Django signals tailored to Open edX's specific needs, we can refer to `Django Signals Documentation`_ for a more detailed understanding of Open edX Events: -Django includes a “signal dispatcher” which helps decoupled applications get notified when actions occur elsewhere in the framework. In a nutshell, signals allow certain senders to notify a set of receivers that some action has taken place. They’re especially useful when many pieces of code may be interested in the same events. +Django includes a "signal dispatcher" which helps decoupled applications get notified when actions occur elsewhere in the framework. In a nutshell, signals allow certain senders to notify a set of receivers that some action has taken place. They’re especially useful when many pieces of code may be interested in the same events. -Events are primarily used as a communication method between components within the same application process or with external services using the Event Bus technology, making them the standard communication mechanism within the Open edX ecosystem. +Events are primarily used as a communication method between components within the same application process or with external services using the `Event Bus technology`_, making them the standard communication mechanism within the Open edX ecosystem. How do Open edX Events work? ---------------------------- -Open edX Events are implemented by a class called ``OpenEdxPublicSignal``, which inherits from Django’s ``Signals`` class and adds behaviors specific to the Open edX ecosystem. Thanks to this design, ``OpenEdxPublicSignal`` leverages the functionality of Django signals, allowing developers to apply their existing knowledge of the Django framework. +Open edX Events are implemented by a class called `OpenEdxPublicSignal`_, which inherits from `Django's Signals class` and adds behaviors specific to the Open edX ecosystem. Thanks to this design, ``OpenEdxPublicSignal`` leverages the functionality of Django signals, allowing developers to apply their existing knowledge of the Django framework. The event execution process follows these steps: -1. An application component emits an event by calling the ``send_event`` method implemented by ``OpenEdxPublicEvents``, which calls the Django signal ``send`` method under the hood. -2. The class generates Open edX-specific metadata for the event on the fly, like the event version or the timestamp when the event was sent. The event receivers use this metadata during their processing. -3. We call the ``send`` method from Django signals, which allows us to use the same Django signals registry for receiver management. -4. The event receivers registered by the Django signals registry mechanism for the emitted event are executed. -5. Each event receivers performs additional processing or triggers other actions based on the event data. -6. The event is considered complete once all registered signal receivers have executed. +#. An application component emits an event by calling the `send_event` method implemented by `OpenEdxPublicSignal`_. -Here is an example of an event in action: +#. The class generates Open edX-specific metadata for the event on the fly, like the event version or the timestamp when the event was sent. The event receivers use this metadata during their processing. -1. A user enrolls in a course, `triggering the COURSE_ENROLLMENT_CREATED event`_. This event includes information about the user, course, and enrollment details. -2. A `signal receiver listening`_ for the ``COURSE_ENROLLMENT_CREATED`` event is called and processes the event data. -3. The signal receiver sends a notification to the user's email confirming their enrollment in the course. -4. The event is considered complete once the signal receiver has finished processing the event. +#. The tooling uses the `send or send_robust`_ method from Django signals under the hood. The `send`` method is used for development and testing, while the `send_robust` method is used in production to ensure receivers don't raise exceptions halting the application process. + +#. Building on Django signals allows us to use the same `Django signals registry mechanism`_ for receiver management. This means that developers can register `signal receivers in their plugins`_ for Open edX Events in the same way they would for Django signals. + +#. The event is sent to all registered receivers, which are executed in the order they were registered. Each receiver processes the event data and performs the necessary actions. + +#. After all receivers for the event have been executed, the process continues with the application logic. + +Here is an example of an event that saves a user's notification preferences when they enroll in a course: + +#. A user enrolls in a course, `triggering the COURSE_ENROLLMENT_CREATED event`_. This event includes information about the user, course, and enrollment details. + +#. A signal receiver listening for the ``COURSE_ENROLLMENT_CREATED`` event is called and processes the event data. In this case, it would be the `course_enrollment_post_save receiver`_. + +#. The signal receiver creates a notification preference for the user, enabling them to receive notifications about the course. + +#. The application continues with the course enrollment process. The `Django Signals Documentation`_ provides a more detailed explanation of how Django signals work. How are Open edX Events used? ----------------------------- -Developers can create receivers for Open edX Events by implementing Django signal receivers that respond to these events emitted by the Open edX platform. These signal receivers can be registered using Django's signal mechanism, allowing them to listen for events and execute custom logic in response. +Developers can listen to Open edX Events by registering signal receivers from their Open edX Django plugins that respond to the emitted events. This is done using Django's signal mechanism, which allows developers to listen for events and execute custom logic in response. For more information on using Open edX Events, refer to the `Using Open edX Events`_ how-to guide. .. _Using Open edX Events: ../how-tos/using-events.html .. _Django Signals Documentation: https://docs.djangoproject.com/en/4.2/topics/signals/ .. _triggering the COURSE_ENROLLMENT_CREATED event: https://github.com/openedx/edx-platform/blob/master/common/djangoapps/student/models/course_enrollment.py#L777-L795 -.. _signal receiver listening: https://github.com/openedx/edx-platform/blob/master/openedx/core/djangoapps/notifications/handlers.py#L38-L53 +.. _course_enrollment_post_save receiver: https://github.com/openedx/edx-platform/blob/master/openedx/core/djangoapps/notifications/handlers.py#L38-L53 +.. _Event Bus technology: https://openedx.atlassian.net/wiki/spaces/AC/pages/3508699151/How+to+start+using+the+Event+Bus +.. _Django signals registry mechanism: https://docs.djangoproject.com/en/4.2/topics/signals/#listening-to-signals +.. _signal receivers in their plugins: https://edx.readthedocs.io/projects/edx-django-utils/en/latest/edx_django_utils.plugins.html#edx_django_utils.plugins.constants.PluginSignals +.. _Open edX Django plugins: https://edx.readthedocs.io/projects/edx-django-utils/en/latest/plugins/readme.html +.. _OpenEdxPublicSignal: https://github.com/openedx/openedx-events/blob/main/openedx_events/tooling.py#L37 +.. _Django's Signals class: https://docs.djangoproject.com/en/4.2/topics/signals/#defining-and-sending-signals +.. _send_event: https://github.com/openedx/openedx-events/blob/main/openedx_events/tooling.py#L185 +.. _send: https://docs.djangoproject.com/en/4.2/topics/signals/#sending-signals From 15c2540e590930b6c136cf23f65c94f93168da35 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Mon, 4 Nov 2024 19:29:10 +0100 Subject: [PATCH 25/26] fix: correctly reference send method from django signals --- docs/concepts/openedx-events.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/concepts/openedx-events.rst b/docs/concepts/openedx-events.rst index 6c2d7b8d..eae7cb77 100644 --- a/docs/concepts/openedx-events.rst +++ b/docs/concepts/openedx-events.rst @@ -66,4 +66,4 @@ For more information on using Open edX Events, refer to the `Using Open edX Even .. _OpenEdxPublicSignal: https://github.com/openedx/openedx-events/blob/main/openedx_events/tooling.py#L37 .. _Django's Signals class: https://docs.djangoproject.com/en/4.2/topics/signals/#defining-and-sending-signals .. _send_event: https://github.com/openedx/openedx-events/blob/main/openedx_events/tooling.py#L185 -.. _send: https://docs.djangoproject.com/en/4.2/topics/signals/#sending-signals +.. _send or send_robust: https://docs.djangoproject.com/en/4.2/topics/signals/#sending-signals From 1656d677071ae5a675abc969c4e5c7a58a8a89c2 Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Mon, 4 Nov 2024 19:42:31 +0100 Subject: [PATCH 26/26] refactor: use double backticks instead of single --- docs/concepts/openedx-events.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/concepts/openedx-events.rst b/docs/concepts/openedx-events.rst index eae7cb77..aca14dce 100644 --- a/docs/concepts/openedx-events.rst +++ b/docs/concepts/openedx-events.rst @@ -28,7 +28,7 @@ The event execution process follows these steps: #. The class generates Open edX-specific metadata for the event on the fly, like the event version or the timestamp when the event was sent. The event receivers use this metadata during their processing. -#. The tooling uses the `send or send_robust`_ method from Django signals under the hood. The `send`` method is used for development and testing, while the `send_robust` method is used in production to ensure receivers don't raise exceptions halting the application process. +#. The tooling uses the `send or send_robust`_ method from Django signals under the hood. The ``send`` method is used for development and testing, while the ``send_robust`` method is used in production to ensure receivers don't raise exceptions halting the application process. #. Building on Django signals allows us to use the same `Django signals registry mechanism`_ for receiver management. This means that developers can register `signal receivers in their plugins`_ for Open edX Events in the same way they would for Django signals.