Este projeto visa simular um autorizador de transações financeiras, onde é possível realizar transações crédito.
- Gradle multi-modules;
- Spring Web, JDBC Client;
- PostgreSQL;
Os seguintes pré-requisitos são necessários para a execução do projeto:
Após instalado os pré-requisitos, execute o projeto a partir da classe principal do projeto app/src/main/java/com.transactions.app/Application.java. A aplicação será executada na porta 8080 e rodará os scripts de seeding para popular o banco de dados que será criado no container do Docker.
A aplicação conta com o Swagger para documentação dos endpoints, que pode ser acessado através do link http://localhost:8080/.
O seguinte endpoint estará disponível para realizar transações:
- POST /transactions/authorize
Body:
{
"accountId": "ee73630f-31f9-4105-b433-537fd3d79e41", // Id da conta
"merchantName": "Merchant Teste", // Nome do estabelecimento
"mcc": "5412", // Código de atuação do estabelecimento
"amountCents": 1000 // Valor da transação em centavos
}
O motivo da escolha do valor da transação ser em centavos é para evitar problemas com arredondamentos de valores decimais.
O projeto foi dividido em 2 módulos seguindo o padrão de arquitetura hexagonal/clean architecture:
- app: Módulo da aplicação, responsável por orquestrar as chamadas aos serviços e regras de negócio por meio de uma API Rest.
- domain: Módulo que contém as entidades e regras de negócio da aplicação. O módulo não depende de nenhum outro módulo tendo dependêcia somente com a especificação de injeção de dependêcias do Java, protegendo o domínio de tecnologias específicas de frameworks como o Spring, sendo assim portátil para outros frameworks caso seja necessário.
Para solucionar o problema de concorrência, foi utilizado o conceito de lock otimista, onde é verificado se a conta foi atualizada por outra transação por meio de um campo de versão. Caso a versão da conta seja diferente da versão que foi lida, a transação é rejeitada. Deixando para o cliente realizar uma nova tentativa de transação.
Foi implementado no DbAccountRepository essa verificação:
UPDATE balanceaccount SET balancecents = ?, lockversion = ? WHERE id = ? AND lockversion = ?
Caso nenhum registro seja atualizado, a transação é rejeitada.
Para simular transações simultâneas, foi criado um script de teste de carga utilizando o K6, que realiza 10 requisições simultâneas ao endpoint de autorização de transações. O script pode ser encontrado na raiz do projeto no arquivo load-test.js que pode ser executado com o comando:
$ k6 run load-test.js
Somente uma transação será autorizada, as demais serão rejeitadas.
Um ponto de melhoria seria a implementação de um mecanismo de retry para as transações rejeitadas, para que o cliente não precise realizar uma nova tentativa manual.
Outro ponto de melhoria seria implementar o conceito de idempotência para evitar transações duplicadas.