Olá, dev! Seja bem-vindo ao Dia 14 da sua preparação para a certificação MongoDB Associate Developer. Hoje abordaremos a camada de integração entre o código da sua aplicação e o banco de dados: o gerenciamento de conexões (Connection Pooling), a especificação de Retryable Writes/Reads e as melhores práticas para construir aplicações resilientes.
1. Formatos de Connection String (URI)
Os drivers oficiais do MongoDB suportam dois formatos principais para estabelecer conexão com clusters:
- Standard Connection String Format (
mongodb://): Especifica explicitamente a lista de nós, portas e opções de réplica.
mongodb://user:pass@node1.db.com:27017,node2.db.com:27017/?replicaSet=rs0&ssl=true - DNS Seedlist Format (
mongodb+srv://): Utiliza registros DNS SRV e TXT. Permite adicionar ou remover nós do Replica Set no nível de infraestrutura sem alterar a connection string na aplicação.
mongodb+srv://user:pass@cluster0.abcde.mongodb.net/meuBanco?retryWrites=true&w=majority
2. Connection Pooling & Ciclo de Vida do `MongoClient`
O MongoClient é o objeto raiz responsável por manter o pool de conexões com os servidores do MongoDB.
Parâmetros Fundamentais do Pool de Conexões:
maxPoolSize(Padrão: 100): O número máximo de conexões simultâneas abertas no pool para cada servidor.minPoolSize(Padrão: 0): Conexões mínimas mantidas ativas e aquecidas.maxIdleTimeMS: Tempo máximo em milissegundos que uma conexão ociosa pode permanecer no pool antes de ser fechada.serverSelectionTimeoutMS(Padrão: 30000 ms / 30s): Tempo que o driver tenta localizar e conectar a um nó compatível antes de lançar erro de timeout.
3. Retryable Writes e Retryable Reads
Em sistemas distribuídos, falhas de rede transitórias e eleições momentâneas de Replica Set podem interromper requisições. O MongoDB provê suporte nativo a repetições transparentes:
- Retryable Writes (
retryWrites=true): Habilitado por padrão. Se uma operação de escrita de documento único falhar devido a um erro transitório de rede ou eleição de Primary, o driver retenta a operação exatamente uma vez automaticamente. - Como o MongoDB Garante a Idempotência: O driver anexa um identificador de sessão lógica (
lsid) e um número sequencial de transação (txnNumber) ao comando. Se a escrita original já tiver sido processada no servidor antes da queda da rede, o Primary reconhece otxnNumbere simplesmente retorna o resultado com sucesso, evitando duplicação de dados. - Requisitos: O cluster deve ser um Replica Set ou Sharded Cluster (instâncias Standalone não suportam retryable writes) e o storage engine deve ser o WiredTiger.
- Retryable Reads (
retryReads=true): Habilitado por padrão. Retenta operações de leitura em caso de erro transitório de comunicação com os nós de dados.
4. Tratamento de Exceções no Código
Para o exame de certificação, é crucial distinguir as diferentes naturezas de erros retornados pelos drivers:
- Write Errors: Falhas na validação ou restrição dos dados. Exemplo clássico: Código 11000 (DuplicateKeyError), gerado ao tentar inserir um valor duplicado em um campo com índice
unique: true. - Write Concern Errors: A gravação do documento foi persistida com sucesso no nó Primary, mas não conseguiu a confirmação da maioria no tempo limite estipulado por
wtimeout. O dado foi salvo, mas não obteve garantia de replicação completa. - TransientTransactionError: Label de erro presente em transações multi-documento que indica que a transação inteira pode ser executada novamente no bloco de repetição (retry loop).
5. Exemplo de Configuração e Boas Práticas (Node.js / TypeScript)
import { MongoClient } from 'mongodb';
// Singleton para o MongoClient com Pool e Retry configurados
const uri = "mongodb+srv://admin:secret@cluster0.mongodb.net/?retryWrites=true&w=majority";
export const client = new MongoClient(uri, {
maxPoolSize: 50,
minPoolSize: 10,
serverSelectionTimeoutMS: 5000,
});
async function run() {
try {
await client.connect();
const db = client.db("producao");
const usuarios = db.collection("usuarios");
// Operação com retry automático garantido pelo driver
const resultado = await usuarios.insertOne({
email: "dev@exemplo.com",
status: "ATIVO"
});
console.log("Inserido ID:", resultado.insertedId);
} catch (error: any) {
if (error.code === 11000) {
console.error("Erro de negócio: Email já cadastrado!");
} else {
console.error("Erro inesperado no MongoDB:", error);
}
}
}
6. Questões no Estilo Exame de Certificação
Questão 1: Uma aplicação web de alta concorrência está instanciando um novo MongoClient dentro do manipulador (controller) de cada requisição HTTP recebida. Qual é a consequência dessa abordagem e como deve ser corrigida?
A) Não há impacto, pois o MongoDB gerencia conexões no sistema operacional.
B) Isso causa exaustão rápida do limite de conexões no servidor MongoDB e alto consumo de memória/CPU devido ao handshake constante de conexões; deve-se criar uma única instância compartilhada (Singleton) de MongoClient para toda a aplicação.
C) A aplicação lançará erro de Sharding automático.
D) O driver converterá automaticamente as requisições para conexões HTTP REST.
Resposta Correta: B. O MongoClient gerencia internamente um pool de conexões. Criar múltiplos clientes destrói a eficiência do pooling e sobrecarrega o servidor.
Questão 2: Quando o recurso retryWrites=true está ativo e ocorre um erro de rede durante um insertOne() em um Replica Set, como o MongoDB evita que o documento seja inserido duas vezes se a primeira tentativa tiver alcançado o Primary antes da desconexão?
A) O MongoDB desfaz a operação utilizando o log de transações.
B) O Primary armazena o txnNumber associado à sessão lógica do cliente e reconhece a segunda tentativa como uma operação repetida, retornando sucesso sem reexecutar a inserção.
C) O driver consulta todos os Secondaries antes de reenviar.
D) O MongoDB exige que todos os documentos tenham um UUID gerado pelo cliente para aceitar repetições.
Resposta Correta: B. O mecanismo de Retryable Writes utiliza sessões lógicas e números de transação para assegurar a idempotência estrita da operação.