Skip to content

joaogabrielaraujo/TEC502-PBL2

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 

Repository files navigation


Projeto da disciplina TEC 502 - Concorrência e Conectividade

Este projeto foi desenvolvido como parte da disciplina MI - Concorrência e Conectividade, do curso de Engenharia de Computação da Universidade Estadual de Feira de Santana (UEFS).

Introdução

Este relatório apresenta a solução desenvolvida para implementar um sistema de transações bancárias semelhante ao Pix, em um país que não possui um banco central. A principal demanda do governo era a criação de um sistema que permitisse a realização de pagamentos, depósitos e transferências entre contas de diferentes bancos, sem utilizar recursos centralizados para controlar as transações.

Com o objetivo de atender aos requisitos solicitados, foi estabelecido um consórcio bancário. A solução proposta foi baseada em um sistema distribuído que garante a comunicação eficiente e segura entre os bancos, permitindo que os clientes realizem transações atômicas sobre suas contas, sejam elas de pessoa física (particulares ou conjuntas) ou jurídica.

Os desafios principais incluíam a prevenção de movimentações de dinheiro além do saldo disponível e a eliminação do risco de duplo gasto, onde o mesmo dinheiro poderia ser transferido para mais de uma conta simultaneamente.

Sumário

Aplicação - API

2PC - Two-Phase Commit

O código apresentado utiliza um método de "two phase commit" (compromisso em duas fases) em conjunto com bloqueios (locks) para garantir a consistência das operações bancárias distribuídas.

O "two phase commit" é um protocolo utilizado para garantir a atomicidade das transações distribuídas, ou seja, garantir que todas as operações relacionadas a uma transação sejam executadas com sucesso ou que nenhuma delas seja executada.

Preparação (Fase 1):

  • Função preparar_transferencia() e preparar_conta_externa(): Essas funções são responsáveis por preparar as contas envolvidas na transação. Isso inclui verificar se as contas existem, aplicar bloqueios (lock.acquire()) para garantir exclusividade durante a modificação da conta e realizar qualquer outra preparação necessária, como verificar saldos suficientes para transferências.

  • Bloqueios (Locks): Os bloqueios são fundamentais para garantir que apenas uma thread ou processo por vez possa modificar uma determinada conta. Isso previne problemas de consistência que poderiam ocorrer se múltiplos processos tentassem modificar a mesma conta simultaneamente. Após a preparação, os bloqueios são liberados (lock.release()) para permitir que outras operações possam ser executadas.

Confirmação (Fase 2):

Após a fase de preparação, o sistema avança para a fase de confirmação das transações preparadas:

  • Função confirmar_transferencia() e confirmacao_conta_externa(): Estas funções são responsáveis por confirmar as operações preparadas na fase anterior. Isso inclui efetuar transferências reais entre contas dentro do banco ou enviar solicitações de transferência para bancos externos, dependendo do destino da transação.

  • Commit ou Rollback: Durante esta fase, é crucial garantir que todas as operações preparadas sejam efetivadas (commit) apenas se todas forem executadas com sucesso. Caso contrário, se ocorrer algum erro durante a confirmação, é necessário desfazer (rollback) todas as operações preparadas para manter a integridade dos dados.

Desfazer (Rollback):

Se ocorrer qualquer falha durante a preparação ou confirmação das transações, é necessário desfazer todas as operações preparadas para evitar estados inconsistentes no sistema:

  • Função desfazer_transferencia() e desfazer_conta_externa(): Essas funções são acionadas em caso de erro durante a preparação ou confirmação das transações. Elas revertem quaisquer modificações feitas durante a preparação, garantindo que nenhuma mudança inconsistente seja persistida no sistema.

Rotas para Gerenciamento de Contas

Rota para cadastrar uma pessoa física:

  • POST /cadastro_pessoa_fisica
  • Recebe dados JSON (nome, CPF, senha) e cadastra uma pessoa física.
  • Verifica se todos os dados obrigatórios foram fornecidos e se o cliente já está cadastrado. Em caso de sucesso, retorna uma mensagem de confirmação e detalhes da conta criada.

Rota para cadastrar uma pessoa jurídica:

  • POST /cadastro_pessoa_juridica
  • Recebe dados JSON (nome, CNPJ, senha) e cadastra uma pessoa jurídica.
  • Verifica se todos os dados obrigatórios foram fornecidos e se o cliente já está cadastrado. Em caso de sucesso, retorna uma mensagem de confirmação e detalhes da conta criada.

Rota para cadastrar uma conta conjunta:

  • POST /cadastro_conta_conjunta
  • Recebe dados JSON (identificador1, identificador2, senha) e cadastra uma conta conjunta.
  • Verifica se os identificadores e a senha foram fornecidos e se os clientes existem. Em caso de sucesso, retorna uma mensagem de confirmação e detalhes da conta criada.

Rota para fazer login:

  • POST /login
  • Recebe dados JSON (identificador, senha) e autentica o cliente.
  • Verifica se o identificador e a senha foram fornecidos.
  • Em caso de sucesso, retorna uma mensagem de login bem-sucedido e detalhes do cliente.

Rota para fazer logout:

  • POST /logout
  • Desloga o cliente atualmente logado.
  • Retorna uma mensagem de confirmação de logout.

Rota para obter todas as contas de um cliente em todos os bancos:

  • GET /contas_cliente/
  • Recebe um identificador (CPF/CNPJ) e retorna todas as contas associadas a esse cliente em todos os bancos.
  • Verifica se o identificador foi fornecido e se o cliente existe.
  • Em caso de sucesso, retorna uma lista de todas as contas do cliente.

Rota para obter todas as contas de um cliente em um banco específico:

  • GET /get_contas/
  • Recebe um identificador (CPF/CNPJ) e retorna todas as contas associadas a esse cliente no banco atual.
  • Verifica se o identificador foi fornecido e se o cliente existe.
  • Em caso de sucesso, retorna uma lista de todas as contas do cliente no banco atual.

Rota para obter uma conta de um cliente em um banco específico:

  • GET /get_conta/<nome_banco>/<numero_conta>
  • Recebe o nome do banco e o número da conta e retorna os detalhes dessa conta.
  • Verifica se o nome do banco e o número da conta foram fornecidos.
  • Em caso de sucesso, retorna os detalhes da conta.

Rota para obter o identificador do cliente logado:

  • GET /get_identificador
  • Retorna o identificador (CPF/CNPJ) do cliente atualmente logado.
  • Verifica se há um cliente logado.
  • Em caso de sucesso, retorna o identificador do cliente logado.

Rota para obter o nome do banco:

  • GET /get_nome_banco
  • Retorna o nome do banco atual.

Rotas Designadas para Lógica Bancária

Rota responsável por realizar um depósito

  • Endpoint: /deposito
  • Método HTTP: POST
  • Funcionalidade:
  • Recebe dados em formato JSON contendo o número da conta, nome do banco e valor a ser depositado. Valida os dados recebidos e executa o depósito na conta correspondente:
  • Se o banco for o mesmo em que o cliente está logado (banco.nome), o depósito é realizado diretamente na conta interna usando métodos do objeto banco. Caso contrário, delega a operação para o método deposito_outro_banco do objeto banco, que lida com depósitos em bancos externos.

Rota responsável por realizar um saque

  • Endpoint: /saque
  • Método HTTP: POST
  • Funcionalidade:
  • Recebe dados em formato JSON contendo o número da conta e o valor a ser sacado.
  • Valida os dados e executa o saque na conta correspondente usando métodos do objeto banco.

Rota responsável por preparar uma transferência

  • Endpoint: /preparar_transferencia
  • Método HTTP: POST
  • Funcionalidade:
  • Recebe dados em formato JSON contendo o número da conta, nome do banco, tipo de transferência e valor a ser transferido.
  • Valida os dados e prepara a transferência: Se o banco for o mesmo em que o cliente está logado (banco.nome), prepara a transferência usando métodos do objeto banco. Caso contrário, delega a operação para o método preparar_conta_externa do objeto banco, que prepara a conta externa para a transferência.

Rota responsável por confirmar uma transferência

  • Endpoint: /confirmar_transferencia
  • Método HTTP: POST
  • Funcionalidade: Recebe dados em formato JSON contendo o número da conta, nome do banco, tipo de transferência e valor a ser transferido.
  • Valida os dados e confirma a transferência: Se o banco for o mesmo em que o cliente está logado (banco.nome), confirma a transferência usando métodos do objeto banco. Caso contrário, delega a operação para o método confirmacao_conta_externa do objeto banco, que confirma a transferência na conta externa.

Rota responsável por desfazer alterações

  • Endpoint: /desfazer_transferencia
  • Método HTTP: POST
  • Funcionalidade: Recebe dados em formato JSON contendo o número da conta, nome do banco, tipo de transferência e valor a ser desfeito.
  • Valida os dados e desfaz as alterações: Se o banco for o mesmo em que o cliente está logado (banco.nome), desfaz as alterações usando métodos do objeto banco. Caso contrário, delega a operação para o método desfazer_conta_externa do objeto banco, que desfaz as alterações na conta externa.

Rota responsável por realizar a transferência

  • Endpoint: /transferir
  • Método HTTP: POST
  • Funcionalidade: Recebe dados em formato JSON contendo o nome do banco de destino, número da conta de destino, valor a ser transferido e uma lista de transferências adicionais.
  • Executa a transferência em duas fases: Preparação: Prepara todas as contas envolvidas na transferência. Confirmação: Confirma as operações preparadas. Usa métodos do objeto banco para realizar essas operações de preparação e confirmação.

Rotas Designadas para Interface

Rota para página de login

  • Endpoint: /
  • Método HTTP: GET
  • Funcionalidade: Renderiza o template login.html, que geralmente contém formulários para login.

Rota para a página de Home

  • Endpoint: /home
  • Método HTTP: GET
  • Funcionalidade: Tenta obter informações das contas do cliente logado e o nome do banco. Realiza chamadas HTTP para endpoints específicos do banco usando requests.get. Se obter sucesso nas chamadas, renderiza o template home.html passando o nome do banco e informações das contas.

Rota para a página de cadastro

  • Endpoint: /cadastro
  • Método HTTP: GET
  • Funcionalidade: Renderiza o template cadastro.html, utilizado para cadastro de novos clientes.

Rota para renderizar a página de depósito

  • Endpoint: /deposito_page
  • Método HTTP: GET
  • Funcionalidade: Renderiza o template deposito.html, que provavelmente contém formulários para realizar depósitos em contas.

Rota para acessar a página de saque

  • Endpoint: /saque_page
  • Método HTTP: GET
  • Funcionalidade: Renderiza o template saque.html, onde são disponibilizados formulários para realizar saques de contas bancárias.

Rota para a página de Transferência

  • Endpoint: /transferencia_page
  • Método HTTP: GET
  • Funcionalidade: Tenta obter informações das contas do cliente logado e o nome do banco. Realiza chamadas HTTP para endpoints específicos do banco usando requests.get. Se obter sucesso nas chamadas, renderiza o template transferencia.html passando o nome do banco e informações das contas.

Execução via Docker

Para executar sem precisar contruir uma imagem, já existe uma imagem feita que está hospedada no site https://www.docker.com/

Siga pos seguintes passos para executar o broker:

docker pull joaogabrielaraujo/bank
docker run --network=host -it -e NUMERO_BANCO=<número do banco> -e IP_BANCO1=<ip do banco 1> -e IP_BANCO2=<ip do banco 2> -e IP_BANCO3=<ip do banco 3> joaogabrielaraujo/bank

Tomando exemplo de números de ip's fictícios: Computador 1 = 250.0.0.1, Computador 2 =250.0.0.2, Computador 3 = 250.0.0.3

  • comando do computador 1:
docker run --network=host - it - NUMERO_BANCO=1 -e IP_BANCO2=250.0.0.2 -e IP_BANCO3=250.0.0.3 joaogabrielaraujo/bank
  • comando do computador 2:
docker run --network=host - it - NUMERO_BANCO=2 -e IP_BANCO1=250.0.0.1 -e IP_BANCO3=250.0.0.3 joaogabrielaraujo/bank
  • comando do computador 3:
docker run --network=host - it - NUMERO_BANCO=3 -e IP_BANCO1=250.0.0.1 -e IP_BANCO2=250.0.0.2 joaogabrielaraujo/bank

Conclusão

A implementação bem-sucedida deste sistema distribuído para transações bancárias possibilita a realização de pagamentos, depósitos e transferências entre contas de diferentes bancos sem a necessidade de um banco central. A solução desenvolvida atendeu plenamente aos requisitos estabelecidos pelo governo, proporcionando uma plataforma robusta e segura para os clientes realizarem transações atômicas de forma eficiente.

Ao adotar uma abordagem distribuída, foi possível garantir a integridade das transações, prevenindo movimentações de dinheiro além do saldo disponível e eliminando o risco de duplo gasto. A comunicação entre os bancos foi estabelecida de maneira eficaz, assegurando que as transações fossem processadas de forma correta.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published