GH GambleHub

Event Surcing: base

O que é Event Surcing

O Event Surcing (ES) é uma forma de armazenar o status dos objetos de domínio, não como uma «linha atual», mas como um registro imutável de eventos que descrevem tudo o que aconteceu. O estado atual de uma unidade é um ajuntamento (replay) de seus eventos, e qualquer visão de leitura é construída como projeções acima deste registro.

Investigações-chave:
  • A história é a «fonte primária da verdade», o estado é a projeção da história.
  • Qualquer estado pode ser reproduzido novamente, verificado e explicado (auditoria).
  • Adicionar novas visualizações e analistas não requer migrações de «instantâneos» antigos - basta perder eventos.

Termos básicos

A unidade é uma unidade de domínio de coerência com invariantes nítidos (Order, Payment, UserBalance).
O evento é um fato imutável que aconteceu no passado ('payment. authorized`, `order. shipped`).
Event Store é uma revista de apend-only que garante a ordem dos eventos dentro da unidade.
A versão do aparelho é o número do último evento aplicado (para optimístico concurrency).
O Snapshot é um molde de estado periódico para acelerar o encolhimento.
Projeção (modelo read) - Uma vista materializada para leitura/pesquisa/relatório (frequentemente asincrona).

Como funciona (fluxo de comandos → eventos → projeções)

1. O cliente envia um comando ('CapturePayment', 'PlaceOrder').
2. A unidade valida os invariantes e, se estiver tudo bem, gera eventos.
3. Eventos atômicos são adicionados à Event Store com uma versão otimística.
4. Os processadores de projeção estão assinados para o fluxo de eventos e atualizam os modelos read.
5. Ao carregar o dispositivo para o seguinte comando, o estado será restaurado (se houver) → evento após o resultado.

Design de eventos

Atributos obrigatórios (núcleo)

json
{
"event_id": "uuid",
"event_type": "payment. authorized. v1",
"aggregate_type": "Payment",
"aggregate_id": "pay_123",
"aggregate_version": 5,
"occurred_at": "2025-10-31T10:42:03Z",
"payload": { "amount": 1000, "currency": "EUR", "method": "card" },
"meta": { "trace_id": "t-abc", "actor": "user_42" }
}
Recomendações:
  • Nome: 'domain. action. v{major}`.
  • Adutora: novos campos - opcionais, sem alterar o sentido dos antigos.
  • Minimalismo: apenas factos, sem duplicação de dados facilmente recuperáveis.

Contratos e esquemas

Verifique os circuitos (Avro/JSON Schema/Protobuf) e verifique a compatibilidade em CI.
As alterações «quebrantes» incluem uma nova versão maior do evento e a publicação paralela de «v1 »/« v2» durante o período de migração.

Acesso competitivo: optimística concurrency

Regra: só é possível gravar novos eventos se 'expected _ version = = current _ version'.

Pseudocode:
pseudo load: snapshot(state, version), then apply events > version new_events = aggregate. handle(command)
append_to_store(aggregate_id, expected_version=current_version, events=new_events)
//if someone has already written an event between load and append, the operation is rejected -> retray with reload

Assim garantimos a integridade dos invariantes sem transações distribuídas.

Snapshots (aceleração do comprimido)

Faça um deslize a cada N de eventos ou temporizador.
Храните `snapshot_state`, `aggregate_id`, `version`, `created_at`.
Verifique sempre e atinja os acontecimentos após o processo (não confia apenas no molde).
Retire-os de modo que possam ser reencaminhados (não guarde os campos mágicos).

Projeções e CQRS

ES é naturalmente combinado com o CQRS:
  • Modelo Write = unidades + Event Store.
  • Modelos read = projeções atualizadas por eventos (cartões Redis, OpenSearch para pesquisa, ClickHouse/OLAP para relatórios).
  • As projeções são idimpotentes: reexaminar o mesmo 'event _ id' não altera o resultado.

Evolução dos circuitos e compatibilidade

Aditivo-first: adicione os campos; não altere os tipos/semântica.
Para alterações complexas: produza novos tipos de eventos e escreva migradores de projeção.
Mantenha a gravação dupla ('v1' + 'v2') por um período de transição e retire 'v1' quando todas as projeções estiverem prontas.

Segurança, PII e «direito ao esquecimento»

O histórico muitas vezes contém dados sensíveis. Abordagens:
  • Minimize o PII em eventos (identificadores em vez de dados, peças em lados protegidos).
  • Cripto-Apagar: Criptografe os campos e destrua a chave ao pedir a remoção (o evento permanece, mas os dados não estão disponíveis).
  • Eventos de redação: 'user. piiredacted. v1 'com substituição de campos sensíveis em projeções (o histórico mantém o fato de edição).
  • Políticas de retenção: Para alguns domínios, alguns eventos podem ser arquivados no armazenamento WORM.

Desempenho e zoom

Particionamento: a ordem é importante dentro do dispositivo - particione por 'aggregate _ id'.
Início frio: snapshots + compactação periódica.
Batch-append: Agrupe os eventos com uma transação.
Backpressure e DLQ para processadores de projeção; mede a liga (tempo e número de mensagens).
Indexação Event Store: acesso rápido por '(aggregate _ tipo, agregate _ id)' e hora.

Testes

Especification tests para agregados: cenário de «comandos → eventos esperados».
Projation tests: forneça um fluxo de eventos e verifique o estado/índice materializado.
Replayability tests: Reestabeleça as projeções «do zero» no estande - verifique se o resultado é igual.
Chaos/latency: Insira atrasos e duplicações, verifique a idempotidade.

Exemplos de domínio

1) Pagamentos

Eventos: 'payment. initiated`, `payment. authorized`, `payment. captured`, `payment. refunded`.
Invariantes: Não se pode 'capture' sem 'autorized'; as quantias são irretocáveis; a moeda está inalterada.
Projeções: cartão de pagamento (KV), pesquisa de transações (OpenSearch), relatórios (OLAP).

2) Pedidos (e-commerce)

Eventos: 'order. placed`, `order. paid`, `order. packed`, `order. shipped`, `order. delivered`.
Invariantes: transições de estado no diagrama de estado; pode ser cancelado antes de 'shipped'.
Projeções: lista de pedidos do usuário, SLA-dashboards por estatais.

3) Balanços (finanças/iGaming)

Eventos: 'balance. deposited`, `balance. debited`, `balance. credited`, `balance. adjusted`.
Invariante rígido: o equilíbrio não sai <0; os comandos são idênticos por 'operation _ id'.
As operações críticas são lidas diretamente a partir da unidade (coerência rigorosa), UI a partir da projeção (eventual).

Estrutura típica da Event Store (opção de banco de dados)

events

`event_id (PK)`, `aggregate_type`, `aggregate_id`, `version`, `occurred_at`, `event_type`, `payload`, `meta`

Índice: '(aggregate _ tipo, aggregate _ id, version)'.

snapshots

`aggregate_type`, `aggregate_id`, `version`, `state`, `created_at`

Índice: '(aggregate _ tipo, aggregate _ id)'.

consumers_offsets

'consumer _ id', 'event _ id '/' posição', 'updated _ at' (para projeções e retlay).

Perguntas frequentes (FAQ)

Você precisa usar o ES em todos os lugares?
Não. ES é útil quando uma auditoria, invariantes complexos, reprodutividade e diferentes visões de dados são importantes. Para um CRUD simples é excessivo.

E os pedidos de «estado relevante»?
Leia a partir da projeção (rápido, eventual) ou - da unidade (mais caro, mas rigoroso). As operações críticas normalmente usam a segunda via.

O Kafka/strim corretor é necessário?
Event Store é a fonte da verdade; o corretor é fácil de distribuir eventos para projetores e sistemas externos.

O que fazer com o «direito ao esquecimento»?
Minimizar o PII, criptografar campos sensíveis e aplicar cripto-apagado/redação em projeções.

Como migrar os dados antigos?
Escreva um script de geração de eventos retrospectiva («re-highstori») ou comece com «estado-como-é» e publique eventos apenas para novas alterações.

Antipattern

Event Surcing «por hábito»: torna o sistema mais difícil sem benefícios de domínio.
Fat events: payload inchado com PII e duplas - freios e problemas de complacência.
Ausência de concurrency optimístico: perda de invariantes nas corridas.
Projeções impermeáveis, sem réplica/snapshot → fixação manual.
CDC crus como eventos de domínio, fuga de esquemas de BD e conectividade severa.
Misture eventos internos e de integração: Publique uma «vitrine» estabilizada.

Folha de cheque para produção

  • Unidades, invariantes e eventos definidos (nomes, versões, esquemas).
  • A Event Store fornece uma ordem dentro da unidade e da concurrency optimística.
  • O plano de reencaminhamento está incluído.
  • As projeções são idimpotentes, há DLQ e métricas de laje.
  • Os esquemas são validados em CI, a política de versões é documentada.
  • PII minimizado, campos criptografados e estratégia de «esquecimento».
  • Réplicas de projeções testadas no estande; Há um plano de recuperação de emergência.
  • Dashboards: taxa de apêndio, lâmina de projeção, erros de aplicação, proporção de retais.

Resultado

O Event Surcing faz da história do sistema um artefacto de primeira classe: nós registramos os factos, a partir deles reproduzimos o estado e construímos livremente qualquer visão. Isso permite uma auditoria, resistência a mudanças e flexibilidade dos analistas - desde que os circuitos sejam disciplinados, controlados de forma competitiva e com dados sensíveis.

Contact

Entrar em contacto

Contacte-nos para qualquer questão ou necessidade de apoio.Estamos sempre prontos para ajudar!

Iniciar integração

O Email é obrigatório. Telegram ou WhatsApp — opcionais.

O seu nome opcional
Email opcional
Assunto opcional
Mensagem opcional
Telegram opcional
@
Se indicar Telegram — responderemos também por lá.
WhatsApp opcional
Formato: +indicativo e número (ex.: +351XXXXXXXXX).

Ao clicar, concorda com o tratamento dos seus dados.