CQRS e Event Sourcing em Rust: Arquitetura para desempenho sem concessões

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Por que CQRS e Event Sourcing não são "exagero", mas sim uma salvação para sistemas complexos

\n\n

Você já se deparou com uma situação em que seu sistema, escrito em Rust, lida perfeitamente com solicitações de leitura, mas "cai de joelhos" na gravação? Ou vice-versa — você sacrifica o desempenho da leitura para poder salvar o histórico completo de alterações? Familiar? Então bem-vindo ao mundo do CQRS e do Event Sourcing.

\n\n

Muitos desenvolvedores consideram esses padrões como "artilharia pesada", aplicável apenas em projetos enterprise em C# ou Java. Mas com o crescimento da popularidade do Rust em sistemas de alta carga (de servidores de jogos a plataformas financeiras), CQRS e Event Sourcing tornam-se não apenas úteis — eles se tornam necessários. Rust, com seu custo zero de abstrações e tipagem estrita, é a linguagem ideal para implementar esses padrões.

\n\n

Neste artigo, não vamos apenas falar sobre teoria. Vamos escrever código funcional em Rust que você poderá adaptar para seus projetos. Você aprenderá como separar a responsabilidade entre comandos e consultas, como armazenar eventos em vez do estado atual e como tudo isso acelera seu sistema várias vezes.

\n\n

O que são CQRS e Event Sourcing? Em linguagem simples para o desenvolvedor Rust

\n\n

Imagine que você gerencia uma conta bancária. No modelo CRUD tradicional, você tem uma tabela "Contas" onde o saldo atual é armazenado. Se precisar ver o histórico, você cria outra tabela "Transações". Mas e se você precisar não apenas saber o saldo, mas entender por que ele mudou? Ou restaurar o estado em qualquer data?

\n\n

CQRS: Dividir para conquistar

\n\n

CQRS (Command Query Responsibility Segregation) é um princípio que divide as operações em dois grupos:

\n
    \n
  • Comandos (Commands) — alteram o estado. Eles não retornam dados, apenas confirmação ou erro.
  • \n
  • Consultas (Queries) — apenas leem dados. Eles não alteram o estado.
  • \n
\n\n

Em Rust, essa divisão parece natural: os tipos de comandos e consultas são estruturas diferentes, e seus manipuladores são funções ou módulos diferentes. Isso não é apenas uma "boa prática", é uma maneira de evitar mutações acidentais durante a leitura.

\n\n
// Comando — altera o estado\npub struct CreateOrder {\n    pub user_id: Uuid,\n    pub items: Vec<OrderItem>,\n}\n\n// Consulta — apenas lê\npub struct GetOrderHistory {\n    pub user_id: Uuid,\n    pub limit: usize,\n}
\n\n

Event Sourcing: Armazene o histórico, não uma foto instantânea

\n\n

Event Sourcing é uma abordagem onde salvamos não o estado atual de um objeto, mas a sequência de eventos que levaram a ele. Quer saber o saldo da conta em 1º de janeiro de 2023? Basta "reproduzir" todos os eventos desde o início até essa data.

\n\n

As vantagens são óbvias:

\n
    \n
  • Auditoria — cada alteração é registrada.
  • \n
  • Instantâneos temporais — é possível restaurar qualquer estado.
  • \n
  • Resistência a bugs — se houver um erro no código, você não perdeu os dados, apenas os "reproduziu" incorretamente.
  • \n
\n\n

Exemplo prático: Sistema de gerenciamento de pedidos em Rust

\n\n

Vamos construir um mini-sistema para uma loja online. Ele processará comandos (criação de pedido, adição de item) e consultas (obter carrinho, histórico de pedidos). Toda a lógica será baseada em eventos.

\n\n

Passo 1: Definindo eventos e comandos

\n\n

A primeira coisa a fazer é projetar o domínio. Em Rust, usamos enumerações (enum) para eventos e estruturas estritas para comandos.

\n\n
use serde::{Deserialize, Serialize};\nuse uuid::Uuid;\n\n// Eventos — fatos imutáveis\n#[derive(Debug, Clone, Serialize, Deserialize)]\npub enum OrderEvent {\n    Created { order_id: Uuid, user_id: Uuid, timestamp: i64 },\n    ItemAdded { order_id: Uuid, item: Str                

Blogs

Book Recommendations