La famille d'erreurs "TransientError" en MongoDB indique qu'une erreur est survenue mais que rien ne garanti que cette erreur apparaitra de nouveau si l'on relance le même code.

Mais qu'est-ce que cela signifie ?

Cela veut dire que la cause de l'erreur ne provient pas de la requête (ou de l'ensemble des requêtes dans le cas d'une transaction), mais peut provenir d'un facteur extérieur.

L'exemple le plus simple est une micro-coupure du réseau au moment d'une requête : cette dernière n'a pas pu s'exécuter correctement, mais si on la relance tout peut très bien se passer.

En résumé, TransientError = vous pouvez retenter la requête.

On trouve comme cause le réseau, éventuellement le manque d'espace disque et d'autres causes plus pernicieuses avec des noms et des codes qui ne donnent pas beaucoup d'indices sur l'origine de l'erreur, comme par exemple "NoSuchTransaction".

NoSuchTransaction - Transaction X has been aborted

Si cette erreur vous est familière et que vous êtes ici, c'est sûrement parce que vous n'avez pas pu trouver l'origine, et pour cause cette erreur ne nous apprends pas grands chose, et la documentation non plus.

Prenons le code entier de cette erreur :

{ MongoError: Transaction 1 has been aborted.
  at server/node_modules/mongodb-core/lib/connection/pool.js:581:63
  at authenticateStragglers (/server/node_modules/mongodb-core/lib/connection/pool.js:504:16)
  at Connection.messageHandler (server/node_modules/mongodb-core/lib/connection/pool.js:540:5)
  ...
  errorLabels: [ 'TransientTransactionError' ],
  operationTime:
  Timestamp { _bsontype: 'Timestamp', low_: 2, high_: 1544250067 },
  ok: 0,
  errmsg: 'Transaction 1 has been aborted.',
  code: 251,
  codeName: 'NoSuchTransaction',
  ...
}

En essayant de le déchiffrer, on comprend que la transaction n'existe plus : "NoSuchTransaction".

Pourquoi ? Car elle a été annulée par le système lui-même : "Transaction 1 has been aborted."

Mais pourquoi cette transaction a-t-elle été annulée ?

Il y a fort à parier que vous ayez reçu cette erreur après avoir attendu la fin de la transaction pendant un certain moment. Tout simplement parce que cette erreur indique que la transaction a été annulée car elle mettait trop de temps à s'exécuter.

Ce n'est pas très visible dans la documentation officielle, mais il est indiqué que, par défaut, MongoDB annulera toute transaction durant plus de 60 secondes afin d'éviter de bloquer la base pendant trop longtemps.

Les solutions

Vérifier que votre transaction n'est pas bloquée

En effet, si jamais il y a un problème dans votre code logique et que l'exécution ou l'enchainement des opération est bloqué, alors MongoDB stoppera tout simplement la transaction en question.

Vous pouvez alors vérifier l'exécution de chaque opération en dehors de votre transaction pour vérifier que tout fonctionne correctement.

Réduire le temps d'exécution

Il se peut que vous ayez tellement d'opérations à effectuer sur la base de données au sein de votre transaction que le temps d'exécution total dépasse simplement le timeout par défaut de MongoDB.

La meilleure solution sera alors de trouver un moyen pour faire en sorte que votre transaction mette moins de temps à s'exécuter.

Si vous utilisez NodeJS, l'une des clés de solutions si vous bouclez sur beaucoup de données que peut être de remplacer des appels async/await par un Promise.all comme expliqué dans cet article.

Modifier la configuration de MongoDB

Si jamais vos contraintes métier vous obligent à concevoir une transaction qui dépasse le timeout par défaut de 60 secondes (ce qui n'est pas recommandé), alors la dernière solution sera de modifier la configuration de la base pour augmenter le temps autorisé pour une transaction :

db.adminCommand( { setParameter: 1, transactionLifetimeLimitSeconds: 90 } )

Pour plus d'informations, je vous invite à lire la documentation officielle sur les transactions : https://docs.mongodb.com/manual/core/transactions-sharded-clusters/

J'espère que cet article vous aura été utile, et à bientôt sur le blog !

Les articles les plus populaires du blog

Envie de continuer à lire des articles autour du développement web (entre autres) ? Voici la sélection des articles de mon blog les plus lus par la communauté !

Voir la sélection 🚀

Recevez les articles de la semaine par e-mail pour ne rien manquer !

S'abonner à la newsletter 📧

À propos de l'auteur

Hello, je suis Nicolas Brondin-Bernard, ingénieur web indépendant depuis 2015 passionné par le partage d'expériences et de connaissances.

Aujourd'hui je suis aussi coach pour développeurs web juniors, tu peux me contacter sur nicolas@brondin.com, sur mon site ou devenir membre de ma newsletter pour ne jamais louper le meilleur article de la semaine et être tenu au courant de mes projets !


Photo by Sigmund on Unsplash