Système d'Événements et Hooks XCore¶
XCore utilise une architecture pilotée par les événements (Event-Driven) pour permettre une communication découplée entre les plugins.
1. Concept de base¶
Le système repose sur deux types d'interactions majeures : - Event Bus : Diffusion asynchrone d'informations (Pub/Sub). - Hooks : Interception asynchrone permettant de modifier des données ou d'interrompre un flux.
2. Event Bus : Publication et Souscription¶
Le bus d'événements permet d'émettre des messages à travers tout le système.
S'abonner à un événement¶
Les abonnements se font généralement dans la méthode on_load.
from xcore.sdk import TrustedBase
class NotificationPlugin(TrustedBase):
async def on_load(self):
# Abonnement standard
self.ctx.events.on("user.registered", self.send_email)
# Abonnement avec wildcards
self.ctx.events.on("order.*", self.log_order_event)
async def send_email(self, event):
user_id = event.data["user_id"]
print(f"Envoi d'un email de bienvenue à {user_id}")
async def log_order_event(self, event):
print(f"Action {event.name} sur la commande {event.data['id']}")
Émettre un événement¶
class RegistrationPlugin(TrustedBase):
async def register_user(self, user_id):
# ... logique métier ...
# Émission asynchrone
await self.ctx.events.emit("user.registered", {
"user_id": user_id,
"ts": 123456789
})
3. Gestion Avancée : Priorités et Flux¶
Contrôle de l'ordre d'exécution (Priorité)¶
Vous pouvez définir une priorité (défaut: 50) pour chaque handler. Les handlers avec une priorité plus élevée (ex: 100) s'exécutent en premier.
# S'exécute AVANT les autres (priorité 100 > 50)
self.ctx.events.on("order.payment", self.check_fraud, priority=100)
# S'exécute APRÈS (priorité 10 < 50)
self.ctx.events.on("order.payment", self.send_invoice, priority=10)
Arrêt de propagation (stop)¶
Un handler peut décider d'interrompre l'exécution des handlers suivants pour un événement donné.
async def check_fraud(self, event):
if is_fraudulent(event.data):
print("ALERTE : Fraude détectée. Arrêt de la propagation.")
event.stop() # Les handlers avec une priorité < 100 ne seront PAS appelés
4. Hooks : Interception et Modification¶
Les hooks sont des événements particuliers conçus pour être interceptés afin de modifier leur contenu avant que l'action finale ne soit effectuée.
Utiliser un Hook pour modifier des données¶
class ContentPlugin(TrustedBase):
async def on_load(self):
# Hook pour modifier le texte avant sauvegarde
self.ctx.hooks.on("content.saving", self.censor_text)
async def censor_text(self, event):
text = event.data.get("text", "")
# Modification directe de l'objet 'data' de l'événement
event.data["text"] = text.replace("gros-mot", "****")
Annulation d'une action (cancel)¶
Un hook peut également être "annulé", signalant à l'émetteur que l'opération ne doit pas se poursuivre.
async def validate_order(self, event):
if event.data["total"] > 10000:
# Annule l'événement et arrête la propagation
event.cancel()
print("Commande trop élevée, annulation via Hook.")
5. Événements Système Natifs¶
XCore émet plusieurs événements natifs auxquels vos plugins peuvent réagir :
| Événement | Description |
|---|---|
xcore.boot | Le framework démarre. |
xcore.plugins.booted | Tous les plugins ont été chargés. |
plugin.<nom>.loaded | Un plugin spécifique a été chargé. |
plugin.<nom>.reloaded | Un plugin a été rechargé à chaud. |
service.<nom>.ready | Un service (DB, Cache) est prêt. |
security.violation | Une violation de sandbox a été détectée. |
6. Performances et Optimisations¶
XCore optimise le bus d'événements pour les charges de production :
- Cache de réflexion : Le type de chaque handler (
asyncousync) est mis en cache lors de l'enregistrement pour éviter d'utiliserinspectà chaque émission (gain de performance de ~30x). - Parallélisme contrôlé : Par défaut,
emitutiliseasyncio.gatherpour exécuter les handlers en parallèle, sauf si l'ordre séquentiel est requis (ex: pour respecterevent.stop()). - Isolation des exceptions : Une erreur dans un handler ne fait pas échouer l'émission globale vers les autres handlers.