Em uma busca rápida no Google, o primeiro significado que eu encontrei para a palavra resiliência, foi: “Capacidade de se recobrar facilmente ou se adaptar à má sorte ou às mudanças.”
Palavra forte e empoderadora, que trouxe à tona a seguinte questão: você tem se preocupado em criar aplicações resilientes?
O MongoDB é um SGBD fantástico! Mas se ele for a sua escolha, você precisa estar atento as características dele para criar uma aplicação resiliente.
Em artigos anteriores eu falei um pouco sobre as transações multidocumento no MongoDB 4.0. Este recurso é muito legal e pode ser um diferencial para as suas aplicações… E este post tem como objetivo principal fazer com que as transações multidocumento sejam um diferencial positivo!!!
De acordo com a documentação da MongoDB “Independentemente do SGBD, seja o MongoDB ou bancos de dados relacionais, os aplicativos devem tomar medidas para lidar com erros durante os commits de transação e incorporar a lógica necessária para a repetição dos comandos.”
Quando ocorre um erro em uma operação, dentro transação multidocumento, as operações não podem ser executadas novamente de maneira automática (não chorem por isso!). Caberá a você criar uma aplicação que se recupere deste estado. E acredite em mim, não é difícil!
Quando ocorre um erro transitório ele deve ser identificado para que a transação seja automaticamente repetida.
E como identificar este tipo de erro? É só verificar se a matriz errorLabels contém um elemento “TransientTransactionError”.
O exemplo de código abaixo, extraído da documentação oficial do MongoDB, vemos como tratar os erros transientes
// Executa a transação txnFunc e tenta novamente se encontrar TransientTransactionError function runTransactionWithRetry(txnFunc, session) { while (true) { try { txnFunc(session); // executa a transação break; } catch (error) { print("Transaction aborted. Caught exception during transaction."); // Se ocorrer um erro transitório, tente novamente toda a transação if ( error.hasOwnProperty("errorLabels") && error.errorLabels.includes( "TransientTransactionError") ) { print("TransientTransactionError, retrying transaction ..."); continue; } else { throw error; } } } }
Retryable Writes
Este recurso não é uma novidade da versão 4.0 do MongoDB (foi lançado na versão 3.6), mas para que você faça uma aplicação resiliente é muito bom você conhecê-lo.
As Retryable Writes permitem que o driver do MongoDB tente automaticamente fazer uma nova tentativa da operação realizada sobre dados se encontrar erros (por exemplo, não encontrou um primary, erros de rede, etc).
E combina com as transações? Sim e não.
As operações de commit e o abort são operações que podem ser repetidas, ou seja, se ocorrer um erro em uma destas etapas, os drivers do MongoDB tentarão novamente fazer a operação, independentemente da propriedade retryWrites estar definida como true.
Contudo, todavia e entretanto as operações de gravação dentro de uma transação não podem ser repetidas individualmente, independentemente de retryWrites estar definida como true.
Para habilitar o retryWrites no Mongo Shell:
Mongo --retryWrites
Resumindo, se ocorrer um erro em uma operação de commit ou abort, o MongoDB automaticamente irá fazer uma nova tentativa.
Mas e se na nova tentativa ocorrer um erro, a operação não será executada novamente. Cabe a você criar o código para que esta situação não ocorra, deixando sua aplicação mais resiliente.
Erros no commit da transação são identificados no elemento “UnknownTransactionCommitResult” da matriz errorLabels.
A seguir temos um exemplo de tratamento para este erro, extraído da documentação oficial do MongoDB:
// Tenta novamente fazer o commit de uma transação se encontrar um erro function commitWithRetry(session) { while (true) { try { session.commitTransaction(); print("Transaction committed."); break; } catch (error) { // Can retry commit if (error.hasOwnProperty("errorLabels") && error.errorLabels.includes( "UnknownTransactionCommitResult") ) { print("UnknownTransactionCommitResult, retrying commit operation ..."); continue; } else { print("Error during commit ..."); throw error; } } } }
Conclusão
O MongoDB 4.0 tem muitas possibilidades fantásticas! Mas para utilizá-lo com sucesso caberá a você conhecer as características dele e construir aplicações cada vez melhores e mais resilientes!