Header Ads

Como o Event Sourcing ajuda você a rastrear o estado do seu aplicativo

Shutterstock / whiteMocca

A fonte de eventos é uma arquitetura de software em que as alterações no estado do aplicativo são capturadas como uma série de eventos “ armazenados perpetuamente. ” Considerando que a maioria dos sistemas apenas expõe seu estado atual, a fonte de eventos cria um registro completo de todos os estados anteriores.

Os fundamentos

A fonte de eventos é mais frequentemente usada com sistemas baseados em tempo ou processos lineares. Um aplicativo de pedido de loja pode fazer a transição de transações entre “ pendentes ”, “ aprovadas ” e “ enviado ” estados. A transição entre cada estado é um “ evento ” distinto; no ciclo de vida desse pedido.

Este sistema pode ser modelado usando um banco de dados relacional tradicional:

 order_id | order_status --------- | ------------- 1000 | APROVADO 

Na maioria dos sistemas, saber o status atual não é suficiente. Você também deseja ver quando o pedido foi aprovado. Poderíamos fazer isso adicionando campos extras:

 id_de_pedida | order_created_time | order_approved_time | order_shipping_time --------- | -------------------- | ------------------ --- | --------------------- 1000 | 2021-04-30 | 2021-05-01 | NULL 

Agora está claro que o pedido foi criado em 30 de abril e aprovado em 1º de maio; seu envio ainda está pendente. Para muitas aplicações, essa estrutura funciona bem. Pode se tornar restritivo à medida que mais estados são adicionados.

Vejamos agora este exemplo reestruturado para usar fonte de eventos:

 id_evento | event_order_id | event_type | event_timestamp --------- | --------------------- | ---------------- | ---------------- 2 | 1000 order. approved | 2021-05-01 1 | 1000 order. created | 2021-04-30 

As transições de estado do pedido foram separadas em um registro de eventos dedicado. Com este modelo, é trivial adicionar um novo tipo de evento no futuro. Se um cliente precisar cancelar um pedido, podemos escrever um evento order. cancelled no log.

O fornecimento de eventos também pode ser usado para rastrear dados sobre o próprio pedido. Você pode adicionar tipos de eventos para order. apply_discount ou order. process_refund. Você pode registrar um evento a qualquer momento, criando um novo estado para o pedido enquanto mantém seus estados anteriores acessíveis.

Reconstruindo o estado de um objeto

Você pode determinar o estado atual de um objeto obtendo todos os eventos relacionados a ele. Se você deseja saber se um pedido foi aprovado, verifique se sua coleção de eventos contém um evento order. approved.

Você pode reconstruir estados históricos exatamente da mesma maneira. Se você precisa saber o estado do pedido em uma data específica, busque todos os eventos registrados antes ou naquele dia.

A fonte de eventos é um modelo incremental que rastreia a cronologia de um objeto automaticamente. Cada alteração no estado do objeto deve ser capturada como um evento com carimbo de data / hora. Ao usar o sourcing de eventos, você tem controle de versão automático e um registro de auditoria completo das transições de estado.

Se alguma vez precisar reconstruir o histórico de um objeto, você pode descartar todos os eventos criados após uma determinada data. Imagine que a conta de um usuário foi comprometida por um agente malicioso que realizou várias ações em seu nome. Em um sistema totalmente baseado em eventos, você pode excluir quaisquer eventos vinculados a esse usuário em um período de tempo questionável. Isso recuperaria a conta para um bom estado.

Para preservar essa capacidade, você deve garantir que os eventos sejam imutáveis. Depois que um evento for registrado, você nunca deve alterar suas propriedades. Se um evento precisar de ajuste, você &’ registraria outro evento para efetuar a mudança.

A imutabilidade do sistema significa que você pode usá-lo com segurança para viajar no tempo e reconstruir estados históricos. Se você quiser reproduzir seu banco de dados como era há dois anos, pode descartar todos os eventos registrados nesse período.

Outro benefício da fonte de eventos é o aumento da visibilidade do estado do sistema. Se um usuário relatar um bug, você pode clonar o banco de dados, descartar novos eventos e repetir suas etapas a partir de um ponto bom conhecido. Analisar eventos registrados pode ajudá-lo a identificar bugs em sua base de código.

Sourcing de eventos no mundo real

O sourcing de eventos tem a reputação de ser complexo, pesado e muito complicado. Historicamente, o fornecimento de eventos tem sido vinculado a aplicativos com requisitos de auditoria rigorosos e uma necessidade comprovada de reproduzir eventos.

Este não tem que ser o caso. Se você for um desenvolvedor experiente, provavelmente já implementou algo próximo ao fornecimento de eventos no passado. Qualquer sistema que mantenha um registro de “ eventos ” – como tentativas de login do usuário, acessos à página do site ou estágios de processamento de pedidos – naturalmente gravita em direção a uma abordagem originada de evento, mesmo se você não estiver implementando uma intencionalmente.

Uma implementação deliberada de fonte de eventos no código pode ser complicada. Os desenvolvedores geralmente presumem que os dados obtidos de bancos de dados são uma representação precisa do estado atual de um objeto. Com a fonte de eventos, os dados que você busca têm pouco valor por si só. Você precisa “ repetir ” eventos em sua base de código para criar uma representação do estado.

O fornecimento de eventos pode gerar sobrecargas de desempenho. No exemplo acima, a criação de uma representação completa do objeto de pedido agora requer muito mais dados a serem buscados. No modelo tradicional, uma única seleção fornece todos os dados associados ao pedido.

Existem outras desvantagens também. No caso de algo dar errado, a origem do evento pode ser mais difícil de corrigir. Você não pode escrever um patch rápido ou corrigir manualmente o banco de dados. Você precisará fazer a transição de seus esquemas de evento sem problemas, ao mesmo tempo que garante que a cronologia histórica permaneça intacta.

Combinando Event Sourcing e CQRS

A fonte de eventos é comumente combinada com CQRS (Command Query Responsibility Segregation). Este padrão defende a separação de comandos (que gravam dados) de consultas (que leem dados).

O uso de fonte de eventos requer um certo grau de CQRS. Os dados são gravados em seu banco de dados por meio de eventos. O modelo de gravação é, portanto, extremamente simples: é um log de acréscimo unilateral dos eventos que ocorrem. Os eventos são uma manifestação dos “ comandos ” descrito por CQRS.

O modelo de recuperação de dados é totalmente independente. Você pode usar o sistema de consulta mais apropriado para buscar eventos e colocá-los no estado atual do aplicativo. Os comandos (eventos) fazem a transição do sistema para um novo estado; as consultas expõem os aspectos de estado que seu aplicativo solicita.

Colocado de outra forma, os modelos de leitura e gravação não têm consciência de como as outras funções. As entidades em sua base de código (como um pedido) são armazenadas como uma sequência de eventos cronológicos. Os eventos armazenados não podem ser reidratados na entidade a que pertencem sem o conhecimento de como o estado dessa entidade é derivado. Esse conhecimento é implementado no modelo de leitura (consulta), que traz os dados de volta ao seu aplicativo.

Esta característica permite que a camada de persistência seja simplificada para uma única inserção de registro para cada operação. Os dados armazenados não precisam representar com precisão nenhuma entidade específica, pois o modelo de consulta irá manipulá-los posteriormente. Isso contrasta com um “ tradicional ” banco de dados relacional em que os campos da tabela geralmente se alinham com as propriedades dos objetos em sua base de código.

A saída do modelo de consulta é conhecida como projeção. Uma projeção é uma representação de dados usando uma perspectiva diferente de seu sistema de armazenamento. Ao usar a fonte de eventos, os dados são armazenados como um fluxo de eventos, mas projetados em uma representação do estado atual do aplicativo. Essa representação é sem estado, imutável e idempotente – a criação da representação não modifica os dados do evento subjacente de forma alguma.

Uma única projeção pode precisar interagir com vários tipos de eventos diferentes. As projeções consideram os dados agregados, de uma forma que faça sentido para as funções do aplicativo. Em nosso exemplo anterior, uma projeção de Pedido poderia gerar um objeto contendo as propriedades CreatedDate, ApprovedDate e ShippedData examinando os eventos associados ao pedido em questão.

Conclusão

O sourcing de eventos é uma arquitetura de software especializada com suporte inato para responsabilidade, cronologia e recriação de estado. O padrão pode simplificar significativamente a implementação de aplicativos onde essas qualidades são desejáveis.

O fornecimento de eventos também pode ser útil em outros cenários, embora retornos decrescentes possam ser encontrados. A adoção de fontes de eventos exige que os desenvolvedores implementem códigos para determinar o estado atual, adicionando sobrecargas que não surgem em sistemas que armazenam apenas o estado atual em seus bancos de dados.

O fornecimento de eventos é melhor combinado com outras técnicas de arquitetura de software, como CQRS, o padrão do observador e eventual consistência. Você não precisa usar a fonte de eventos em todo o seu aplicativo – frequentemente, submódulos individuais se beneficiarão com o fornecimento de eventos, enquanto a maior parte do seu projeto fica com um banco de dados relacional tradicional.

Nenhum comentário