Trilhas
/
Roc
Roc
/
Exercícios
/
Conta bancária
Conta bancária

Conta bancária

Fácil

Introdução

Depois de anos preenchendo formulários e esperando, você finalmente conseguiu sua licença bancária. Isso significa que agora você está oficialmente apto a abrir seu próprio banco, ebaaa!

Sua primeira prioridade é pôr os sistemas de TI para funcionar. Depois de um dia de trabalho puxado, você já consegue abrir e fechar contas, além de lidar com saques e depósitos.

Como você não quis se dar ao trabalho de escrever testes, você convida alguns amigos para ajudar a testar o sistema. Mas, depois de apenas cinco minutos, um dos seus amigos afirma que perdeu dinheiro! Embora você tenha certeza de que seu código não tem bugs, você começa a examinar os logs para investigar.

Ah, sim, exatamente como você suspeitava: a culpa é do seu amigo! Ele compartilhou as credenciais de teste com outro amigo, e juntos eles conspiraram para fazer depósitos e saques na mesma conta em paralelo. Quem faria uma coisa dessas?

Enquanto você argumenta que é fisicamente impossível alguém acessar a própria conta em paralelo, seu amigo avisa, com um ar de superioridade, que as regras bancárias exigem que você dê esse suporte. Ou seja: sem suporte a operações bancárias em paralelo, sem sinal verde para entrar em funcionamento. Suspirando, você faz uma nota mental para trabalhar nisso amanhã. Isso vai adiar sua data de lançamento em pelo menos mais um dia, mas, bem...

Instruções

Sua tarefa é implementar contas bancárias com suporte a abertura e fechamento, saques e depósitos de dinheiro.

Como as contas bancárias podem ser acessadas de muitas formas diferentes (internet, celulares, cobranças automáticas), o software do seu banco precisa permitir que as contas sejam acessadas com segurança a partir de várias threads/processos (a terminologia depende da sua linguagem de programação) em paralelo. Por exemplo, pode haver muitos depósitos e saques acontecendo em paralelo; você precisa garantir que não haja condições de corrida entre o momento em que você lê o saldo da conta e o momento em que define o novo saldo.

Deve ser possível fechar uma conta; operações em uma conta fechada devem falhar.

Responsabilidades do Roc e do host

No código Roc, normalmente focamos na lógica de negócio enquanto a plataforma cuida da concorrência e do estado compartilhado. Por isso, neste exercício você só precisa implementar as operações da conta em BankAccount.roc, sem se preocupar com concorrência. As contas começam fechadas, reabrir uma conta zera o saldo, e depósitos e saques precisam ser positivos.

Demonstração opcional do servidor

O arquivo bank-account-demo.roc incluído mostra como a sua implementação pode ser usada em um pequeno serviço web. Você pode lê-lo no editor, mas ele é independente dos testes e não faz parte da sua solução.

Para rodar a demonstração, você precisa instalar o Roc na sua máquina, instalar a CLI do Exercism e então rodar este comando em um terminal:

exercism download --exercise=bank-account --track=roc

Em seguida, implemente BankAccount.roc e teste com o comando a seguir (mude o local de download impresso pela CLI se ele for diferente do caminho abaixo):

cd ~/Exercism/roc/bank-account
roc test bank-account-test.roc

Quando todos os testes passarem, você pode iniciar o servidor da demonstração com o comando a seguir:

roc bank-account-demo.roc

O servidor usa a plataforma basic-webserver e o suporte a SQLite embutido nela (o Roc baixa a plataforma na primeira execução). Não é preciso um servidor de banco de dados separado. O servidor escuta em http://127.0.0.1:8000 e cria bank-account-demo.db no seu diretório atual (defina DB_PATH para usar outro arquivo de banco de dados). Pare o servidor com Ctrl-C. Os dados sobrevivem a reinicializações.

Em outro terminal, você pode chamar o serviço web usando curl (no Windows, use curl.exe o tempo todo para evitar o alias curl do PowerShell). Por exemplo, veja como abrir a conta #123, depositar 50, sacar 10 e consultar o saldo dela:

curl -X POST http://127.0.0.1:8000/accounts/123/open
curl -X POST http://127.0.0.1:8000/accounts/123/deposit/50
curl -X POST http://127.0.0.1:8000/accounts/123/withdraw/10
curl http://127.0.0.1:8000/accounts/123/balance

O saldo é 40. Os IDs das contas e os valores precisam ser inteiros sem sinal. As atualizações retornam OK em caso de sucesso ou um erro da sua implementação de conta em caso de falha. Para fechar a conta #123:

curl -X POST http://127.0.0.1:8000/accounts/123/close

Para testar requisições concorrentes no Linux/macOS, use um ID de conta novo e envie 100 depósitos a partir de oito clientes:

curl -X POST http://127.0.0.1:8000/accounts/456/open
seq 100 | xargs -P 8 -I '{}' curl --fail --silent --show-error -X POST http://127.0.0.1:8000/accounts/456/deposit/1
curl http://127.0.0.1:8000/accounts/456/balance

No Windows, use o PowerShell 7+ para o exemplo paralelo:

curl.exe -X POST http://127.0.0.1:8000/accounts/456/open
1..100 | ForEach-Object -Parallel { curl.exe --fail --silent --show-error -X POST http://127.0.0.1:8000/accounts/456/deposit/1 } -ThrottleLimit 8
curl.exe http://127.0.0.1:8000/accounts/456/balance

Todos os depósitos devem dar certo e o saldo deve ser 100.

Como a demonstração lida com a concorrência

Cada requisição lê a conta, chama as suas funções em Roc e salva o resultado dentro de uma transação Immediate do SQLite. Operações que falham são revertidas sem alterar a conta. O SQLite permite apenas um escritor por vez, o que impede que requisições concorrentes sobrescrevam as atualizações umas das outras (mesmo em contas diferentes).

Observação: o exercício usa U64, mas a demonstração armazena os saldos como inteiros do SQLite e rejeita atualizações que ultrapassem o valor máximo de I64 (9223372036854775807).

Para ver um exemplo de cálculos independentes rodando em paralelo, experimente o exercício parallel-letter-frequency.

Dicas

Mostrar dicas

Use match para distinguir Closed de Open(balance). Uma operação retorna uma conta atualizada em vez de modificar a conta recebida. Use Ok(updated_account) para uma atualização bem-sucedida e Err(...) para uma operação rejeitada.

Editar via GitHub O link abre em uma nova janela ou aba
Roc Exercism

Tudo pronto para começar Conta bancária?

Crie sua conta no Exercism para aprender e dominar Roc com 135 exercícios e mentoria humana de verdade, tudo de graça.