Domeingebeurtenissen
Wat een domeingebeurtenis is
Sectie getiteld “Wat een domeingebeurtenis is”Domeingebeurtenissen zijn het ontkoppelingsmechanisme waarmee features met elkaar kunnen communiceren zonder directe afhankelijkheden. In plaats van dat feature A feature B aanroept, publiceert feature A een gebeurtenis en abonneert feature B zich daarop.
De DomainEventBus is een broadcast-publish/subscribe-bus die binnen één proces
draait. Uitgevers roepen publish(event) aan; abonnees consumeren een getypeerde
on<T>()-stream. Elke gebeurtenis implementeert DomainEvent en draagt
occurredAt.
De bus draait in cc_server. Elke uitgever en elke actieve abonnee leeft
daar. Geen enkele client ziet deze bus. Wat een client ziet, is een zorgvuldig
samengestelde subset die de server opnieuw uitzendt als notifications/*
JSON-RPC-frames.
Waarom überhaupt een bus
Sectie getiteld “Waarom überhaupt een bus”Zonder gebeurtenissen is elke reactie tussen features een import. Het meldingspad zou de feature voor agenten, de pull-requestfeature, ticketing en vergaderingen moeten importeren om alleen al te weten wanneer er een toast moet worden getoond — en elk van die onderdelen zou dan moeten weten dat meldingen bestaan. Ticketing zou pipelines importeren zodat een afgerond ticket een run verder kon brengen. De afhankelijkheidsgraaf raakt in de knoop en de gedeelde kernel is niet langer gedeeld.
Een gebeurtenis publiceren doorbreekt dat. Het meldingspad abonneert zich op eenentwintig gebeurtenisklassen en importeert geen van de features die ze publiceren. De pipelinetrigger-dispatcher abonneert zich op de hele bus en weet niets van pull requests, tickets of vergaderingen. Observability-aggregaten bundelen run-uitkomsten zonder in te grijpen in dispatch.
De prijs is de gebruikelijke: een uitgever kan niet zien of iemand luistert, en
een luisteraar die nooit wordt geconstrueerd is stilzwijgend inert.
TicketRemoteSyncHandler is het vaste voorbeeld: hij is gedeclareerd, gedekt
door tests en nooit in productie aangesloten.
Wat de bus niet is
Sectie getiteld “Wat de bus niet is”Het loont om precies te zijn over één ding dat de bus niet bezit.
Het auditspoor is geen projectie van de gebeurtenisstroom. Elke muterende
RPC-operatie wordt standaard geauditeerd — RepoOp.audited staat standaard op
true en een operatie kiest er alleen voor om zich af te melden door
audited: false te declareren, een bewuste daad die zichtbaar is op de operatie
zelf. De dispatcher voegt de rij met “wie deed wat, van waar” direct na een
geslaagde aanroep toe. Er is geen DomainEventAuditBridge.
ActivityLogPersister schrijft activity_log-rijen vanuit
ActivityLogged-gebeurtenissen; dat is een aparte feed naast de RPC-audit.
De gebeurtenissenbus is het transport voor meldingen en voor automatisering. Hij is niet het systeem van waarheid voor de administratie.
Wat de bus wél aanstuurt
Sectie getiteld “Wat de bus wél aanstuurt”- Meldingen. Eenentwintig gebeurtenisklassen worden door de server omgezet
in
notifications/*-wire frames, vastgelegd in een duurzame feed per werkruimte en uitgezonden naar verbonden sessies. Een frame waarvan deworkspace_ideen werkruimte noemt waarvan de sessiegebruiker geen lid is, wordt op de server weggegooid; de client filtert de rest vervolgens tot de werkruimte waarnaar hij kijkt. - Gebeurtenisgestuurde automatisering. Pipelinetriggers abonneren zich op de bus en starten automatisch passende pipelines (zie hieronder).
- Levenscyclusreacties. Bij het aanmaken van een werkruimte worden de CEO-agent en de specialistische agenten, de ingebouwde pipelinesjablonen en de initiële eval-suites geïnitialiseerd. Een afgeronde agentrun hervat een opgeschorte pipelinestap, sluit een taak, voedt de doelsupervisor, kan een genoemde controleur wekken en kan een teamleider opnieuw triggeren. Een gemergede PR of een verwijderde ruimte start garbage collection van de worktree.
- Synchronisatie tussen leveranciers. Lokale ticketwijzigingen worden naar geconfigureerde leveranciers gepusht door een coördinator die op vijf ticketgebeurtenissen luistert.
Gebeurteniscategorieën
Sectie getiteld “Gebeurteniscategorieën”Gebeurtenissen bestrijken het hele productoppervlak. Op hoofdlijnen:
- Werkruimtes, agenten en repo’s — aanmaken van werkruimtes, afronden van runs, registreren van repo’s, skillupdates
- Pull requests — publiceren, statuswijzigingen, merges, reviewverzoeken, vermeldingen, het volgen van eigen PR’s, extern gedetecteerde PR’s
- Berichten — berichten, ruimtes en de voortgang van het provisioneren van ruimtes
- Tickets — aanmaken, toewijzen, opnieuw toewijzen, details, status en de drie einduitkomsten
- Taken — opeenvolgende levenscyclusframes voor één dispatch, zodat clients ze kunnen ordenen en dedupliceren
- Pipelines — alleen eindgebeurtenissen van runs (voltooid, geannuleerd, mislukt)
- Observability — vermeldingen in het activiteitenlogboek en budgetdrempels
- Identiteit en lidmaatschap — lid toegevoegd, verwijderd, rol gewijzigd
- Agenda en vergaderingen — het verlopen van authenticatie, startende vergaderingen en afrondende opnames
- Rigs — overname, reap en onverwachte afsluiting
Geheugen, orkestratie, plandocumenten, artefacten, goedkeuringen, ticket-sync-intake, agendaverversing, worktree-merges, het aanmaken van gebruikers, uitnodigingen en het intrekken van apparaten zijn geen domeingebeurtenissen; zie de referentie.
Voor de volledige catalogus — alle 53 concrete gebeurtenisklassen, hun payloads en de 24 abonnees die ze consumeren — zie de referentie domeingebeurtenissen. Die pagina is de inventaris; deze is het model.
Live toegangscontrole verloopt via twee verschillende mechanismen
Sectie getiteld “Live toegangscontrole verloopt via twee verschillende mechanismen”Gebeurtenissen rond lidmaatschap en apparaten lijken symmetrisch en zijn dat niet, wat van belang is als je redeneert over hoe snel een intrekking ingaat.
Het intrekken van een apparaat beëindigt wél de sessies. De server houdt de tabel met gekoppelde apparaten in het oog en gooit binnen enkele seconden elke actieve sessie weg waarvan het apparaat de actieve set heeft verlaten.
Het verwijderen van een lid sluit de socket niet. WorkspaceMemberRemoved
wordt geconsumeerd: LocalRpcServer en RemoteRelayHost laten de gekoppelde
werkruimte-abonnementen van die gebruiker vallen, en RemoteEventForwarder
maakt de cache van het lidmaatschap ongeldig, zodat er geen verdere frames meer
voor die werkruimte worden gepusht. Wat de volgende RPC weigert, is nog steeds
de rolpoort, die het lidmaatschap bij elke aanroep opnieuw bepaalt — hun
volgende verzoek wordt dus geweigerd met “Not a member of this workspace”. Het
effect is onmiddellijk voor alles wat ze proberen te doen; het wordt alleen niet
bereikt door de verbinding met hen te verbreken.
Pipelinetriggers
Sectie getiteld “Pipelinetriggers”Pipelinetriggers abonneren zich op domeingebeurtenissen en starten automatisch
passende pipelines. PipelineTriggerDispatcher luistert naar de hele bus en
doet vervolgens:
- Breekt direct af tenzij het gebeurtenistype er een is dat hij naar een payload kan mappen
- Zoekt in elke werkruimte naar ingeschakelde triggers die bij dat gebeurtenistype passen
- Filtert elke trigger op zijn eigen werkruimte en past het eigen payload-filter toe
- Start een run voor elke trigger die overblijft
De belangrijkste beperking is stap 1. De bus vervoert 53 gebeurtenistypen; de
kiezer waarmee je een trigger toevoegt start alleen een run voor deze veertien
(EventPayloadMapper-payloadtakken):
ExternalPrDetected, PullRequestPublished, PullRequestStatusChanged,
PrMerged, MessageReceived, TicketAssigned,
TicketCompleted, TicketFailed, TicketCancelled,
BudgetThresholdCrossed, RepoAdded, MeetingRecordingStopped, SkillUpdated
en SpaceDeleted. Niets anders kan een pipeline starten.
Hoe een client dit allemaal ziet
Sectie getiteld “Hoe een client dit allemaal ziet”RemoteEventForwarder vertaalt de gebeurtenissen van de meldingsklasse naar
wire frames en pusht ze via RPC naar verbonden sessies, waar een frame-mapper ze
omzet in in-app meldingen. Een thin client ziet dus een projectie van de
gebeurtenisstroom van de server zonder zelf uitvoering te bezitten — precies het
punt van de
thin-client-splitsing.
Niet elk gepusht frame is echter een melding. De stroom van de taaklevenscyclus en het opnieuw toewijzen van tickets worden live doorgestuurd om de UI aan te sturen, maar ze worden niet in de meldingsfeed opgenomen en tonen geen toast.
Zie ook
Sectie getiteld “Zie ook”- Pipelines en automatisering: wat een trigger start
- Tickets en delegatie: toewijzing aan een agent vs. een team
- Architectuur: hoe gebeurtenissen bij de afhankelijkheidsregel passen
- Referentie domeingebeurtenissen: de volledige catalogus en zijn abonnees
- Pipeline-triggers instellen
- Meldingen configureren