Gå til innholdet

Domenehendelser

Domenehendelser er frikoblingsmekanismen som lar funksjoner kommunisere uten direkte avhengigheter. I stedet for at funksjon A kaller funksjon B, publiserer funksjon A en hendelse, og funksjon B abonnerer på den.

DomainEventBus er en prosessintern buss for kringkastet publisering og abonnement. Utgivere kaller publish(event); abonnenter konsumerer en typet on<T>()-strøm. Hver hendelse implementerer DomainEvent og bærer occurredAt.

Bussen kjører inne i cc_server. Enhver utgiver og enhver levende abonnent holder til der. Ingen klient ser denne bussen. Det en klient ser, er en kuratert delmengde som serveren sender videre som JSON-RPC-rammer av typen notifications/*.

Uten hendelser er enhver reaksjon på tvers av funksjoner en import. Varselveien ville måttet importere agentfunksjonen, pull request-funksjonen, saksfunksjonen og møtefunksjonen bare for å vite når det skal vises en toast — og hver av dem ville da måttet vite at varsler finnes. Saksfunksjonen ville importere pipelines slik at en fullført sak kunne føre en kjøring videre. Avhengighetsgrafen lukker seg til en knute, og den delte kjernen slutter å være delt.

Å publisere en hendelse bryter dette. Varselveien abonnerer på tjueen hendelsesklasser og importerer ingen av funksjonene som reiser dem. Dispatcheren for pipeline-utløsere abonnerer på hele bussen og vet ingenting om pull requests, saker eller møter. Observerbarheten aggregerer kjøringsutfall uten å strekke seg inn i utsendingen.

Kostnaden er den vanlige: en utgiver kan ikke vite om noen lytter, og en lytter som aldri blir konstruert, er taust inaktiv. TicketRemoteSyncHandler er det faste eksempelet: den er deklarert, dekket av tester og aldri koblet inn i produksjon.

Det er verdt å være presis på én ting bussen ikke eier.

Revisjonssporet er ikke en projeksjon av hendelsesstrømmen. Hver muterende RPC-operasjon revideres som standard — RepoOp.audited er true som standard, og en operasjon velger det bare bort ved å deklarere audited: false, en bevisst handling som er synlig på selve operasjonen. Dispatcheren legger til raden for «hvem gjorde hva, hvorfra» rett etter et vellykket kall. Det finnes ingen DomainEventAuditBridge. ActivityLogPersister skriver activity_log-rader fra ActivityLogged-hendelser; det er en egen strøm, atskilt fra RPC-revisjonen.

Hendelsesbussen er transporten for varsler og for automatisering. Den er ikke bokføringssystemet som er kilden til sannhet.

  • Varsler. Tjueen hendelsesklasser gjøres om til notifications/*-rammer av serveren, registreres i en varig strøm per arbeidsområde og kringkastes til tilkoblede økter. En ramme der workspace_id peker på et arbeidsområde som brukeren i økten ikke er medlem av, droppes på serveren; deretter filtrerer klienten resten ned til det arbeidsområdet den ser på.
  • Hendelsesdrevet automatisering. Pipeline-utløsere abonnerer på bussen og starter samsvarende pipelines automatisk (se nedenfor).
  • Livssyklusreaksjoner. Når et arbeidsområde opprettes, får det sin CEO, sine spesialistagenter, de innebygde pipeline-malene og startsettet med eval-suiter. En fullført agentkjøring gjenopptar et suspendert pipeline-steg, lukker en oppgave, mater målvokteren, kan vekke en navngitt kontrollør og kan utløse en teamleder på nytt. En sammenslått PR eller et slettet område utløser søppelsamling av worktreer.
  • Synkronisering på tvers av leverandører. Lokale saksendringer sendes ut til konfigurerte leverandører av en koordinator som lytter på fem sakshendelser.

Hendelsene spenner over hele produktflaten. På et overordnet nivå:

  • Arbeidsområder, agenter og repoer — oppretting av arbeidsområder, fullførte kjøringer, registrering av repoer, oppdateringer av skills
  • Pull requests — publisering, statusendringer, sammenslåinger, gjennomgangsforespørsler, omtaler, overvåking av egne PR-er, eksternt oppdagede PR-er
  • Meldinger — meldinger, områder og fremdrift for klargjøring av områder
  • Saker — oppretting, tildeling, omtildeling, detaljer, status og de tre endelige utfallene
  • Oppgaver — sekvenserte livssyklusrammer for én utsendt kjøring, slik at klienter kan ordne og avduplisere dem
  • Pipelines — bare endelige kjøringshendelser (fullført, avbrutt, mislyktes)
  • Observerbarhet — oppføringer i aktivitetsloggen og budsjettgrenser
  • Identitet og medlemskap — medlem lagt til, fjernet, rolle endret
  • Kalender og møter — utløp av autentisering, møter som starter og opptak som fullføres
  • Stasjoner — overtakelse, gjenvinning og uventet lukking

Minne, orkestrering, plandokumenter, artefakter, godkjenninger, inntak av sakssynkronisering, kalenderoppdatering, worktree-sammenslåinger, oppretting av brukere, invitasjoner og tilbakekalling av enheter er ikke domenehendelser; se referansen.

For den fullstendige katalogen — alle de 53 konkrete hendelsesklassene, nyttelastene deres og de 24 abonnentene som konsumerer dem — se referansen for domenehendelser. Den siden er fortegnelsen; denne er modellen.

Sanntids tilgangskontroll hviler på to ulike mekanismer

Seksjon med tittelen «Sanntids tilgangskontroll hviler på to ulike mekanismer»

Medlemskaps- og enhetshendelser ser symmetriske ut, men er det ikke, og det har betydning hvis du resonnerer om hvor raskt en tilbakekalling trer i kraft.

Å tilbakekalle en enhet avslutter faktisk øktene dens. Serveren overvåker tabellen over sammenkoblede enheter og dropper enhver levende økt der enheten har forlatt det aktive settet, innen sekunder.

Å fjerne et medlem lukker ikke socketen. WorkspaceMemberRemoved konsumeres: LocalRpcServer og RemoteRelayHost dropper brukerens tilknyttede arbeidsområdeabonnementer, og RemoteEventForwarder ugyldiggjør medlemskapsbufferen sin, slik at flere rammer for det arbeidsområdet ikke sendes. Det som avviser den neste RPC-en, er fortsatt rolleporten, som løser opp medlemskapet på nytt ved hvert kall — så den neste forespørselen deres avvises med «Not a member of this workspace». Virkningen er umiddelbar for alt de prøver å gjøre; den oppnås bare ikke ved å legge på røret.

Pipeline-utløsere abonnerer på domenehendelser og starter samsvarende pipelines automatisk. PipelineTriggerDispatcher lytter på hele bussen og gjør deretter følgende:

  1. Kortslutter med mindre hendelsestypen er en den vet hvordan den skal tilordne til en nyttelast
  2. Slår opp aktiverte utløsere som samsvarer med den hendelsestypen, på tvers av alle arbeidsområder
  3. Filtrerer hver av dem til sitt eget arbeidsområde og bruker nyttelastfilteret sitt
  4. Starter en kjøring for hver utløser som overlever

Den viktige begrensningen er steg 1. Bussen frakter 53 hendelsestyper; velgeren for å legge til utløsere starter en kjøring for disse fjorten (EventPayloadMapper-nyttelastgrenene): ExternalPrDetected, PullRequestPublished, PullRequestStatusChanged, PrMerged, MessageReceived, TicketAssigned, TicketCompleted, TicketFailed, TicketCancelled, BudgetThresholdCrossed, RepoAdded, MeetingRecordingStopped, SkillUpdated og SpaceDeleted. Ingenting annet kan starte en pipeline.

RemoteEventForwarder oversetter hendelsene i varselklassen til rammer og sender dem over RPC til tilkoblede økter, der en rammetilordner gjør dem om til varsler i appen. En tynnklient ser derfor en projeksjon av serverens hendelsesstrøm uten å eie noen utførelse — som er hele poenget med tynnklientdelingen.

Likevel er ikke alle rammer som sendes, et varsel. Strømmen for oppgavelivssyklus og omtildeling av saker videresendes direkte for å drive brukergrensesnittet, men de registreres ikke i varselstrømmen og viser ingen toast.