The Event Bus
Plugins communicate through a typed publish/subscribe bus. Domain events emitted by core are bridged onto the same bus automatically.
Why a bus
The bus decouples producers from consumers. A plugin emits an event (“payment captured”, “coupon redeemed”) without knowing who listens; any number of plugins subscribe without the emitter changing. Core domain events are forwarded onto the same EventBus, so plugins get one consistent stream.
Subscribing
Override register_event_handlers on your plugin class. It runs once when the plugin is enabled:
class MyPlugin(BasePlugin):
def register_event_handlers(self, bus):
bus.subscribe("payment.captured", self._on_paid)
def _on_paid(self, event):
user_id = event.data["user_id"]
# …react: grant access, send mail, credit tokens…Publishing
class MyService:
def __init__(self, bus):
self._bus = bus
def do_thing(self, user_id):
# …work…
self._bus.publish("my.thing_done",
{"user_id": user_id, "amount": 10})Subscribe-all (relays)
Infrastructure that needs every event — e.g. the outbound webhook relay — uses bus.subscribe_all(handler) and filters downstream. That is how a generic, plugin-agnostic webhook system delivers any plugin's events without importing the plugin.