Event Linkers¶
As we discussed in the previous section on Event Types, events are essential components of an event-driven architecture. However, by themselves, they are simply messages without context. So, we need a way to connect these events to the logic that determines how the system should respond. To accomplish this, Pyventus introduces the concept of the Event Linker.
In summary, the Event Linker is a base class that provides a centralized mechanism for managing the connections between events and their corresponding logic. It can be subclassed to create specific namespaces or contexts, or to modify its behavior.
Event Subscribers and Handlers¶
Before we dive deeper into the functionalities of the Event Linker, it's important to grasp the following concepts for a better understanding:
Event Handler: The Event Handler is an abstract base class that defines the workflow and essential protocols for event handling.
Event Subscriber: Represents an Event Handler that is or was subscribed to an event(s). It combines the Event Handler interface with the Subscription base class, providing a convenient way to handle events and manage the subscription lifecycle.
When performing subscriptions with the Event Linker, the returned object will always be an Event Subscriber.
Subscribing¶
The Event Linker offers different alternatives for the subscription process, allowing you to choose the approach that best aligns with your unique requirements and style. However, regardless of the method you choose, each subscription will create an independent instance of an Event Subscriber. So, for example, if you subscribe the same callback multiple times to an event, it will be invoked multiple times.
Regular Subscriptions¶
Regular subscriptions enable the event workflow to be triggered by the subscribed event(s) any number of times until they are explicitly unsubscribed.
-
You can also work with
async
functions:
-
You can also work with
async
functions:
One-time Subscriptions¶
One-time subscriptions enable the event workflow to be triggered by the subscribed event(s) only once, after which it automatically unsubscribes.
-
You can also work with
async
functions:
-
You can also work with
async
functions:
Multi-Event Subscriptions¶
The previous subscription methods also allow you to subscribe the event workflow to multiple events at once. Simply add more events after the first one, and that’s it! You can even combine different event types together.
-
You can also work with
async
functions: -
You can also work with
async
functions:
-
You can also work with
async
functions: -
You can also work with
async
functions:
One-Time Subscriptions with Multiple Events
When performing one-time subscriptions with multiple events, the first event that gets triggered will automatically unsubscribe the subscriber from all other events. As a result, regardless of how many events a one-time subscriber is listening to, it will only be triggered once.
Event Workflow Definition¶
With Pyventus, you can define the overall workflow for an event, from its initial response to its completion, whether it succeeds or encounters errors. This definition is established during the subscription process and includes three main callbacks: event_callback
, success_callback
, and failure_callback
.
-
You can also use the
once()
decorator: -
This decorator will wrap the callback that will be executed when the event occurs.
-
You can also work with
async
functions: -
This decorator will wrap the callback that will be executed when the event response is completed successfully.
-
You can also work with
async
functions: -
This decorator will wrap the callback that will be executed if the event response fails.
-
You can also work with
async
functions:
-
You can also make this a one-time subscription:
-
This callback will be executed when the event occurs.
- This callback will be executed when the event response completes successfully.
- This callback will be executed when the event response fails.
Optimizing Event Subscribers¶
By default, event subscribers in Pyventus are executed concurrently during an event emission1, running their sync
and async
callbacks as defined. However, if you have a sync
callback that involves I/O or non-CPU bound operations, you can enable the force_async
parameter to offload it to a thread pool, ensuring optimal performance and responsiveness. The offloading process is handled by the asyncio.to_thread()
function.
-
This property is also available for the
once()
decorator:
-
You can also make this a one-time subscription:
Retrieving Event Subscribers from Subscriptions¶
As we discussed earlier, each subscription generates its own instance of an Event Subscriber, and you can always access it whenever necessary.
- Setting
stateful_subctx
toTrue
will not only make the subscription context object accessible, but it will also preserve its state, allowing you to access both the subscriber and the source to which it was subscribed through theunpack()
method.
- Setting
stateful_subctx
toTrue
will cause the subscription context object to preserve its state, allowing you to access both the subscriber and the source to which it was subscribed through theunpack()
method.
Unsubscribing¶
The unsubscription process can be accomplished through various methods, each providing different levels of detail and control. It's worth noting that all of these methods will return a boolean value to indicate whether the removal was successful.
Removing Subscribers¶
- This will remove the event subscriber from both the
FirstEvent
andSecondEvent
.
- This will remove the event subscriber from both the
FirstEvent
andSecondEvent
.
Removing Linkages¶
- This will remove the
FirstEvent
from theevent_subscriber
, but it will not be fully unsubscribed since it is still subscribed to theSecondEvent
.
Removing Events¶
- This will remove the
FirstEvent
from both subscribers. However, only the first subscriber will be fully unsubscribed, as it was exclusively subscribed to theFirstEvent
. The second subscriber will continue to be subscribed to theSecondEvent
.
Removing All¶
- This will remove all events and their associated subscribers from the Event Linker registry.
Registry Accessibility¶
The Event Linker offers several methods to access the registry and retrieve necessary information from both the event and subscriber perspectives. For instance, you can obtain all subscribers for a specific event or retrieve all events associated with a particular subscriber. For more information, please refer to the API documentation for methods ranging from is_empty()
to are_linked()
.
Custom Event Linkers¶
The Event Linker class in Pyventus is built from the ground up to support both subclassing and configuration, allowing you to not only create separate linking registries or namespaces but also customize its behavior as needed.
- The
max_subscribers
property determines the maximum number of subscribers allowed for each event. By default, it is set toNone
(infinity).
Debug Mode¶
The Event Linker also offers a debug mode feature which helps you understand how event subscriptions and unsubscriptions are happening during runtime.
Global Debug Mode¶
By default, Pyventus leverages Python's global debug tracing feature to determine whether the code is running in debug mode or not. When this mode is enabled, all local debug flags are set to True
unless they are already configured. To activate global debug mode, simply run your code in a debugger like pdb.
Namespace Debug Mode¶
Alternatively, if you want to enable or disable the debug mode specifically for a certain EventLinker
namespace, you can use the debug
flag that is available in the subclass configurations. Setting the debug
flag to True
enables debug mode for that namespace, while setting it to False
disables debug mode.
-
Since each event subscriber is executed concurrently during an event emission, an active AsyncIO loop is always present within each callback. As a result, creating a new AsyncIO loop inside a callback is neither possible nor useful for performing asynchronous work. Instead, you can define the entire callback as
async
without any issues. ↩