From 7d00bcbd702fd7257baedb0ead09aee54f3e6136 Mon Sep 17 00:00:00 2001 From: Toan Quach Date: Wed, 24 Jul 2024 14:17:53 +0700 Subject: [PATCH 01/11] added simple documentation for core notification --- .../create-and-start-core-event-consumer.py | 42 +++++++++++++++++++ .../register-specific-topic-to-notifier.py | 41 ++++++++++++++++++ .../userman/sdm/events/events-description.md | 23 ++++++++++ docs/manuals/userman/sdm/events/examples.md | 0 docs/manuals/userman/sdm/events/index.md | 39 +++++++++++++++++ .../sdm/events/understanding-topics.md | 0 6 files changed, 145 insertions(+) create mode 100644 docs/manuals/userman/sdm/events/code-example/create-and-start-core-event-consumer.py create mode 100644 docs/manuals/userman/sdm/events/code-example/register-specific-topic-to-notifier.py create mode 100644 docs/manuals/userman/sdm/events/events-description.md create mode 100644 docs/manuals/userman/sdm/events/examples.md create mode 100644 docs/manuals/userman/sdm/events/index.md create mode 100644 docs/manuals/userman/sdm/events/understanding-topics.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 new file mode 100644 index 000000000..892ee646b --- /dev/null +++ b/docs/manuals/userman/sdm/events/code-example/create-and-start-core-event-consumer.py @@ -0,0 +1,42 @@ +from taipy.core.notification import CoreEventConsumerBase, Event, Notifier +from time import sleep + +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 created at : {event.creation_date}") + +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="My default data in my_input datanode.") + 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.Core().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() + + # Create a scenario and submit it. + scenario = tp.create_scenario(scenario_config) + submission = tp.submit(scenario) + + 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/register-specific-topic-to-notifier.py b/docs/manuals/userman/sdm/events/code-example/register-specific-topic-to-notifier.py new file mode 100644 index 000000000..bacb08627 --- /dev/null +++ b/docs/manuals/userman/sdm/events/code-example/register-specific-topic-to-notifier.py @@ -0,0 +1,41 @@ +from taipy.core.notification import CoreEventConsumerBase, Event, Notifier, EventEntityType, EventOperation +from time import sleep + +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.Core().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/events-description.md b/docs/manuals/userman/sdm/events/events-description.md new file mode 100644 index 000000000..f52346776 --- /dev/null +++ b/docs/manuals/userman/sdm/events/events-description.md @@ -0,0 +1,23 @@ +When registering to the Notifier, you can specify which events you want to receive by providing topics. + +A topic is defined by the combination of an optional entity type, an optional +entity id, an optional operation, and an optional attribute name. The purpose is +to be as flexible as possible. For example, we can register to: + +- All actions emitted by Core +- All behaviors of scenarios +- All actions related to a certain data node +- All task creations +- A specific data node update +- A sequence submission +- A scenario deletion +- Job failures + +!!! example + + ```python linenums="1" + {% + include-markdown "./code-example/register-specific-topic-to-notifier.py" + comments=false + %} + ``` diff --git a/docs/manuals/userman/sdm/events/examples.md b/docs/manuals/userman/sdm/events/examples.md new file mode 100644 index 000000000..e69de29bb diff --git a/docs/manuals/userman/sdm/events/index.md b/docs/manuals/userman/sdm/events/index.md new file mode 100644 index 000000000..aa7460863 --- /dev/null +++ b/docs/manuals/userman/sdm/events/index.md @@ -0,0 +1,39 @@ +This page covers how you can utilize the Core event consumer feature to get notifications +about the changes to the entities in the Core service. + +Objects of class `Event^` are used to represent the changes in the Core service. +An `Event^` object holds the necessary attributes to identify the change. + +For more details and examples, see the +[event descriptions](../events-description.md) page. + +`CoreEventConsumerBase^` provides a framework for defining custom logic to consume `Event^` from +a queue in a separate thread + +# Create an event consumer + +To create an event consumer, you need to create a new consumer class +and extend it from `CoreEventConsumerBase^`. You class should implement +the `process_event` method to define their specific event handling behavior. + +Then, we register with the `Notifier^` to retrieve a `registration_id` and a `registered_queue`, +which is an event queue. These values will be used to create an object of the consumer class. + +Finally, we can begin consuming events from Core service by starting the consumer. After finishing, +we can stop the consumer and unregister from the `Notifier^` with the `registration_id` from earlier. + +!!! example + + ```python linenums="1" + {% + include-markdown "./code-example/create-and-start-core-event-consumer.py" + comments=false + %} + ``` + +This snippet provides a method to listen to all events emitting by the Core service. However, +we might want to specify the type of events we want to receive by providing topics during +the registration process. + +For more details and examples, see the +[understanding topics](../understanding-topics.md) page. diff --git a/docs/manuals/userman/sdm/events/understanding-topics.md b/docs/manuals/userman/sdm/events/understanding-topics.md new file mode 100644 index 000000000..e69de29bb From 7f5e86da9e3ac397f52d84f01e21c236de0ad58e Mon Sep 17 00:00:00 2001 From: Toan Quach Date: Wed, 24 Jul 2024 14:22:50 +0700 Subject: [PATCH 02/11] moved topic content from event to topic file --- .../sdm/events/understanding-topics.md | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/docs/manuals/userman/sdm/events/understanding-topics.md b/docs/manuals/userman/sdm/events/understanding-topics.md index e69de29bb..f52346776 100644 --- a/docs/manuals/userman/sdm/events/understanding-topics.md +++ b/docs/manuals/userman/sdm/events/understanding-topics.md @@ -0,0 +1,23 @@ +When registering to the Notifier, you can specify which events you want to receive by providing topics. + +A topic is defined by the combination of an optional entity type, an optional +entity id, an optional operation, and an optional attribute name. The purpose is +to be as flexible as possible. For example, we can register to: + +- All actions emitted by Core +- All behaviors of scenarios +- All actions related to a certain data node +- All task creations +- A specific data node update +- A sequence submission +- A scenario deletion +- Job failures + +!!! example + + ```python linenums="1" + {% + include-markdown "./code-example/register-specific-topic-to-notifier.py" + comments=false + %} + ``` From 91198bbb3a973e8c7711e1c4bee38a04c9d945a7 Mon Sep 17 00:00:00 2001 From: Toan Quach Date: Thu, 25 Jul 2024 13:42:54 +0700 Subject: [PATCH 03/11] added info about event --- .../userman/sdm/events/events-description.md | 36 +++++++++---------- .../sdm/events/understanding-topics.md | 28 +++++++++++++++ 2 files changed, 45 insertions(+), 19 deletions(-) diff --git a/docs/manuals/userman/sdm/events/events-description.md b/docs/manuals/userman/sdm/events/events-description.md index f52346776..e90cdee03 100644 --- a/docs/manuals/userman/sdm/events/events-description.md +++ b/docs/manuals/userman/sdm/events/events-description.md @@ -1,23 +1,21 @@ -When registering to the Notifier, you can specify which events you want to receive by providing topics. +Event object is used to notify any change in the Core service. -A topic is defined by the combination of an optional entity type, an optional -entity id, an optional operation, and an optional attribute name. The purpose is -to be as flexible as possible. For example, we can register to: +In an `Event^` object, `EventEntityType^` is an Enum representing the entity type. It is used as an attribute of +the `Event^` object to describe the entity that was changed. The possible operations are `CYCLE`, `SCENARIO`, +`SEQUENCE`, `TASK`, `DATA_NODE`, `JOB` or `SUBMISSION`. -- All actions emitted by Core -- All behaviors of scenarios -- All actions related to a certain data node -- All task creations -- A specific data node update -- A sequence submission -- A scenario deletion -- Job failures +There is also the `EventOperation^`, which is an Enum representing a type of operation performed on a Core entity. +It is used as an attribute of the `Event^` object to describe the operation performed on an entity. +The possible operations are `CREATION`, `UPDATE`, `DELETION`, or `SUBMISSION`. -!!! example +An event holds the following attributes to represent the change: - ```python linenums="1" - {% - include-markdown "./code-example/register-specific-topic-to-notifier.py" - comments=false - %} - ``` +- _**entity_type**_: Type of the entity that was changed (`DataNode^`, `Scenario^`, `Cycle^`, etc. ). +- _**tasks**_: A list of task configurations. +- _**entity_id**_: Unique identifier of the entity that was changed. +- _**operation**_: Enum describing the operation (among `CREATION`, `UPDATE`, `DELETION`, and `SUBMISSION`) + that was performed on the entity. +- _**attribute_name**_: Name of the entity's attribute changed. Only relevant for `UPDATE` operations +- _**attribute_value**_: Name of the entity's attribute changed. Only relevant for `UPDATE` operations. +- _**metadata**_: A dict of additional medata about the source of this event +- _**creation_date**_: Date and time of the event creation. diff --git a/docs/manuals/userman/sdm/events/understanding-topics.md b/docs/manuals/userman/sdm/events/understanding-topics.md index f52346776..ff9cea403 100644 --- a/docs/manuals/userman/sdm/events/understanding-topics.md +++ b/docs/manuals/userman/sdm/events/understanding-topics.md @@ -13,6 +13,34 @@ to be as flexible as possible. For example, we can register to: - A scenario deletion - Job failures +Topic is defined when you call `Notifier.register()^` method with the following +parameters: + +- _**entity_type**_: If provided, the listener will be notified for all events related to this entity type. + Otherwise, the listener will be notified for events related to all entity types. The possible entity type values + are defined in the `EventEntityType^` enum. The possible values are: + - CYCLE + - SCENARIO + - SEQUENCE + - TASK + - DATA_NODE + - JOB + - SUBMISSION + +- _**entity_id**_: If provided, the listener will be notified for all events related to this entity. + Otherwise, the listener will be notified for events related to all entities. + +- _**operation**_: If provided, the listener will be notified for all events related to this operation. + Otherwise, the listener will be notified for events related to all operations. The possible operation values are + defined in the `EventOperation^` enum. The possible values are: + - CREATION + - UPDATE + - DELETION + - SUBMISSION + +- _**attribute_name**_: If provided, the listener will be notified for all events related to this entity's attribute. + Otherwise, the listener will be notified for events related to all attributes. + !!! example ```python linenums="1" From 5a47604b26d85180c7dbc3ab9b20fb64a4842ec4 Mon Sep 17 00:00:00 2001 From: Toan Quach Date: Wed, 31 Jul 2024 14:21:33 +0700 Subject: [PATCH 04/11] added more info about consumer --- .../create-and-start-core-event-consumer.py | 19 +++--- docs/manuals/userman/sdm/events/index.md | 63 ++++++++++++------- 2 files changed, 50 insertions(+), 32 deletions(-) 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 index 892ee646b..61599bc8e 100644 --- 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 @@ -1,25 +1,20 @@ from taipy.core.notification import CoreEventConsumerBase, Event, Notifier from time import sleep -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 created at : {event.creation_date}") + 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 - 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="My default data in my_input datanode.") - print_task_cfg = Config.configure_task("print_task", print, input_data_node_cfg) - scenario_config = Config.configure_scenario("my_scenario", [print_task_cfg]) + # 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. tp.Core().run() @@ -31,10 +26,12 @@ def process_event(self, event: Event): consumer = MyEventConsumer(registration_id, registered_queue) consumer.start() - # Create a scenario and submit it. + # 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. diff --git a/docs/manuals/userman/sdm/events/index.md b/docs/manuals/userman/sdm/events/index.md index aa7460863..aae8ee50a 100644 --- a/docs/manuals/userman/sdm/events/index.md +++ b/docs/manuals/userman/sdm/events/index.md @@ -1,29 +1,51 @@ -This page covers how you can utilize the Core event consumer feature to get notifications -about the changes to the entities in the Core service. +In this section, we explore how to register and process *events*. -Objects of class `Event^` are used to represent the changes in the Core service. -An `Event^` object holds the necessary attributes to identify the change. +# What is an Event -For more details and examples, see the -[event descriptions](../events-description.md) page. +Taipy, particularly the scenario and management capability, is designed to be natively +multi-user and asynchronous. That means you cannot control when an action is done or completed +(an end-user created a scenario, my submission failed, a data node has been edited, a job +completed, etc.). For that purpose, Taipy emits *events* that you can consume and react to. +An *event* is a message that Taipy emits when something happens in the system. It is +represented by an object of class `Event^`. An *event* holds the necessary attributes to +identify the change. -`CoreEventConsumerBase^` provides a framework for defining custom logic to consume `Event^` from -a queue in a separate thread +!!! 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 -# Create an event consumer +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 details, see the [event](events-description.md) page. + +# What is a Registration + +Taipy exposes the `Notifier.register()^` method to register to events. When you register, +you specify parameters that define the events you want to receive. These parameters +allow you to filter the events you want to receive. +For more details, see the [registration](understanding-topics.md) page. + +# How to process events To create an event consumer, you need to create a new consumer class -and extend it from `CoreEventConsumerBase^`. You class should implement +and extend it from `CoreEventConsumerBase^`. Your class should implement the `process_event` method to define their specific event handling behavior. +Then, your need to register through the `Notifier.register()^` method to get a +`registration_id` and a `registered_queue`. These values are used to instantiate +a consumer that you can start to begin consuming events. -Then, we register with the `Notifier^` to retrieve a `registration_id` and a `registered_queue`, -which is an event queue. These values will be used to create an object of the consumer class. - -Finally, we can begin consuming events from Core service by starting the consumer. After finishing, -we can stop the consumer and unregister from the `Notifier^` with the `registration_id` from earlier. +You can also stop the consumer and unregister from the `Notifier^` with the `registration_id` +from earlier. !!! example - ```python linenums="1" {% include-markdown "./code-example/create-and-start-core-event-consumer.py" @@ -31,9 +53,8 @@ we can stop the consumer and unregister from the `Notifier^` with the `registrat %} ``` -This snippet provides a method to listen to all events emitting by the Core service. However, -we might want to specify the type of events we want to receive by providing topics during -the registration process. + This snippet provides a generic way to process all the events. However, you might want to + specify the type of events you are interested in to avoid processing all the events. + For more details, see the [registration](understanding-topics.md) page. -For more details and examples, see the -[understanding topics](../understanding-topics.md) page. +For more realistic examples, see the [common use cases](examples.md) page. \ No newline at end of file From 2ae5e9998f2b65536d6029fac3d0f7a7a0eea3db Mon Sep 17 00:00:00 2001 From: Toan Quach Date: Wed, 21 Aug 2024 14:47:40 +0700 Subject: [PATCH 05/11] change doc --- .../userman/sdm/events/events-description.md | 79 +++++++++++----- docs/manuals/userman/sdm/events/index.md | 54 ++++++----- .../sdm/events/understanding-topics.md | 89 ++++++++++--------- 3 files changed, 130 insertions(+), 92 deletions(-) diff --git a/docs/manuals/userman/sdm/events/events-description.md b/docs/manuals/userman/sdm/events/events-description.md index e90cdee03..4f5c311fb 100644 --- a/docs/manuals/userman/sdm/events/events-description.md +++ b/docs/manuals/userman/sdm/events/events-description.md @@ -1,21 +1,58 @@ -Event object is used to notify any change in the Core service. - -In an `Event^` object, `EventEntityType^` is an Enum representing the entity type. It is used as an attribute of -the `Event^` object to describe the entity that was changed. The possible operations are `CYCLE`, `SCENARIO`, -`SEQUENCE`, `TASK`, `DATA_NODE`, `JOB` or `SUBMISSION`. - -There is also the `EventOperation^`, which is an Enum representing a type of operation performed on a Core entity. -It is used as an attribute of the `Event^` object to describe the operation performed on an entity. -The possible operations are `CREATION`, `UPDATE`, `DELETION`, or `SUBMISSION`. - -An event holds the following attributes to represent the change: - -- _**entity_type**_: Type of the entity that was changed (`DataNode^`, `Scenario^`, `Cycle^`, etc. ). -- _**tasks**_: A list of task configurations. -- _**entity_id**_: Unique identifier of the entity that was changed. -- _**operation**_: Enum describing the operation (among `CREATION`, `UPDATE`, `DELETION`, and `SUBMISSION`) - that was performed on the entity. -- _**attribute_name**_: Name of the entity's attribute changed. Only relevant for `UPDATE` operations -- _**attribute_value**_: Name of the entity's attribute changed. Only relevant for `UPDATE` operations. -- _**metadata**_: A dict of additional medata about the source of this event -- _**creation_date**_: Date and time of the event creation. +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. diff --git a/docs/manuals/userman/sdm/events/index.md b/docs/manuals/userman/sdm/events/index.md index aae8ee50a..d64e56b9c 100644 --- a/docs/manuals/userman/sdm/events/index.md +++ b/docs/manuals/userman/sdm/events/index.md @@ -2,48 +2,44 @@ In this section, we explore how to register and process *events*. # What is an Event -Taipy, particularly the scenario and management capability, is designed to be natively -multi-user and asynchronous. That means you cannot control when an action is done or completed -(an end-user created a scenario, my submission failed, a data node has been edited, a job -completed, etc.). For that purpose, Taipy emits *events* that you can consume and react to. -An *event* is a message that Taipy emits when something happens in the system. It is -represented by an object of class `Event^`. An *event* holds the necessary attributes to -identify the change. +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: + 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 + - `entity_id`: the identifier 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. +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 exposes the `Notifier.register()^` method to register to events. When you register, -you specify parameters that define the events you want to receive. These parameters -allow you to filter the events you want to receive. +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 create an event consumer, you need to create a new consumer class -and extend it from `CoreEventConsumerBase^`. Your class should implement -the `process_event` method to define their specific event handling behavior. -Then, your need to register through the `Notifier.register()^` method to get a -`registration_id` and a `registered_queue`. These values are used to instantiate -a consumer that you can start to begin consuming events. - -You can also stop the consumer and unregister from the `Notifier^` with the `registration_id` -from earlier. +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" @@ -53,8 +49,8 @@ from earlier. %} ``` - This snippet provides a generic way to process all the events. However, you might want to - specify the type of events you are interested in to avoid processing all the events. + 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. \ No newline at end of file diff --git a/docs/manuals/userman/sdm/events/understanding-topics.md b/docs/manuals/userman/sdm/events/understanding-topics.md index ff9cea403..5982119b5 100644 --- a/docs/manuals/userman/sdm/events/understanding-topics.md +++ b/docs/manuals/userman/sdm/events/understanding-topics.md @@ -1,45 +1,50 @@ -When registering to the Notifier, you can specify which events you want to receive by providing topics. - -A topic is defined by the combination of an optional entity type, an optional -entity id, an optional operation, and an optional attribute name. The purpose is -to be as flexible as possible. For example, we can register to: - -- All actions emitted by Core -- All behaviors of scenarios -- All actions related to a certain data node -- All task creations -- A specific data node update -- A sequence submission -- A scenario deletion -- Job failures - -Topic is defined when you call `Notifier.register()^` method with the following -parameters: - -- _**entity_type**_: If provided, the listener will be notified for all events related to this entity type. - Otherwise, the listener will be notified for events related to all entity types. The possible entity type values - are defined in the `EventEntityType^` enum. The possible values are: - - CYCLE - - SCENARIO - - SEQUENCE - - TASK - - DATA_NODE - - JOB - - SUBMISSION - -- _**entity_id**_: If provided, the listener will be notified for all events related to this entity. - Otherwise, the listener will be notified for events related to all entities. - -- _**operation**_: If provided, the listener will be notified for all events related to this operation. - Otherwise, the listener will be notified for events related to all operations. The possible operation values are - defined in the `EventOperation^` enum. The possible values are: - - CREATION - - UPDATE - - DELETION - - SUBMISSION - -- _**attribute_name**_: If provided, the listener will be notified for all events related to this entity's attribute. - Otherwise, the listener will be notified for events related to all attributes. +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 From 2f835e72d44388afdbe2730149a19f2c679cdad5 Mon Sep 17 00:00:00 2001 From: Toan Quach Date: Wed, 21 Aug 2024 14:51:18 +0700 Subject: [PATCH 06/11] change doc --- .pre-commit-config.yaml | 5 ----- .../userman/sdm/events/events-description.md | 22 ++++++++++++++++--- docs/manuals/userman/sdm/events/index.md | 9 ++++---- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4cc0074e2..e0665ed2e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -34,8 +34,3 @@ repos: - id: black args: [--line-length=120] language_version: python3.9 -- repo: https://gitlab.com/pycqa/flake8 - rev: 3.9.2 - hooks: - - id: flake8 - additional_dependencies: [flake8-typing-imports==1.10.0] diff --git a/docs/manuals/userman/sdm/events/events-description.md b/docs/manuals/userman/sdm/events/events-description.md index 4f5c311fb..801c515ed 100644 --- a/docs/manuals/userman/sdm/events/events-description.md +++ b/docs/manuals/userman/sdm/events/events-description.md @@ -12,7 +12,7 @@ details. - **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` @@ -25,11 +25,11 @@ details. - **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. + - `SUBMISSION` - An entity has been submitted for processing. 3. `entity_id` - **Type**: `str` @@ -56,3 +56,19 @@ details. 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/index.md b/docs/manuals/userman/sdm/events/index.md index d64e56b9c..2fab0332b 100644 --- a/docs/manuals/userman/sdm/events/index.md +++ b/docs/manuals/userman/sdm/events/index.md @@ -19,7 +19,7 @@ It is represented by an object of class `Event^`. An *event* contains attributes 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) + - 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. @@ -28,12 +28,13 @@ For more details, see the [event](events-description.md) page. 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. +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 @@ -49,8 +50,8 @@ that can start consuming events. %} ``` - This snippet shows a generic way to process all events. However, you might want to + 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. \ No newline at end of file +For more realistic examples, see the [common use cases](examples.md) page. From cfb9fd872158ca12cb37eba3c02de6f05e4a9db6 Mon Sep 17 00:00:00 2001 From: Toan Quach Date: Wed, 21 Aug 2024 14:51:44 +0700 Subject: [PATCH 07/11] added flake8 --- .pre-commit-config.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e0665ed2e..4cc0074e2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -34,3 +34,8 @@ repos: - id: black args: [--line-length=120] language_version: python3.9 +- repo: https://gitlab.com/pycqa/flake8 + rev: 3.9.2 + hooks: + - id: flake8 + additional_dependencies: [flake8-typing-imports==1.10.0] From 0193d9e9f91d7c417ac5219f6a420e90b56a3c71 Mon Sep 17 00:00:00 2001 From: Toan Quach Date: Fri, 23 Aug 2024 10:45:41 +0700 Subject: [PATCH 08/11] added examples --- .../code-example/user-changes-notifier.py | 81 +++++++++++++++++++ docs/manuals/userman/sdm/events/examples.md | 13 +++ ....md => understanding-notifier-register.md} | 3 + 3 files changed, 97 insertions(+) create mode 100644 docs/manuals/userman/sdm/events/code-example/user-changes-notifier.py rename docs/manuals/userman/sdm/events/{understanding-topics.md => understanding-notifier-register.md} (96%) 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 new file mode 100644 index 000000000..5aa340cbc --- /dev/null +++ b/docs/manuals/userman/sdm/events/code-example/user-changes-notifier.py @@ -0,0 +1,81 @@ +import taipy as tp +import taipy.gui.builder as tgb + +##### Configuration and Functions ##### +from taipy import Config, Core, Gui, Scope +from taipy.core import SubmissionStatus +from taipy.core.notification import CoreEventConsumerBase, EventEntityType, EventOperation, Notifier +from taipy.gui import notify + + +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]) +#### Listen on Core Events #### + + +value = "Default text" + + +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]) + else: + pass + + +#### 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") + + +#### 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("Press me!", on_action=create_and_submit_scenario) + + +if __name__ == "__main__": + core = Core() + gui = Gui(page) + core.run() + SpecificCoreConsumer(gui).start() + gui.run() diff --git a/docs/manuals/userman/sdm/events/examples.md b/docs/manuals/userman/sdm/events/examples.md index e69de29bb..11c494798 100644 --- a/docs/manuals/userman/sdm/events/examples.md +++ b/docs/manuals/userman/sdm/events/examples.md @@ -0,0 +1,13 @@ +An example of using Taipy event notifications to capture and consume *events*. + +!!! example + ```python linenums="1" + {% + include-markdown "./code-example/create-and-start-core-event-consumer.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. diff --git a/docs/manuals/userman/sdm/events/understanding-topics.md b/docs/manuals/userman/sdm/events/understanding-notifier-register.md similarity index 96% rename from docs/manuals/userman/sdm/events/understanding-topics.md rename to docs/manuals/userman/sdm/events/understanding-notifier-register.md index 5982119b5..4e9d3a823 100644 --- a/docs/manuals/userman/sdm/events/understanding-topics.md +++ b/docs/manuals/userman/sdm/events/understanding-notifier-register.md @@ -3,6 +3,7 @@ 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 @@ -54,3 +55,5 @@ parameters define the events you want to process, like a topic of interest: comments=false %} ``` + +To see complete and realistic examples, see the [examples](examples.md) page. From ffa8d06866808bed070df91688a7c56e879afb47 Mon Sep 17 00:00:00 2001 From: Toan Quach <93168955+toan-quach@users.noreply.github.com> Date: Thu, 29 Aug 2024 08:25:13 +0700 Subject: [PATCH 09/11] Update docs/manuals/userman/sdm/events/code-example/user-changes-notifier.py Co-authored-by: Jean-Robin --- .../userman/sdm/events/code-example/user-changes-notifier.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 5aa340cbc..a486c8c8d 100644 --- a/docs/manuals/userman/sdm/events/code-example/user-changes-notifier.py +++ b/docs/manuals/userman/sdm/events/code-example/user-changes-notifier.py @@ -70,7 +70,7 @@ def create_and_submit_scenario(state): with tgb.Page() as page: tgb.text("{value}") - tgb.button("Press me!", on_action=create_and_submit_scenario) + tgb.button("Create and submit a scenario!", on_action=create_and_submit_scenario) if __name__ == "__main__": From d8f32b288c6280506b431c933127c02d89623bc9 Mon Sep 17 00:00:00 2001 From: Toan Quach <93168955+toan-quach@users.noreply.github.com> Date: Thu, 29 Aug 2024 08:25:20 +0700 Subject: [PATCH 10/11] Update docs/manuals/userman/sdm/events/code-example/user-changes-notifier.py Co-authored-by: Jean-Robin --- .../userman/sdm/events/code-example/user-changes-notifier.py | 2 -- 1 file changed, 2 deletions(-) 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 index a486c8c8d..a4db0d402 100644 --- a/docs/manuals/userman/sdm/events/code-example/user-changes-notifier.py +++ b/docs/manuals/userman/sdm/events/code-example/user-changes-notifier.py @@ -40,8 +40,6 @@ def process_event(self, event): scenario = tp.get(scenario_id) new_value_of_dn = scenario.message.read() self.gui.broadcast_callback(notify_users_of_update, [new_value_of_dn]) - else: - pass #### Notification function to be called #### From 830be2f607786f06fbe209167a2fd5fe43b19f52 Mon Sep 17 00:00:00 2001 From: Toan Quach Date: Fri, 30 Aug 2024 14:56:28 +0700 Subject: [PATCH 11/11] added examples and minor fixes --- .../create-and-start-core-event-consumer.py | 9 ++- .../external-api-call-notifier.py | 65 +++++++++++++++++++ .../register-specific-topic-to-notifier.py | 14 ++-- .../code-example/user-changes-notifier.py | 40 ++++++------ docs/manuals/userman/sdm/events/examples.md | 29 ++++++++- 5 files changed, 126 insertions(+), 31 deletions(-) create mode 100644 docs/manuals/userman/sdm/events/code-example/external-api-call-notifier.py 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 index 61599bc8e..fb44bab02 100644 --- 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 @@ -1,12 +1,15 @@ -from taipy.core.notification import CoreEventConsumerBase, Event, Notifier 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 @@ -17,8 +20,8 @@ def process_event(self, event: Event): scenario_config = Config.configure_scenario("scenario", [print_task_cfg]) # Run the core service. - tp.Core().run() - + orchestrator = tp.Orchestrator().run() + # Register to the Notifier to retrieve a registration id and a registered queue. registration_id, registered_queue = Notifier.register() 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 new file mode 100644 index 000000000..4273eac57 --- /dev/null +++ b/docs/manuals/userman/sdm/events/code-example/external-api-call-notifier.py @@ -0,0 +1,65 @@ +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 index bacb08627..48e6b879e 100644 --- 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 @@ -1,20 +1,24 @@ -from taipy.core.notification import CoreEventConsumerBase, Event, Notifier, EventEntityType, EventOperation 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())}.') + 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) @@ -22,8 +26,8 @@ def process_event(self, event: Event): scenario_config = Config.configure_scenario("my_scenario", [print_task_cfg]) # Run the core service. - tp.Core().run() - + 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) @@ -33,7 +37,7 @@ def process_event(self, event: Event): # Create a scenario and submit it. scenario = tp.create_scenario(scenario_config) - + sleep(1) # Stop the consumer and unregister from the Notifier. 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 index a4db0d402..a2863f0b0 100644 --- a/docs/manuals/userman/sdm/events/code-example/user-changes-notifier.py +++ b/docs/manuals/userman/sdm/events/code-example/user-changes-notifier.py @@ -1,12 +1,12 @@ import taipy as tp import taipy.gui.builder as tgb - -##### Configuration and Functions ##### -from taipy import Config, Core, Gui, Scope +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}!" @@ -16,12 +16,24 @@ def build_message(name: str): 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]) -#### Listen on Core Events #### - 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 @@ -42,20 +54,6 @@ def process_event(self, event): self.gui.broadcast_callback(notify_users_of_update, [new_value_of_dn]) -#### 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") - - #### Normal callbacks #### @@ -72,8 +70,8 @@ def create_and_submit_scenario(state): if __name__ == "__main__": - core = Core() + orchestrator = Orchestrator() gui = Gui(page) - core.run() + orchestrator.run() SpecificCoreConsumer(gui).start() gui.run() diff --git a/docs/manuals/userman/sdm/events/examples.md b/docs/manuals/userman/sdm/events/examples.md index 11c494798..ecfcfdcd8 100644 --- a/docs/manuals/userman/sdm/events/examples.md +++ b/docs/manuals/userman/sdm/events/examples.md @@ -1,9 +1,16 @@ -An example of using Taipy event notifications to capture and consume *events*. +Examples of using Taipy event notifications to capture and consume *events*. + +# Real-Time GUI Updates with Taipy Event Consumers + +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/create-and-start-core-event-consumer.py" + include-markdown "./code-example/user-changes-notifier.py" comments=false %} ``` @@ -11,3 +18,21 @@ An example of using Taipy event notifications to capture and consume *events*. 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 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.