Événements de domaine
Ce qu’est un événement de domaine
Section intitulée « Ce qu’est un événement de domaine »Les événements de domaine sont le mécanisme de découplage qui permet aux fonctionnalités de communiquer sans dépendances directes. Au lieu que la fonctionnalité A appelle la fonctionnalité B, la fonctionnalité A publie un événement et la fonctionnalité B s’y abonne.
Le DomainEventBus est un bus de publication/abonnement en diffusion, interne au processus. Les
éditeurs appellent publish(event) ; les abonnés consomment un flux typé on<T>(). Chaque
événement implémente DomainEvent et porte un occurredAt.
Le bus s’exécute à l’intérieur de cc_server. Chaque éditeur et chaque abonné actif y résident.
Aucun client ne voit ce bus. Ce qu’un client voit, c’est un sous-ensemble sélectionné que le
serveur réémet sous forme de trames JSON-RPC notifications/*.
Pourquoi un bus, au juste
Section intitulée « Pourquoi un bus, au juste »Sans événements, chaque réaction entre fonctionnalités est un import. Le chemin des notifications devrait importer la fonctionnalité des agents, celle des demandes de tirage, la billetterie et les réunions, rien que pour savoir quand afficher une notification — et chacune de ces fonctionnalités devrait ensuite savoir que les notifications existent. La billetterie importerait les pipelines pour qu’un ticket terminé puisse faire avancer une exécution. Le graphe de dépendances se referme en un nœud, et le noyau partagé cesse d’être partagé.
Publier un événement brise cette logique. Le chemin des notifications s’abonne à vingt et une classes d’événements et n’importe aucune des fonctionnalités qui les émettent. Le répartiteur de déclencheurs de pipeline s’abonne à tout le bus et ne connaît rien des demandes de tirage, des tickets ni des réunions. L’observabilité agrège les résultats d’exécution sans aller chercher dans la répartition.
Le coût est le coût habituel : un éditeur ne peut pas savoir si quelqu’un écoute, et un écouteur
jamais construit reste silencieusement inerte. TicketRemoteSyncHandler en est l’exemple
permanent : il est déclaré, couvert par des tests, et jamais câblé en production.
Ce que le bus n’est pas
Section intitulée « Ce que le bus n’est pas »Il vaut la peine d’être précis sur une chose que le bus ne possède pas.
La piste d’audit n’est pas une projection du flux d’événements. Chaque opération RPC qui
modifie l’état est auditée par défaut — RepoOp.audited vaut true par défaut et une opération ne
s’y soustrait qu’en déclarant audited: false, un acte délibéré visible sur l’opération elle-même.
Le répartiteur ajoute la ligne « qui a fait quoi, depuis où » directement après un appel réussi. Il
n’existe pas de DomainEventAuditBridge. ActivityLogPersister écrit les lignes activity_log à
partir des événements ActivityLogged ; c’est un flux distinct de l’audit RPC.
Le bus d’événements est le transport des notifications et de l’automatisation. Il n’est pas le système d’enregistrement de référence.
Ce que le bus pilote réellement
Section intitulée « Ce que le bus pilote réellement »- Notifications. Vingt et une classes d’événements sont converties en trames
notifications/*par le serveur, consignées dans un fil durable par espace de travail et diffusées aux sessions connectées. Une trame dont leworkspace_iddésigne un espace de travail dont l’utilisateur de la session n’est pas membre est écartée sur le serveur ; le client filtre ensuite le reste sur l’espace de travail qu’il consulte. - Automatisation pilotée par événements. Les déclencheurs de pipeline s’abonnent au bus et démarrent automatiquement les pipelines correspondants (voir ci-dessous).
- Réactions au cycle de vie. La création d’un espace de travail initialise son agent CEO et ses agents spécialistes, les modèles de pipeline intégrés et les suites d’évaluation de démarrage. Une exécution d’agent terminée reprend une étape de pipeline suspendue, clôt une tâche, alimente le superviseur d’objectif, peut réveiller un vérificateur nommé et peut relancer un chef d’équipe. Une PR fusionnée ou un espace supprimé déclenche le nettoyage des arbres de travail.
- Synchronisation entre fournisseurs. Les modifications locales de tickets sont poussées vers les fournisseurs configurés par un coordinateur qui écoute cinq événements de tickets.
Catégories d’événements
Section intitulée « Catégories d’événements »Les événements couvrent toute la surface du produit. En gros :
- Espaces de travail, agents et dépôts — création d’espace de travail, fin d’exécution, enregistrement de dépôt, mises à jour de skills
- Demandes de tirage — publication, changements de statut, fusions, demandes de revue, mentions, veille des PR rédigées, PR détectées de l’extérieur
- Messagerie — messages, espaces et progression du provisionnement des espaces
- Tickets — création, assignation, réassignation, détails, statut et les trois issues terminales
- Tâches — trames de cycle de vie séquencées pour une exécution lancée, afin que les clients puissent les ordonner et les dédupliquer
- Pipelines — événements de fin d’exécution uniquement (terminée, annulée, échouée)
- Observabilité — entrées du journal d’activité et seuils budgétaires
- Identité et appartenance — membre ajouté, supprimé, rôle modifié
- Calendrier et réunions — expiration d’authentification, début de réunion et fin d’enregistrement
- Rigs — prise de contrôle, récupération et fermeture inattendue
La mémoire, l’orchestration, les documents de plan, les artefacts, les approbations, l’entrée de synchronisation des tickets, le rafraîchissement du calendrier, les fusions d’arbres de travail, la création d’utilisateurs, les invitations et la révocation d’appareils ne sont pas des événements de domaine ; voir la référence.
Pour le catalogue complet — les 53 classes d’événements concrètes, leurs charges utiles et les 24 abonnés qui les consomment — voir la référence des événements de domaine. Cette page est l’inventaire ; celle-ci est le modèle.
Le contrôle d’accès en direct repose sur deux mécanismes distincts
Section intitulée « Le contrôle d’accès en direct repose sur deux mécanismes distincts »Les événements d’appartenance et d’appareil semblent symétriques et ne le sont pas, ce qui compte si vous raisonnez sur la vitesse à laquelle une révocation prend effet.
Révoquer un appareil met bien fin à ses sessions. Le serveur surveille la table des appareils associés et coupe toute session active dont l’appareil a quitté l’ensemble actif, en quelques secondes.
Retirer un membre ne ferme pas la socket. WorkspaceMemberRemoved est consommé : LocalRpcServer
et RemoteRelayHost abandonnent les abonnements d’espace de travail rattachés à cet utilisateur, et
RemoteEventForwarder invalide son cache d’appartenance pour que les trames suivantes concernant cet
espace de travail ne soient plus poussées. Ce qui refuse l’appel RPC suivant reste la vérification de
rôle, qui résout à nouveau l’appartenance à chaque appel — leur requête suivante est donc refusée
avec « Not a member of this workspace ». L’effet est immédiat pour tout ce qu’ils tentent de faire ;
il n’est simplement pas obtenu en coupant leur connexion.
Déclencheurs de pipeline
Section intitulée « Déclencheurs de pipeline »Les déclencheurs de pipeline s’abonnent aux événements de domaine et démarrent automatiquement les
pipelines correspondants. PipelineTriggerDispatcher écoute tout le bus, puis :
- Sort immédiatement, sauf si le type d’événement est l’un de ceux qu’il sait mapper vers une charge utile
- Recherche les déclencheurs activés correspondant à ce type d’événement, dans tous les espaces de travail
- Filtre chacun sur son propre espace de travail et applique son filtre de correspondance de charge utile
- Démarre une exécution pour chaque déclencheur qui subsiste
La contrainte importante, c’est l’étape 1. Le bus transporte 53 types d’événements ; le
sélecteur « Ajouter un déclencheur » démarre une exécution pour ces quatorze (EventPayloadMapper,
branches de charge utile) :
ExternalPrDetected, PullRequestPublished, PullRequestStatusChanged,
PrMerged, MessageReceived, TicketAssigned,
TicketCompleted, TicketFailed, TicketCancelled,
BudgetThresholdCrossed, RepoAdded, MeetingRecordingStopped, SkillUpdated
et SpaceDeleted. Rien d’autre ne peut démarrer un pipeline.
Comment un client voit tout cela
Section intitulée « Comment un client voit tout cela »RemoteEventForwarder traduit les événements de la classe notification en trames et les pousse via
RPC vers les sessions connectées, où un mappeur de trames les transforme en notifications dans
l’application. Un client léger voit donc une projection du flux d’événements du serveur sans
posséder la moindre exécution — c’est tout l’intérêt de la
séparation client léger.
Cependant, toutes les trames poussées ne sont pas des notifications. Le flux du cycle de vie des tâches et la réassignation de tickets sont transmis en direct pour alimenter l’interface, mais ils ne sont pas consignés dans le fil de notifications et n’affichent aucune notification éphémère.
Voir aussi
Section intitulée « Voir aussi »- Pipelines et automatisation : ce qu’un déclencheur démarre
- Tickets et délégation : assignation à un agent ou à une équipe
- Architecture : comment les événements s’inscrivent dans la règle de dépendances
- Référence des événements de domaine : le catalogue complet et ses abonnés
- Configurer des déclencheurs de pipeline
- Configurer les notifications