Přeskočit na obsah

Doménové události

Co je doménová událost

Sekce “Co je doménová událost”

Doménové události jsou mechanismus, kterým spolu moduly komunikují bez přímé závislosti. Místo aby modul A volal modul B, modul A událost publikuje a modul B se na ni přihlásí.

DomainEventBus je broadcastová sběrnice publish/subscribe uvnitř procesu. Publikující volají publish(event), odběratelé konzumují typovaný proud on<T>(). Každá událost implementuje DomainEvent a nese occurredAt.

Sběrnice běží uvnitř cc_server. Každý publikující i každý živý odběratel žije tam. Žádný klient tuhle sběrnici nevidí. Klient vidí vybranou podmnožinu, kterou server znovu vysílá jako JSON-RPC rámce notifications/*.

Bez událostí je každá reakce napříč moduly import. Cesta oznámení by musela importovat modul agentů, modul pull requestů, tickety a schůzky jen proto, aby věděla, kdy zvednout toast. A každý z těch modulů by pak musel vědět, že oznámení existují. Tickety by importovaly pipeline, aby dokončený ticket posunul běh. Graf závislostí se zauzlí a sdílené jádro přestane být sdílené.

Publikování události ten uzel rozváže. Cesta oznámení se přihlásí k 21 třídám událostí a moduly, které je vyvolávají, neimportuje. Dispečer spouštěčů pipeline se přihlásí k celé sběrnici. Pull requesty, tickety ani schůzky nezná. Observabilita agreguje výsledky běhů a do odeslání nesahá.

Cena je obvyklá. Publikující nepozná, jestli někdo poslouchá, a posluchač, který se nikdy nezkonstruuje, zůstane tiše nečinný. TicketRemoteSyncHandler je stálý příklad. Je deklarovaný, pokrytý testy a v produkci nezapojený.

Jednu věc sběrnice nevlastní.

Auditní stopa není projekce proudu událostí. Každá měnící RPC operace se audituje ve výchozím stavu. RepoOp.audited má výchozí hodnotu true a operace se z auditu vyváže jedině deklarací audited: false. Je to záměrný krok, viditelný na operaci samotné. Dispečer hned po úspěšném volání připojí řádek „kdo co udělal a odkud“. DomainEventAuditBridge neexistuje. ActivityLogPersister zapisuje řádky activity_log z událostí ActivityLogged. Je to samostatný kanál, mimo RPC audit.

Sběrnice událostí je přenos pro oznámení a pro automatizaci. Závaznou evidencí systému není.

Co sběrnice skutečně řídí

Sekce “Co sběrnice skutečně řídí”
  • Oznámení. Z 21 tříd událostí server udělá rámce na drátě notifications/*, zapíše je do trvalého kanálu daného pracovního prostoru a rozešle je připojeným relacím. Rámec, jehož workspace_id míří na pracovní prostor, kde uživatel relace není členem, server zahodí. Klient pak zbytek omezí na pracovní prostor, který má otevřený.
  • Automatizace řízená událostmi. Spouštěče pipeline se přihlásí ke sběrnici a samy spustí pipeline, které sedí (viz níže).
  • Reakce životního cyklu. Vytvoření pracovního prostoru osadí jeho CEO a specializované agenty, vestavěné šablony pipeline a startovní sady evalů. Dokončený běh agenta obnoví pozastavený krok pipeline, uzavře úkol, předá podnět supervizorovi cíle, může probudit pojmenovaného kontrolora a může znovu spustit vedoucího týmu. Sloučený PR nebo smazaný prostor spustí garbage collection worktree.
  • Synchronizace mezi dodavateli. Koordinátor, který poslouchá pět událostí ticketu, odešle místní změny ticketů nakonfigurovaným dodavatelům.

Události pokrývají celý produkt. V hrubém členění:

  • Pracovní prostory, agenti a repozitáře – vytvoření pracovního prostoru, dokončení běhu, registrace repozitáře, aktualizace skillů
  • Pull requesty – publikování, změny stavu, sloučení, žádosti o revizi, zmínky, sledování vlastních PR, externě zjištěné PR
  • Zprávy – zprávy, prostory a průběh zřizování prostoru
  • Tickety – vytvoření, přiřazení, přeřazení, detaily, stav a tři konečné výsledky
  • Úkoly – seřazené rámce životního cyklu jednoho odeslaného běhu, aby je klienti uměli seřadit a zbavit duplicit
  • Pipelines – jen konečné události běhu (dokončeno, zrušeno, selhalo)
  • Observabilita – záznamy activity logu a prahy rozpočtu
  • Identita a členství – přidání člena, odebrání člena, změna role
  • Kalendář a schůzky – vypršení ověření, začínající schůzky a dokončené nahrávky
  • Stanice – převzetí, uvolnění a neočekávané zavření

Paměť, orchestrace, dokumenty plánu, artefakty, schválení, příjem synchronizace ticketů, obnovení kalendáře, sloučení worktree, vytvoření uživatele, pozvánky a odvolání zařízení nejsou doménové události. Viz referenci.

Úplný katalog (všech 53 konkrétních tříd událostí, jejich payloady a 24 odběratelů, kteří je konzumují) je v Referenci doménových událostí. Ta stránka je soupis. Tahle je model.

Řízení přístupu za běhu stojí na dvou mechanismech

Sekce “Řízení přístupu za běhu stojí na dvou mechanismech”

Události členství a události zařízení vypadají symetricky. Mechanismus je pokaždé jiný, a právě na tom záleží, když odhaduješ, jak rychle se odebrání přístupu projeví.

Odvolání zařízení jeho relace ukončí. Server sleduje tabulku spárovaných zařízení a do několika sekund zahodí každou živou relaci, jejíž zařízení opustilo aktivní sadu.

Odebrání člena soket nezavírá. WorkspaceMemberRemoved se konzumuje. LocalRpcServer a RemoteRelayHost zahodí připojené odběry pracovního prostoru toho uživatele a RemoteEventForwarder zneplatní svou cache členství, takže další rámce pro ten pracovní prostor se neposílají. Další RPC pořád odmítá brána rolí, která členství znovu vyhodnotí při každém volání, takže další požadavek dostane “Not a member of this workspace”. Na cokoli, co zkusí udělat, to platí hned. Spojení se jim kvůli tomu nezavěšuje.

Spouštěče pipeline se přihlásí k doménovým událostem a samy spustí pipeline, které sedí. PipelineTriggerDispatcher poslouchá celou sběrnici a pak:

  1. Hned skončí, pokud typ události neumí namapovat na payload
  2. Vyhledá zapnuté spouštěče pro ten typ události, ve všech pracovních prostorech
  3. Omezí každý na jeho vlastní pracovní prostor a použije jeho filtr shody payloadu
  4. Spustí běh pro každý spouštěč, který projde

Podstatné omezení je krok 1. Sběrnice nese 53 typů událostí. Výběr při přidání spouštěče spustí běh pro těchto čtrnáct (větve payloadu EventPayloadMapper): ExternalPrDetected, PullRequestPublished, PullRequestStatusChanged, PrMerged, MessageReceived, TicketAssigned, TicketCompleted, TicketFailed, TicketCancelled, BudgetThresholdCrossed, RepoAdded, MeetingRecordingStopped, SkillUpdated a SpaceDeleted. Nic jiného pipeline nespustí.

Jak z toho klient cokoli vidí

Sekce “Jak z toho klient cokoli vidí”

RemoteEventForwarder překládá události třídy oznámení na rámce na drátě a posílá je přes RPC připojeným relacím. Mapovač rámců z nich udělá oznámení v aplikaci. Tenký klient tak vidí projekci proudu událostí serveru a žádné provádění nevlastní. O to v oddělení tenkého klienta jde.

Ne každý poslaný rámec je oznámení. Proud životního cyklu úkolu a přeřazení ticketu se předávají živě, aby poháněly rozhraní. Do kanálu oznámení se nezapisují a toast nezvednou.