Eventos de domínio
O que é um evento de domínio
Secção intitulada “O que é um evento de domínio”Os eventos de domínio são o mecanismo de desacoplamento que permite às funcionalidades comunicar sem dependências diretas. Em vez de a funcionalidade A chamar a funcionalidade B, a funcionalidade A publica um evento e a funcionalidade B subscreve-o.
O DomainEventBus é um barramento de publicação/subscrição com difusão e em
processo. Os publicadores chamam publish(event); os subscritores consomem um
stream tipado on<T>(). Todos os eventos implementam DomainEvent e transportam
occurredAt.
O barramento é executado dentro do cc_server. Todos os publicadores e todos
os subscritores em atividade residem aí. Nenhum cliente vê este barramento. O que
um cliente vê é um subconjunto curado que o servidor reemite como frames JSON-RPC
notifications/*.
Porquê um barramento, afinal
Secção intitulada “Porquê um barramento, afinal”Sem eventos, qualquer reação entre funcionalidades é uma importação. O percurso das notificações teria de importar a funcionalidade dos agentes, a das pull requests, a dos tickets e a das reuniões só para saber quando mostrar um aviso — e cada uma delas teria então de saber que as notificações existem. A parte dos tickets importaria os pipelines para que um ticket concluído pudesse fazer avançar uma execução. O grafo de dependências fecha-se num nó, e o kernel partilhado deixa de ser partilhado.
Publicar um evento quebra isso. O percurso das notificações subscreve vinte e uma classes de eventos e não importa nenhuma das funcionalidades que os emitem. O despachante de disparadores de pipeline subscreve o barramento inteiro e não sabe nada sobre pull requests, tickets ou reuniões. A observabilidade agrega resultados de execuções sem se intrometer no despacho.
O custo é o habitual: um publicador não consegue saber se alguém está a escutar,
e um ouvinte que nunca é construído fica silenciosamente inerte. O
TicketRemoteSyncHandler é o exemplo permanente: está declarado, tem cobertura de
testes e nunca é ligado em produção.
O que o barramento não é
Secção intitulada “O que o barramento não é”Vale a pena ser preciso quanto a uma coisa que o barramento não possui.
O registo de auditoria não é uma projeção do fluxo de eventos. Todas as
operações RPC que alteram estado são auditadas por predefinição — RepoOp.audited
tem o valor true por predefinição e uma operação só prescinde disso declarando
audited: false, um ato deliberado visível na própria operação. O despachante
acrescenta a linha «quem fez o quê, a partir de onde» imediatamente a seguir a uma
chamada bem-sucedida. Não existe nenhum DomainEventAuditBridge. O
ActivityLogPersister escreve linhas em activity_log a partir de eventos
ActivityLogged; esse é um feed separado da auditoria de RPC.
O barramento de eventos é o transporte das notificações e da automatização. Não é o sistema de registo oficial.
O que o barramento impulsiona
Secção intitulada “O que o barramento impulsiona”- Notificações. Vinte e uma classes de eventos são convertidas em frames
notifications/*pelo servidor, registadas num feed durável por espaço de trabalho e difundidas para as sessões ligadas. Um frame cujoworkspace_ididentifica um espaço de trabalho do qual o utilizador da sessão não é membro é descartado no servidor; o cliente filtra depois o resto pelo espaço de trabalho que está a ver. - Automatização orientada a eventos. Os disparadores de pipeline subscrevem o barramento e iniciam automaticamente os pipelines correspondentes (ver abaixo).
- Reações de ciclo de vida. A criação de um espaço de trabalho semeia os seus agentes CEO e especialistas, os modelos de pipeline incorporados e as suites de avaliação iniciais. Uma execução de agente concluída retoma um passo de pipeline suspenso, fecha uma tarefa, alimenta o supervisor de objetivos, pode acordar um verificador com nome e pode voltar a acionar um líder de equipa. Uma PR com merge ou um espaço eliminado desencadeia a recolha de lixo dos worktrees.
- Sincronização entre fornecedores. As alterações locais de tickets são enviadas para os fornecedores configurados por um coordenador que escuta cinco eventos de tickets.
Categorias de eventos
Secção intitulada “Categorias de eventos”Os eventos abrangem toda a superfície do produto. A um nível geral:
- Espaços de trabalho, agentes e repos — criação de espaços de trabalho, conclusão de execuções, registo de repos, atualizações de skills
- Pull requests — publicação, alterações de estado, merges, pedidos de revisão, menções, vigilância de PRs próprias, PRs detetadas externamente
- Mensagens — mensagens, espaços e progresso do aprovisionamento de espaços
- Tickets — criar, atribuir, reatribuir, detalhes, estado e os três desfechos terminais
- Tarefas — frames sequenciados do ciclo de vida de uma execução despachada, para que os clientes os possam ordenar e deduplicar
- Pipelines — apenas eventos terminais de execução (concluída, cancelada, falhada)
- Observabilidade — entradas do registo de atividade e limiares de orçamento
- Identidade e associação — membro adicionado, removido, papel alterado
- Calendário e reuniões — expiração da autenticação, início de reuniões e conclusão de gravações
- Rigs — tomada de controlo, recuperação e fecho inesperado
A memória, a orquestração, os documentos de plano, os artefactos, as aprovações, a entrada de sincronização de tickets, a atualização do calendário, os merges de worktrees, a criação de utilizadores, os convites e a revogação de dispositivos não são eventos de domínio; ver a referência.
Para o catálogo completo — as 53 classes de eventos concretas, os respetivos payloads e os 24 subscritores que as consomem — ver a referência de eventos de domínio. Essa página é o inventário; esta é o modelo.
O controlo de acesso em tempo real assenta em dois mecanismos diferentes
Secção intitulada “O controlo de acesso em tempo real assenta em dois mecanismos diferentes”Os eventos de associação e de dispositivos parecem simétricos e não o são, o que importa se estiver a raciocinar sobre a rapidez com que uma revogação produz efeito.
Revogar um dispositivo termina mesmo com as suas sessões. O servidor vigia a tabela de dispositivos emparelhados e elimina qualquer sessão ativa cujo dispositivo tenha saído do conjunto ativo, em segundos.
Remover um membro não fecha o socket. O WorkspaceMemberRemoved é
consumido: o LocalRpcServer e o RemoteRelayHost eliminam as subscrições de
espaços de trabalho associadas a esse utilizador, e o RemoteEventForwarder
invalida a sua cache de associação para que não sejam enviados mais frames desse
espaço de trabalho. O que recusa o RPC seguinte continua a ser a verificação de
papéis, que volta a resolver a associação em todas as chamadas — por isso o
pedido seguinte é recusado com «Not a member of this workspace». O efeito é
imediato para tudo o que essa pessoa tente fazer; simplesmente não é alcançado
desligando-lhes a ligação.
Disparadores de pipeline
Secção intitulada “Disparadores de pipeline”Os disparadores de pipeline subscrevem eventos de domínio e iniciam
automaticamente os pipelines correspondentes. O PipelineTriggerDispatcher
escuta o barramento inteiro e, em seguida:
- Sai imediatamente, a menos que o tipo de evento seja um dos que sabe mapear para um payload
- Procura, em todos os espaços de trabalho, os disparadores ativados que correspondem a esse tipo de evento
- Filtra cada um para o seu próprio espaço de trabalho e aplica o respetivo filtro de correspondência de payload
- Inicia uma execução por cada disparador que sobrevive
A restrição importante é o passo 1. O barramento transporta 53 tipos de eventos;
o seletor de adicionar disparador inicia uma execução para estes catorze (ramos de
payload do EventPayloadMapper):
ExternalPrDetected, PullRequestPublished, PullRequestStatusChanged,
PrMerged, MessageReceived, TicketAssigned,
TicketCompleted, TicketFailed, TicketCancelled,
BudgetThresholdCrossed, RepoAdded, MeetingRecordingStopped, SkillUpdated
e SpaceDeleted. Nada mais pode iniciar um pipeline.
Como um cliente vê tudo isto
Secção intitulada “Como um cliente vê tudo isto”O RemoteEventForwarder traduz os eventos da classe das notificações em frames e
envia-os por RPC para as sessões ligadas, onde um mapeador de frames os transforma
em notificações dentro da aplicação. Um cliente leve vê, por conseguinte, uma
projeção do fluxo de eventos do servidor sem deter qualquer execução — que é
precisamente o objetivo da
separação de cliente leve.
Nem todos os frames enviados são uma notificação, no entanto. O fluxo do ciclo de vida das tarefas e a reatribuição de tickets são reencaminhados em tempo real para alimentar a interface, mas não são registados no feed de notificações nem mostram qualquer aviso.
Ver também
Secção intitulada “Ver também”- Pipelines e automatização: o que um disparador inicia
- Tickets e delegação: atribuição a um agente vs. a uma equipa
- Arquitetura: como os eventos se enquadram na regra das dependências
- Referência de eventos de domínio: o catálogo completo e os respetivos subscritores
- Configurar disparadores de pipeline
- Configurar notificações