Skip to content

gustavofreze/transactional-outbox

Repository files navigation

Transactional outbox

Overview

Este projeto é uma POC para apresentar na prática uma forma de implementar o padrão Transactional outbox. Eu escrevi este artigo, explicando o que é o padrão, quando e o porque usá-lo.

Implementação

Existem maneiras distintas de implementar o padrão Transactional outbox. E a forma proposta nesta POC, basicamente, se apoia em 3 passos.

  • Salvar de forma transacional o seu registro do modelo e do evento. O código abaixo é a implementação do Adapter do repository.

    override fun save(event: TransactionRequested): Unit = jdbi.inTransactionUnchecked { handle ->
          handle
              .createUpdate(INSERT)
              .bind("id", event.transactionId.value.toString())
              .bind("value", event.amount.positive.value)
              .bind("currency", event.amount.currency.toString())
              .bind("countryAlpha2", event.country.alpha2)
              .execute()
    
          outboxEventOf(event = event).also { it.insertUsing(handle = handle) }
    }
  • Definir um Schema para o evento, neste caso, utilizei o formato JSON.

  • Definir um Conector para a tabela de outbox.

Instalação

Repositório

Para clonar o repositório usando a linha de comando, execute:

git clone https://github.com/gustavofreze/transactional-outbox.git

Configuração

Verifique se algum processo usa as portas: 2181, 3306, 3307, 8081, 8083, 8084, 9021, 9092 e 29092. Se alguma das portas descritas estiver em uso, ela deve ser “liberada”.

Para instalar e configurar o projeto, execute na raiz do projeto:

make configure

Roadmap

Verificando o ambiente

Para executar o caso de uso, basta estar com o ambiente docker inicializado.

Você pode conferir executando na raiz do projeto:

make configure-status

Containers inicializados.
Containers inicializados.

Executando o caso de uso

O caso de uso, consiste em uma transação solicitada pelo domínio de Checkout, por meio do evento CheckoutDone. Quando este evento ocorre, um registro é inserido na tabela do modelo, e outro na tabela de outbox, do domínio de Checkout. Com a tabela de outbox mapeada para o Kafka connect, ele lê os arquivos de bin log, e então publica os dados no tópicopayin.checkout.

make checkout-done

Registros de checkout inseridos.
Registros de checkout inseridos.

Com os dados publicados no tópico payin.checkout, uma política do domínio de Transaction reage a este evento, resultando no comando RequestTransaction. A execução do comando, resulta no evento TransactionRequested. Quando este evento ocorre, um registro é inserido na tabela do modelo, e outro na tabela de outbox, do domínio de Transaction. Da mesma forma a qual foi explicado anteriormente, o Kafka connect irá ler os arquivos de bin log, e então publicar os dados do evento TransactionRequested no tópico payin.transaction.

Acessando o Control Center, é possível verificar os eventos publicados em seus respectivos tópicos. No menu Topics, na aba Messages, utilize o filtro Partition, definindo o valor como 0.

Eventos do tópico payin.transaction.
Eventos do tópico payin.transaction.

Úteis

  • Para todos os containers do projeto:

    make stop
  • Remove todos os containers e networks criados pelo projeto:

    make clean
  • Remove todos os containers, networks e imagens criados pelo projeto:

    make clean-all