From ce6ed7290545787a973ed74966dbf823c2dbc93c Mon Sep 17 00:00:00 2001 From: Toan Quach Date: Wed, 11 Sep 2024 10:05:38 +0700 Subject: [PATCH] added example motivation --- .../create-and-start-core-event-consumer.py | 42 ------- .../external-api-call-notifier.py | 65 ----------- .../register-specific-topic-to-notifier.py | 45 ------- .../code-example/user-changes-notifier.py | 77 ------------ .../userman/sdm/events/events-description.md | 74 ------------ docs/manuals/userman/sdm/events/examples.md | 50 -------- docs/manuals/userman/sdm/events/index.md | 57 --------- .../events/understanding-notifier-register.md | 59 ---------- .../scenario_features/events/examples.md | 110 ++++++++++++++---- 9 files changed, 86 insertions(+), 493 deletions(-) delete mode 100644 docs/manuals/userman/sdm/events/code-example/create-and-start-core-event-consumer.py delete mode 100644 docs/manuals/userman/sdm/events/code-example/external-api-call-notifier.py delete mode 100644 docs/manuals/userman/sdm/events/code-example/register-specific-topic-to-notifier.py delete mode 100644 docs/manuals/userman/sdm/events/code-example/user-changes-notifier.py delete mode 100644 docs/manuals/userman/sdm/events/events-description.md delete mode 100644 docs/manuals/userman/sdm/events/examples.md delete mode 100644 docs/manuals/userman/sdm/events/index.md delete mode 100644 docs/manuals/userman/sdm/events/understanding-notifier-register.md diff --git a/docs/manuals/userman/sdm/events/code-example/create-and-start-core-event-consumer.py b/docs/manuals/userman/sdm/events/code-example/create-and-start-core-event-consumer.py deleted file mode 100644 index fb44bab02..000000000 --- a/docs/manuals/userman/sdm/events/code-example/create-and-start-core-event-consumer.py +++ /dev/null @@ -1,42 +0,0 @@ -from time import sleep - -from taipy.core.notification import CoreEventConsumerBase, Event, Notifier - - -# Define a custom event consumer. -class MyEventConsumer(CoreEventConsumerBase): - def process_event(self, event: Event): - # Custom event processing logic here - print(f"Received a {event.entity_type} {event.operation} event at : {event.creation_date}") - - -if __name__ == "__main__": - import taipy as tp - from taipy import Config - - # Create a scenario configuration. - some_datanode_cfg = Config.configure_data_node("data", default_data="Some content.") - print_task_cfg = Config.configure_task("print", print, some_datanode_cfg) - scenario_config = Config.configure_scenario("scenario", [print_task_cfg]) - - # Run the core service. - orchestrator = tp.Orchestrator().run() - - # Register to the Notifier to retrieve a registration id and a registered queue. - registration_id, registered_queue = Notifier.register() - - # Create a consumer and start it. - consumer = MyEventConsumer(registration_id, registered_queue) - consumer.start() - - # The scenario creation and submission will trigger event emissions. - scenario = tp.create_scenario(scenario_config) - submission = tp.submit(scenario) - - # The events are processed in parallel by the consumer. - # So we need to wait for the consumer to process the events. - sleep(1) - - # Stop the consumer and unregister from the Notifier. - consumer.stop() - Notifier.unregister(registration_id) diff --git a/docs/manuals/userman/sdm/events/code-example/external-api-call-notifier.py b/docs/manuals/userman/sdm/events/code-example/external-api-call-notifier.py deleted file mode 100644 index 4273eac57..000000000 --- a/docs/manuals/userman/sdm/events/code-example/external-api-call-notifier.py +++ /dev/null @@ -1,65 +0,0 @@ -import requests - -import taipy as tp -import taipy.gui.builder as tgb -from taipy import Config, Gui, Orchestrator -from taipy.core import SubmissionStatus -from taipy.core.job.status import Status -from taipy.core.notification import CoreEventConsumerBase, EventEntityType, EventOperation, Notifier -from taipy.gui import notify - -##### Configuration and Functions ##### - - -def fail_task(name: str): - raise Exception(f"This function is trigger by {name} and is supposed to fail, and it did!") - - -name_data_node_cfg = Config.configure_data_node(id="input_name", default_data="Florian") -message_data_node_cfg = Config.configure_data_node(id="message") -build_msg_task_cfg = Config.configure_task("build_msg", fail_task, name_data_node_cfg, message_data_node_cfg) -scenario_cfg = Config.configure_scenario("scenario", task_configs=[build_msg_task_cfg]) - -value = "Default text" - - -#### Notification function to be called #### - - -def trigger_api_of_job_failure(job_id): - requests.get("http://127.0.0.1:5000/replace-this-with-your-api", params={"message": f"Job {job_id} failed."}) - - -class JobFailureCoreConsumer(CoreEventConsumerBase): - def __init__(self): - reg_id, queue = Notifier.register( - entity_type=EventEntityType.JOB, operation=EventOperation.UPDATE, attribute_name="status" - ) # Adapt the registration to the events you want to listen to - super().__init__(reg_id, queue) - - def process_event(self, event): - if event.attribute_value == Status.FAILED: - trigger_api_of_job_failure(event.entity_id) - - -#### Normal callbacks #### - - -def create_and_submit_scenario(state): - scenario = tp.create_scenario(config=scenario_cfg) - tp.submit(scenario) - - -#### Page #### - -with tgb.Page() as page: - tgb.text("{value}") - tgb.button("Create and submit a scenario!", on_action=create_and_submit_scenario) - - -if __name__ == "__main__": - orchestrator = Orchestrator() - gui = Gui(page) - orchestrator.run() - JobFailureCoreConsumer().start() - gui.run() diff --git a/docs/manuals/userman/sdm/events/code-example/register-specific-topic-to-notifier.py b/docs/manuals/userman/sdm/events/code-example/register-specific-topic-to-notifier.py deleted file mode 100644 index 48e6b879e..000000000 --- a/docs/manuals/userman/sdm/events/code-example/register-specific-topic-to-notifier.py +++ /dev/null @@ -1,45 +0,0 @@ -from time import sleep - -from taipy.core.notification import CoreEventConsumerBase, Event, EventEntityType, EventOperation, Notifier - - -def double(nb): - return nb * 2 - - -# Define a custom event consumer. -class MyEventConsumer(CoreEventConsumerBase): - def process_event(self, event: Event): - # Custom event processing logic here' - print(f"Received event of type: {event.entity_type}; and of operation: {event.operation}.") - - -if __name__ == "__main__": - import taipy as tp - from taipy import Config - - print(f"(1) Number of jobs: {len(tp.get_jobs())}.") - - # Create a scenario configuration with 2 sequential tasks. - input_data_node_cfg = Config.configure_data_node("my_input", default_data=21) - print_task_cfg = Config.configure_task("print_task", print, input_data_node_cfg) - scenario_config = Config.configure_scenario("my_scenario", [print_task_cfg]) - - # Run the core service. - tp.Orchestrator().run() - - # Register to the Notifier to retrieve events related to all scenarios' creations. - registration_id, registered_queue = Notifier.register(EventEntityType.SCENARIO, operation=EventOperation.CREATION) - - # Create a consumer and start it. - consumer = MyEventConsumer(registration_id, registered_queue) - consumer.start() - - # Create a scenario and submit it. - scenario = tp.create_scenario(scenario_config) - - sleep(1) - - # Stop the consumer and unregister from the Notifier. - consumer.stop() - Notifier.unregister(registration_id) diff --git a/docs/manuals/userman/sdm/events/code-example/user-changes-notifier.py b/docs/manuals/userman/sdm/events/code-example/user-changes-notifier.py deleted file mode 100644 index a2863f0b0..000000000 --- a/docs/manuals/userman/sdm/events/code-example/user-changes-notifier.py +++ /dev/null @@ -1,77 +0,0 @@ -import taipy as tp -import taipy.gui.builder as tgb -from taipy import Config, Gui, Orchestrator -from taipy.core import SubmissionStatus -from taipy.core.notification import CoreEventConsumerBase, EventEntityType, EventOperation, Notifier -from taipy.gui import notify - -##### Configuration and Functions ##### - - -def build_message(name: str): - return f"Hello {name}!" - - -name_data_node_cfg = Config.configure_data_node(id="input_name", default_data="Florian") -message_data_node_cfg = Config.configure_data_node(id="message") -build_msg_task_cfg = Config.configure_task("build_msg", build_message, name_data_node_cfg, message_data_node_cfg) -scenario_cfg = Config.configure_scenario("scenario", task_configs=[build_msg_task_cfg]) - -value = "Default text" - - -#### Notification function to be called #### - - -def notify_users_of_creation(state): - state.value = "Scenario created and submitted" - notify(state, "s", "Scenario Created") - - -def notify_users_of_update(state, new_value_of_dn): - print("Value of Data Node:", new_value_of_dn) - state.value = f"Data Node updated with value: {new_value_of_dn}" - notify(state, "i", "Data Node Updated") - - -class SpecificCoreConsumer(CoreEventConsumerBase): - def __init__(self, gui): - self.gui = gui - reg_id, queue = Notifier.register() # Adapt the registration to the events you want to listen to - super().__init__(reg_id, queue) - - def process_event(self, event): - if event.operation == EventOperation.CREATION: - if event.entity_type == EventEntityType.SCENARIO: - self.gui.broadcast_callback(notify_users_of_creation) - elif event.operation == EventOperation.UPDATE: - if event.entity_type == EventEntityType.SUBMISSION: - print(event) - if event.attribute_value == SubmissionStatus.COMPLETED: - scenario_id = event.metadata["origin_entity_id"] - scenario = tp.get(scenario_id) - new_value_of_dn = scenario.message.read() - self.gui.broadcast_callback(notify_users_of_update, [new_value_of_dn]) - - -#### Normal callbacks #### - - -def create_and_submit_scenario(state): - scenario = tp.create_scenario(config=scenario_cfg) - tp.submit(scenario) - - -#### Page #### - -with tgb.Page() as page: - tgb.text("{value}") - tgb.button("Create and submit a scenario!", on_action=create_and_submit_scenario) - - -if __name__ == "__main__": - orchestrator = Orchestrator() - gui = Gui(page) - orchestrator.run() - SpecificCoreConsumer(gui).start() - gui.run() diff --git a/docs/manuals/userman/sdm/events/events-description.md b/docs/manuals/userman/sdm/events/events-description.md deleted file mode 100644 index 801c515ed..000000000 --- a/docs/manuals/userman/sdm/events/events-description.md +++ /dev/null @@ -1,74 +0,0 @@ -The `Event^` object in Taipy is a notification mechanism for any changes occurring within Taipy Core, -particularly those related to the Scenario and Data Management. It is a crucial part of the system that allows -tracking and responding to changes in the state of various entities managed by Taipy, such as data nodes, jobs, -and scenarios. - -An `Event^` object is composed of several key attributes that describe what happened, the -type of operation performed, the entity concerned and its type, and other contextual -details. - -1. `entity_type` - - **Type**: `EventEntityType^` (Enum) - - **Description**: Specifies the type of entity that has undergone a change. This - attribute helps identify the nature of the object affected. The possible entity - types are: - - - `CYCLE` - - `SCENARIO` - - `SEQUENCE` - - `TASK` - - `DATA_NODE` - - `JOB` - - `SUBMISSION` - -2. `operation` - - **Type**: `EventOperation^` (Enum) - - **Description**: Indicates the type of operation performed. The `operation` attribute - is essential for understanding the nature of the change. The possible operations are: - - - `CREATION` - An entity has been created. - - `UPDATE` - An entity has been updated. - - `DELETION` - An entity has been deleted. - - `SUBMISSION` - An entity has been submitted for processing. - -3. `entity_id` - - **Type**: `str` - - **Description**: The unique identifier for the entity that has been changed. This - ID allows you to precisely identify which object in the system the event refers to. - -4. `attribute_name` - - **Type**: `str` - - **Description**: The name of the specific attribute that has been changed within - the entity. This attribute is only relevant for `UPDATE` operations, where - a specific field of an entity has been modified. - -5. `attribute_value` - - **Type**: `Any` - - **Description**: The new value of the changed attribute. Like `attribute_name`, this - only applies to `UPDATE` operations. - -6. `metadata` - - **Type**: `dict` - - **Description**: A dictionary containing additional metadata about the source of the - event. This can include context-specific information that provides more insight into - the event's origin or purpose. - -7. `creation_date` - - **Type**: `datetime` - - **Description**: The exact date and time the event was created. - -!!! example "Scenario creation event" - For example, when a scenario is created, an event is emitted with - the following attributes: - - `entity_type`: `EventEntityType.SCENARIO^` - - `operation`: `EventOperation.CREATION^` - - `entity_id`: the id of the scenario - - `creation_date`: the date and time of the event creation - -Events are particularly useful when you want to: - - Update the user interface (e.g., update a list of scenarios when a new one is created) - - Trigger an action (e.g., automatically submit a scenario when its input data is updated) - - Notify end-users (e.g., send a GUI notification to all users when a job fails) - - etc. - -For more examples, see the [examples](examples.md) page. diff --git a/docs/manuals/userman/sdm/events/examples.md b/docs/manuals/userman/sdm/events/examples.md deleted file mode 100644 index 3c80f3e81..000000000 --- a/docs/manuals/userman/sdm/events/examples.md +++ /dev/null @@ -1,50 +0,0 @@ -Examples of using Taipy event notifications to capture and consume *events*. - -# Real-Time GUI Updates with Taipy Event Consumers - -This example is provided to demonstrate the practical application of event-driven programming in -a real-world scenario. By capturing and processing events, developers can create responsive and -dynamic systems that notify users of important changes, such as the creation of new scenarios or -updates to data nodes. This approach enhances user experience by ensuring that users are always -informed of relevant updates in real-time. - -This script defines a custom event consumer class `SpecificCoreConsumer`, which listens -for all events published by Taipy Core and triggers GUI notification based on those events. -It includes determining if the event is published from a `Scenario^` entity or `DataNode^` entity -and if the action is `CREATION^` or `UPDATE^`. - -!!! example - ```python linenums="1" - {% - include-markdown "./code-example/user-changes-notifier.py" - comments=false - %} - ``` - - This snippet shows a how you can capture and process events to notify user whenever - a new scenario is created or the value of a data node is updated. - For more details, see the [registration](understanding-topics.md) page. - -# External API triggered with Taipy Event Consumers - -This example illustrates how to effectively utilize event-driven programming to monitor and -respond to changes of specific event type within Taipy Core. By defining a custom event consumer, -`JobFailureCoreConsumer`, developers can seamlessly integrate external API calls triggered -by specific job status updates. This approach ensures that critical job status changes are promptly -communicated to external systems, enhancing the robustness and responsiveness of the application. - -This script defines a custom event consumer class `JobFailureCoreConsumer`, which listens -for all events published by Taipy Core, when a `JOB^` entity's `status` attribute is `UPDATE`, -and triggers an external API call based on the `JOB^`'s `id`. - -!!! example - ```python linenums="1" - {% - include-markdown "./code-example/external-api-call-notifier.py" - comments=false - %} - ``` - - This snippet shows a how you can capture and process `JOB^` events when an `UPDATE` is made to the `status` - of the `JOB^` and request an external API. - For more details, see the [registration](understanding-topics.md) page. diff --git a/docs/manuals/userman/sdm/events/index.md b/docs/manuals/userman/sdm/events/index.md deleted file mode 100644 index 2fab0332b..000000000 --- a/docs/manuals/userman/sdm/events/index.md +++ /dev/null @@ -1,57 +0,0 @@ -In this section, we explore how to register and process *events*. - -# What is an Event - -Taipy, particularly its scenario and management capabilities, is designed to be natively -multi-user and asynchronous. This means you cannot control when an action is completed -(e.g., an end-user creating a scenario, a submission failing, a data node being edited, a job completing). -To handle these situations, Taipy emits *events* that you can consume and react to. -An *event* is a message emitted by Taipy when something occurs in the system. -It is represented by an object of class `Event^`. An *event* contains attributes necessary to identify the change. - -!!! example "Scenario creation event" - For example, when a scenario is created, an event is emitted with the following attributes: - - `entity_type`: `EventEntityType.SCENARIO^` - - `operation`: `EventOperation.CREATION^` - - `entity_id`: the identifier of the scenario - - `creation_date`: the date and time of the event creation - -Events are particularly useful for: - - Updating the user interface (e.g., refreshing a list of scenarios when a new one is created) - - Triggering actions (e.g., automatically submitting a scenario when its input data is updated) - - Notifying end-users (e.g., sending a GUI notification when a job fails) - - And more - -For more details, see the [event](events-description.md) page. - -# What is a Registration - -Taipy provides the `Notifier.register()^` method to register for events. When you register, -you specify parameters that define the events you want to receive. These parameters allow you to -filter the events you are interested in. -For more details, see the [registration](understanding-topics.md) page. - -# How to process events - -To process events, follow these steps: - -1. Create a new consumer class and extend it from `CoreEventConsumerBase^`. -2. Implement the `process_event` method to define your specific event-handling behavior. -3. Register the consumer using the `Notifier.register()^` method to obtain -a `registration_id` and a `registered_queue`. These values are used to instantiate a consumer -that can start consuming events. -4. You can stop the consumer and unregister from the `Notifier^` using the `registration_id` from earlier. - -!!! example - ```python linenums="1" - {% - include-markdown "./code-example/create-and-start-core-event-consumer.py" - comments=false - %} - ``` - - This snippet shows a generic way to process all events. However, you might want to - specify the types of events you are interested in to avoid processing all the events. - For more details, see the [registration](understanding-topics.md) page. - -For more realistic examples, see the [common use cases](examples.md) page. diff --git a/docs/manuals/userman/sdm/events/understanding-notifier-register.md b/docs/manuals/userman/sdm/events/understanding-notifier-register.md deleted file mode 100644 index 4e9d3a823..000000000 --- a/docs/manuals/userman/sdm/events/understanding-notifier-register.md +++ /dev/null @@ -1,59 +0,0 @@ -Taipy exposes the `Notifier.register()^` method to register to events. The registration -result is passed to a consumer that processes the events. When you register, -you specify parameters that define the events you want to process. These parameters and the -registration mechanism allows you to tailor your event consumer to your application's precise -needs. For example, you can register to: - - - All events emitted - - All operations related to scenarios - - All operations related to a specific data node - - All job creations - - A specific data node update - - A sequence submission - - A scenario deletion - - Job failures - -To register for event notifications, use the `Notifier.register()` method. The following -parameters define the events you want to process, like a topic of interest: - -1. `entity_type` - - **Type**: `EventEntityType^` (Enum) - - **Description**: Specifies the entity type for which you want to receive notifications. - If omitted, the consumer will be called for events across all entity types. The - possible entity types are: - - `CYCLE` - - `SCENARIO` - - `SEQUENCE` - - `TASK` - - `DATA_NODE` - - `JOB` - - `SUBMISSION` - -2. `entity_id` - - **Type**: `str` - - **Description**: Identifies the specific entity instance to register for. If omitted, - the consumer will be called of events for all entities of the specified `entity_type`. - -3. `operation` - - **Type**: `EventOperation^` (Enum) - - **Description**: Specifies the type of operation to monitor (e.g., `CREATION`, `UPDATE`, - `DELETION`, `SUBMISSION`). If omitted, the consumer will be called for all operations - performed on the specified `entity_type`. - -4. `attribute_name` - - **Type**: `str` - - **Description**: Targets a specific attribute within an entity. This is - particularly useful when you are interested in changes to a particular attribute, - such as when an attribute's value is updated. If omitted, the consumer will be called - for changes to all attributes. - -!!! example - - ```python linenums="1" - {% - include-markdown "./code-example/register-specific-topic-to-notifier.py" - comments=false - %} - ``` - -To see complete and realistic examples, see the [examples](examples.md) page. diff --git a/docs/userman/scenario_features/events/examples.md b/docs/userman/scenario_features/events/examples.md index b3e57f46d..4c4100126 100644 --- a/docs/userman/scenario_features/events/examples.md +++ b/docs/userman/scenario_features/events/examples.md @@ -1,38 +1,100 @@ -This page aims at exposing common use cases using Taipy *events*. +Examples of using Taipy event notifications to capture and consume *events*. -# Triggering user interface updates +# Real-Time GUI Updates with Taipy Event Consumers + +This example is provided to demonstrate the practical application of event-driven programming in +a real-world scenario. By capturing and processing events, developers can create responsive and +dynamic systems that notify users of important changes, such as the creation of new scenarios or +updates to data nodes. This approach enhances user experience by ensuring that users are always +informed of relevant updates in real-time. This script defines a custom event consumer class `SpecificCoreConsumer`, which listens for all events published by Taipy Core and triggers GUI notification based on those events. It includes determining if the event is published from a `Scenario^` entity or `DataNode^` entity -and if the action is `CREATION` or `UPDATE`. +and if the action is `CREATION^` or `UPDATE^`. +!!! example + ```python linenums="1" + {% + include-markdown "./code-example/user-changes-notifier.py" + comments=false + %} + ``` -```python linenums="1" -{% -include-markdown "./code-example/user-changes-notifier.py" -comments=false - %} -``` + This snippet shows a how you can capture and process events to notify user whenever + a new scenario is created or the value of a data node is updated. + For more details, see the [registration](understanding-topics.md) page. -This snippet shows a how you can capture and process events to notify user whenever -a new scenario is created or the value of a data node is updated. -For more details, see the [registration](understanding-notifier-register.md) page. +# External API triggered with Taipy Event Consumers -# Triggering External API Calls +This example illustrates how to effectively utilize event-driven programming to monitor and +respond to changes of specific event type within Taipy Core. By defining a custom event consumer, +`JobFailureCoreConsumer`, developers can seamlessly integrate external API calls triggered +by specific job status updates. This approach ensures that critical job status changes are promptly +communicated to external systems, enhancing the robustness and responsiveness of the application. This script defines a custom event consumer class `JobFailureCoreConsumer`, which listens -for all events published by Taipy Core, when a `JOB` entity's `status` attribute is `UPDATE`, -and triggers an external API call based on the `JOB`'s `id`. +for all events published by Taipy Core, when a `JOB^` entity's `status` attribute is `UPDATE`, +and triggers an external API call based on the `JOB^`'s `id`. + +!!! example + ```python linenums="1" + {% + include-markdown "./code-example/external-api-call-notifier.py" + comments=false + %} + ``` + + This snippet shows a how you can capture and process `JOB^` events when an `UPDATE` is made to the `status` + of the `JOB^` and request an external API. + For more details, see the [registration](understanding-topics.md) page. +Examples of using Taipy event notifications to capture and consume *events*. + +# Real-Time GUI Updates with Taipy Event Consumers + +This example is provided to demonstrate the practical application of event-driven programming in +a real-world scenario. By capturing and processing events, developers can create responsive and +dynamic systems that notify users of important changes, such as the creation of new scenarios or +updates to data nodes. This approach enhances user experience by ensuring that users are always +informed of relevant updates in real-time. + +This script defines a custom event consumer class `SpecificCoreConsumer`, which listens +for all events published by Taipy Core and triggers GUI notification based on those events. +It includes determining if the event is published from a `Scenario^` entity or `DataNode^` entity +and if the action is `CREATION^` or `UPDATE^`. + +!!! example + ```python linenums="1" + {% + include-markdown "./code-example/user-changes-notifier.py" + comments=false + %} + ``` + + This snippet shows a how you can capture and process events to notify user whenever + a new scenario is created or the value of a data node is updated. + For more details, see the [registration](understanding-topics.md) page. +# External API triggered with Taipy Event Consumers + +This example illustrates how to effectively utilize event-driven programming to monitor and +respond to changes of specific event type within Taipy Core. By defining a custom event consumer, +`JobFailureCoreConsumer`, developers can seamlessly integrate external API calls triggered +by specific job status updates. This approach ensures that critical job status changes are promptly +communicated to external systems, enhancing the robustness and responsiveness of the application. + +This script defines a custom event consumer class `JobFailureCoreConsumer`, which listens +for all events published by Taipy Core, when a `JOB^` entity's `status` attribute is `UPDATE`, +and triggers an external API call based on the `JOB^`'s `id`. -```python linenums="1" -{% -include-markdown "./code-example/external-api-call-notifier.py" -comments=false - %} -``` +!!! example + ```python linenums="1" + {% + include-markdown "./code-example/external-api-call-notifier.py" + comments=false + %} + ``` -This snippet shows a how you can capture and process `JOB` events when an `UPDATE` is made to the `status` -of the `JOB` and request an external API. -For more details, see the [registration](understanding-notifier-register.md) page. + This snippet shows a how you can capture and process `JOB^` events when an `UPDATE` is made to the `status` + of the `JOB^` and request an external API. + For more details, see the [registration](understanding-topics.md) page.