Seu carrinho está vazio no momento!

Introdução (3 min)
Imagine uma transferência bancária. Você está enviando dinheiro da sua conta para a conta de um amigo. Esse processo precisa ser confiável, certo? Não podemos ter dinheiro sumindo no ar ou aparecendo duplicado. As propriedades ACID garantem exatamente isso, a confiabilidade das transações, em diversos contextos, incluindo APIs.
Em APIs modernas, especialmente aquelas que lidam com dados sensíveis como e-commerce ou sistemas financeiros, a integridade dos dados é imprescindível. As propriedades ACID são vitais para garantir que as operações sejam processadas de forma segura e consistente.
Nesta aula, desenvolveremos um exemplo prático em Node.js/Express, demonstrando como implementar transações com as propriedades ACID utilizando um banco de dados.
Dentro do ecossistema Node.js/Express, o gerenciamento de transações é frequentemente realizado com o auxílio de bibliotecas de acesso a banco de dados, como o Sequelize ou o Mongoose, que fornecem abstrações para facilitar a implementação das propriedades ACID.
Conceito Fundamental (7 min)
ACID é um acrônimo para Atomicidade, Consistência, Isolamento e Durabilidade. Essas quatro propriedades asseguram que as transações sejam processadas de maneira confiável.
- Atomicidade: A transação é tratada como uma unidade indivisível. Ou todas as operações são concluídas com sucesso, ou nenhuma é. Imagine como um interruptor de luz: está ligado ou desligado, não existe meio termo.
- Consistência: A transação mantém a integridade dos dados. Se o banco de dados tinha certas regras antes da transação, essas regras continuam válidas após a transação. Pense em um jogo de xadrez: cada movimento deve seguir as regras do jogo, mantendo a consistência do jogo.
- Isolamento: Transações concorrentes são isoladas umas das outras, como se estivessem sendo executadas individualmente. Imagine vários cozinheiros trabalhando na mesma cozinha, cada um com sua própria estação de trabalho, sem interferir no trabalho dos outros.
- Durabilidade: Uma vez que a transação é concluída, as alterações são permanentes, mesmo em caso de falha do sistema. Pense em salvar um documento: uma vez salvo, ele permanece salvo mesmo se o computador for desligado.
Casos de uso reais incluem sistemas de reserva de passagens aéreas, compras online e operações bancárias. A integração com outras tecnologias, como bancos de dados relacionais (SQL) e NoSQL, é feita através de drivers e ORMs.
As vantagens de usar transações ACID são a confiabilidade e a integridade dos dados. A principal desvantagem pode ser um pequeno impacto no desempenho devido ao overhead de gerenciamento das transações.
Implementação Prática (10 min)
const express = require('express');
const Sequelize = require('sequelize');
const app = express();
const sequelize = new Sequelize('database', 'user', 'password', {
dialect: 'mysql', // Adapte para o banco de dados do seu HostGator Plano M
host: 'localhost', // Host do seu banco de dados
logging: console.log, // Logging profissional para o console
});
// Definição do modelo de usuário (adapte para suas necessidades)
const User = sequelize.define('user', {
balance: {
type: Sequelize.INTEGER,
},
});
app.post('/transfer', async (req, res) => {
const { from, to, amount } = req.body;
// Validação robusta de entrada
if (!from || !to || !amount || amount <= 0) {
return res.status(400).json({ error: 'Parâmetros inválidos' });
}
try {
// Inicia a transação
await sequelize.transaction(async (t) => {
// Bloqueia as linhas para evitar condições de corrida
const [sender, receiver] = await Promise.all([
User.findByPk(from, { lock: true, transaction: t }),
User.findByPk(to, { lock: true, transaction: t }),
]);
if (!sender || !receiver) {
throw new Error('Usuário não encontrado');
}
if (sender.balance < amount) {
throw new Error('Saldo insuficiente');
}
// Atualiza os saldos atomicamente dentro da transação
await Promise.all([
sender.update({ balance: sender.balance - amount }, { transaction: t }),
receiver.update({ balance: receiver.balance + amount }, { transaction: t }),
]);
});
res.json({ message: 'Transferência realizada com sucesso' });
} catch (error) {
console.error('Erro na transferência:', error); // Log de erro detalhado
res.status(500).json({ error: 'Erro ao processar a transferência' });
}
});
app.listen(3000, () => console.log('Servidor rodando na porta 3000'));
npm install express sequelize mysql2
Exercício Hands-On (5 min)
Implemente um endpoint /revert que reverte uma transferência específica, utilizando uma transação para garantir a atomicidade da operação. Você precisará adicionar um modelo para armazenar as transferências e usar esse modelo para reverter a operação.
Solução:
A solução envolverá buscar a transferência no banco de dados, verificar se ela existe e, em seguida, dentro de uma transação, atualizar os saldos dos usuários envolvidos e marcar a transferência como revertida.
Testes:
Use ferramentas como Postman ou Insomnia para testar seus endpoints, simulando diferentes cenários, incluindo transferências válidas, saldos insuficientes e usuários inexistentes.
Troubleshooting:
Verifique o log de erros para identificar problemas. Certifique-se de que as dependências estejam instaladas corretamente e que a configuração do banco de dados esteja correta para o HostGator Plano M.
Próximos Passos:
Explore outras funcionalidades relacionadas a transações, como pontos de salvamento (savepoints) e diferentes níveis de isolamento de transação.
🚀 Pronto para a próxima aula?
Continue sua jornada no desenvolvimento de APIs e domine Node.js & Express!