Tovább a tartalomhoz

Domainesemények

A domainesemények az a leválasztási mechanizmus, amely révén a funkciók közvetlen függőségek nélkül tudnak kommunikálni. Ahelyett, hogy az A funkció hívná a B funkciót, az A funkció közzétesz egy eseményt, a B funkció pedig előfizet rá.

A DomainEventBus egy folyamaton belüli, szórásos publish/subscribe busz. A közzétevők a publish(event) metódust hívják, az előfizetők pedig egy típusos on<T>() adatfolyamot fogyasztanak. Minden esemény implementálja a DomainEvent interfészt, és hordozza az occurredAt értéket.

A busz a cc_server belsejében fut. Minden közzétevő és minden élő előfizető ott él. Ezt a buszt egyetlen kliens sem látja. Amit egy kliens lát, az egy válogatott részhalmaz, amelyet a szerver notifications/* JSON-RPC wire-frame-ekként bocsát ki újra.

Események nélkül minden funkciókon átívelő reakció egy import lenne. Az értesítési útvonalnak importálnia kellene az ügynökfunkciót, a pull requestek funkcióját, a jegykezelést és a megbeszéléseket, csak hogy tudja, mikor kell toastot megjelenítenie — és ezek mindegyikének tudnia kellene azt is, hogy léteznek értesítések. A jegykezelés importálná a pipeline-okat, hogy egy befejezett jegy továbbíthasson egy futtatást. A függőségi gráf csomóvá záródik, a megosztott kernel pedig megszűnik megosztottnak lenni.

Egy esemény közzététele megtöri ezt. Az értesítési útvonal 21 eseményosztályra fizet elő, és egyetlen olyan funkciót sem importál, amely ezeket kiváltja. A pipeline-eseményindítók diszpécsere az egész buszra előfizet, és semmit sem tud a pull requestekről, a jegyekről vagy a megbeszélésekről. A megfigyelhetőség összesíti a futtatások kimeneteleit anélkül, hogy belenyúlna a diszpécserbe.

Az ár a szokásos: egy közzétevő nem tudhatja, hogy figyel-e rá valaki, és egy soha létre nem hozott figyelő csendben tétlen marad. TicketRemoteSyncHandler az állandó példa: deklarálva van, tesztek fedik, éles környezetben viszont soha nem kötődik be.

Érdemes pontosan megfogalmazni egy dolgot, amelyet a busz nem birtokol.

Az auditnapló nem az eseményfolyam vetülete. Minden módosító RPC-művelet alapértelmezés szerint auditált — a RepoOp.audited értéke alapból true, és egy művelet csak úgy lép ki ez alól, ha audited: false értéket deklarál; ez szándékos aktus, amely magán a műveleten látszik. A diszpécser közvetlenül egy sikeres hívás után fűzi be a „ki mit tett, honnan” sort. DomainEventAuditBridge nem létezik. Az ActivityLogPersister az ActivityLogged eseményekből ír activity_log sorokat; ez az RPC-audittól különálló csatorna.

Az eseménybusz az értesítések és az automatizálás szállítója. A hivatalos nyilvántartás viszont nem ő.

  • Értesítések. A szerver 21 eseményosztályt alakít notifications/* wire-frame-ekké, tartós, munkaterületenkénti hírfolyamba rögzíti őket, és kiküldi a csatlakozott munkameneteknek. Az a keret, amelynek workspace_id mezője olyan munkaterületet nevez meg, amelynek a munkamenet felhasználója nem tagja, a szerveren elvész; a kliens ezután a maradékot arra a munkaterületre szűri, amelyet éppen néz.
  • Eseményvezérelt automatizálás. A pipeline-eseményindítók előfizetnek a buszra, és maguktól elindítják a megfelelő pipeline-okat (lásd lent).
  • Életciklus-reakciók. Egy munkaterület létrehozása elveti a saját CEO-t és szakértő ügynökeit, a beépített pipelinesablonokat és a kezdő kiértékelési csomagokat. Egy befejezett ügynökfuttatás folytat egy szüneteltetett pipeline-lépést, lezár egy feladatot, táplálja a célfelügyelőt, felébreszthet egy megnevezett ellenőrzőt, és újraindíthat egy csapatvezetőt. Egy összefésült PR vagy egy törölt tér elindítja a worktree-k szemétgyűjtését.
  • Szolgáltatók közötti szinkronizálás. A helyi jegyek módosításait egy koordinátor továbbítja a beállított szolgáltatóknak, amely öt jegyeseményre figyel.

Az események a termék teljes felületét átfogják. Magas szinten:

  • Munkaterületek, ügynökök és repók — munkaterület létrehozása, futtatás befejezése, repó regisztrálása, készségfrissítések
  • Pull requestek — közzététel, állapotváltozások, összefésülések, átnézési kérések, említések, a saját PR-ek figyelése, kívülről észlelt PR-ek
  • Üzenetküldés — üzenetek, terek és a térprovisionálás előrehaladása
  • Jegyek — létrehozás, hozzárendelés, újrahozzárendelés, részletek, állapot és a három végkimenetel
  • Feladatok — sorrendbe állított életciklus-keretek egyetlen indított futtatáshoz, hogy a kliensek sorba tudják rendezni és ki tudják szűrni a duplikátumaikat
  • Pipeline-ok — csak a futtatás végállapot-eseményei (befejezve, megszakítva, sikertelen)
  • Megfigyelhetőség — tevékenységnapló-bejegyzések és költségkeret-küszöbök
  • Identitás és tagság — tag hozzáadva, eltávolítva, szerep módosítva
  • Naptár és megbeszélések — a hitelesítés lejárta, a megbeszélések kezdete és a felvételek befejeződése
  • Állomások — átvétel, begyűjtés és váratlan lezárás

A memória, az orchestráció, a tervdokumentumok, az artefaktumok, a jóváhagyások, a jegyszinkronizációs bemenet, a naptárfrissítés, a worktree-összefésülések, a felhasználók létrehozása, a meghívók és az eszközvisszavonás nem domainesemények; lásd a referenciát.

A teljes katalógust — mind az 53 konkrét eseményosztályt, azok payloadjait és a 24 előfizetőt, amelyek fogyasztják őket — a Domainesemények referenciája tartalmazza. Az a lap a leltár, ez pedig a modell.

Az élő hozzáférés-vezérlés két különböző mechanizmuson nyugszik

Szekció neve “Az élő hozzáférés-vezérlés két különböző mechanizmuson nyugszik”

A tagsági és az eszközesemények szimmetrikusnak látszanak, de nem azok, és ez számít, ha arról gondolkodik, milyen gyorsan érvényesül egy visszavonás.

Egy eszköz visszavonása valóban lezárja annak munkameneteit. A szerver figyeli a párosított eszközök tábláját, és másodperceken belül eldob minden élő munkamenetet, amelynek eszköze kikerült az aktív halmazból.

Egy tag eltávolítása nem zárja be a socketet. A WorkspaceMemberRemoved eseményt feldolgozzák: a LocalRpcServer és a RemoteRelayHost eldobja az adott felhasználó csatolt munkaterület-előfizetéseit, a RemoteEventForwarder pedig érvényteleníti a tagsági gyorsítótárát, így nem küld további kereteket arról a munkaterületről. A következő RPC-t továbbra is a szerepkapu utasítja el, amely minden híváskor újra feloldja a tagságot — így a következő kérésüket „Not a member of this workspace” üzenettel utasítja el. A hatás azonnali mindarra, amit megpróbálnak tenni; csak éppen nem a kapcsolat bontásával érhető el.

A pipeline-eseményindítók domaineseményekre fizetnek elő, és maguktól elindítják a megfelelő pipeline-okat. A PipelineTriggerDispatcher az egész buszra figyel, majd:

  1. Rövidre zár, ha az eseménytípus nem olyan, amelyet payloadra képes leképezni
  2. Kikeresi az adott eseménytípushoz illeszkedő engedélyezett eseményindítókat, az összes munkaterületen
  3. Mindegyiket a saját munkaterületére szűri, és alkalmazza a payload-egyezési szűrőjét
  4. Elindít egy futtatást minden egyes eseményindítóhoz, amely talpon marad

A fontos megkötés az 1. lépés. A busz 53 eseménytípust szállít; az eseményindító hozzáadására szolgáló választó erre a tizennégyre indít futtatást (EventPayloadMapper payload-ágak): ExternalPrDetected, PullRequestPublished, PullRequestStatusChanged, PrMerged, MessageReceived, TicketAssigned, TicketCompleted, TicketFailed, TicketCancelled, BudgetThresholdCrossed, RepoAdded, MeetingRecordingStopped, SkillUpdated és SpaceDeleted. Semmi más nem indíthat pipeline-t.

A RemoteEventForwarder az értesítési osztályba tartozó eseményeket wire-frame-ekké alakítja, és RPC-n keresztül továbbítja a csatlakozott munkameneteknek, ahol egy keretleképező alkalmazáson belüli értesítésekké alakítja őket. Egy vékony kliens így a szerver eseményfolyamának egy vetületét látja, anélkül hogy bármilyen végrehajtást birtokolna — pontosan ez a lényege a vékonykliens-szétválasztásnak.

Nem minden továbbított keret értesítés azonban. A feladat-életciklus adatfolyamát és a jegyek újrahozzárendelését élőben továbbítják a felület vezérléséhez, de nem kerülnek be az értesítési hírfolyamba, és nem jelenítenek meg toastot.