Une application Android de transfert de fonds populaire ne parvenait pas à envoyer de l'argent dans une région spécifique. L'application effectuait les requêtes réseau habituelles, mais rien n'indiquait la cause du problème. Il allait me falloir toutes mes compétences de détective, ainsi qu'un peu de chance, pour retrouver la cause profonde.
En tant que développeur Android travaillant sur une application de transfert de fonds populaire prenant en charge plus de 100 000 utilisateurs, il est de mon devoir de veiller à ce que l'application fonctionne correctement et que tous les problèmes signalés soient résolus rapidement. J'avais l'habitude de recevoir des tickets d'assistance occasionnels d'utilisateurs signalant des problèmes avec l'application. Mais un jour, j'ai reçu un déluge de tickets de personnes qui n'envoyaient pas d'argent dans une région particulière via l'application. C'était particulièrement inquiétant car c'était proche de la période des fêtes, une période où de nombreuses personnes comptent sur notre application pour envoyer de l'argent à leurs proches.
Je savais que je devais aller au fond de ce problème le plus rapidement possible. Je me suis donc tourné vers la sagesse de Sherlock Holmes et j'ai commencé mon travail de détective. Mais comme je l'ai vite découvert, résoudre ce problème n'allait pas être une tâche facile. Il allait falloir toutes mes compétences de détective, ainsi qu'un peu de chance, pour retrouver la cause première du bogue et faire fonctionner à nouveau l'application correctement.
La mise en place
J'ai commencé par reproduire le problème sur mon propre appareil, en essayant d'envoyer de l'argent dans la région touchée. Effectivement, l'application s'est figée et a affiché un message d'erreur indiquant : "Échec de la transaction. Veuillez réessayer plus tard." J'ai essayé d'utiliser un profileur dans Android Studio pour voir s'il y avait des problèmes de performances qui pourraient être à l'origine du problème. Pas de dés ; l'application fonctionnait comme prévu.
J'ai rapidement vérifié les journaux pour voir s'il y avait des informations qui pourraient m'aider à comprendre ce qui se passait. Malheureusement, les journaux n'étaient pas très utiles. Ils ont montré que l'application faisait les requêtes réseau habituelles, mais il n'y avait aucune indication de ce qui causait le problème. Il semblait cependant qu'une erreur se produisait chaque fois que nous essayions de faire une demande POST au point de terminaison des transactions mais uniquement pour cette région spécifique. Il semblait que peu importe ce que j'essayais; Je n'arrivais pas à me rapprocher de la résolution du mystère.
Ensuite, j'ai extrait le dernier code et vérifié la branche de production pour voir si des commits récents pourraient être pertinents pour le problème en cours. J'ai également essayé de faire des demandes individuelles à l'aide de Postman et j'ai remarqué quelque chose de particulier. La requête a renvoyé un code de réponse de 400 , ce qui signifie qu'il s'agissait d'une mauvaise requête ; cela signifie normalement que le client n'envoie pas toutes les informations requises par le backend. Cependant, il n'a pas renvoyé d'erreur significative détaillant les données manquantes dans la demande. Étant donné que cette requête fonctionnait auparavant, il semblait que le problème se situait du côté du serveur.
Pour tester cette théorie, j'ai utilisé un debugger pour approfondir le code. J'ai défini des points d'arrêt à des points clés du code et j'ai essayé d'envoyer à nouveau une transaction, cette fois en prêtant une attention particulière à ce qui se passait sous le capot. J'ai vérifié si la demande contenait toutes les données nécessaires requises par le backend et j'ai même déconnecté la demande et la réponse. Hélas, tout était comme prévu, mais j'obtenais toujours l'erreur Bad request.
L'intrigue se corse
Alors que je poursuivais mon enquête, je n'ai pas pu m'empêcher d'avoir l'impression qu'il me manquait quelque chose. Il semblait qu'il devait y avoir une explication évidente au problème, mais peu importe à quel point j'ai cherché, je ne l'ai pas trouvée. Je pourrais avoir envie de me narguer, moi, mon propre Moriarty, le bogue non résolu.
Juste au moment où je commençais à perdre espoir, j'ai eu une idée. Je me suis souvenu que deux semaines avant le début du problème, l'équipe backend avait publié une mise à jour du code côté serveur de l'application. Se pourrait-il que la mise à jour soit à l'origine du problème ?
J'ai envoyé un ping aux développeurs backend sur Slack pour voir s'ils avaient des idées sur le problème. Ils m'ont dit qu'ils avaient récemment publié une mise à jour du code côté serveur, mais ils ne savaient pas si cela pouvait être lié au problème que je rencontrais. Ils étaient actuellement submergés par la résolution d'un autre problème et ne pouvaient se pencher sur le mien que plus tard. Ils ont mentionné que la mise à jour avait été déployée progressivement, seul un petit pourcentage d'utilisateurs la recevant au début. En raison d'une nouvelle politique, nos déploiements étaient désormais échelonnés et les utilisateurs le recevraient sur une période de deux semaines. Se pourrait-il que la mise à jour ait causé le problème uniquement pour les utilisateurs qui l'ont reçue ?
Le moment de l'ampoule
J'ai rapidement vérifié mes journaux de de Firebase pour voir s'il y avait une corrélation entre le moment de la mise à jour et le moment où les utilisateurs ont commencé à rencontrer le problème. Et bien sûr, j'ai trouvé un indice!
Après quelques allers-retours avec l'équipe, ma théorie s'est confirmée. La mise à jour comprenait une modification de la façon dont le serveur gérait certains types de transactions. Et il s'est avéré que le changement causait des problèmes spécifiquement pour les transactions vers la région affectée. Après une enquête plus approfondie, j'ai découvert que le backend nécessitait désormais un champ supplémentaire à inclure dans les demandes de transaction, un champ qui était auparavant facultatif. Ce changement avait été apporté en raison de nouvelles réglementations dans la région, mais il avait malheureusement été précipité, mal documenté et pas complètement testé. Par conséquent, le champ n'a pas été inclus dans les demandes de transaction pour la région concernée, ce qui a entraîné l'échec des transactions.
Je ne pouvais pas le croire. Après tout mon travail de détective, j'ai enfin trouvé la cause première du bogue. Il avait fallu beaucoup de déductions à la Sherlock et un peu de créativité, mais j'avais finalement résolu le cas de l'argent manquant.
J'ai immédiatement contacté l'équipe backend pour leur faire savoir ce que j'avais découvert. Ils ont été choqués d'apprendre que leur mise à jour avait causé le problème et se sont excusés pour l'oubli. Nous nous sommes mis d'accord sur une solution à deux volets. L'équipe backend publierait un correctif avec une valeur par défaut pour le champ désormais obligatoire, permettant aux utilisateurs d'effectuer des transactions entre-temps tandis que l'équipe de l'application mobile publierait une version mise à jour de notre application Android qui demanderait ces informations supplémentaires.
Conclusion
La résolution de ce bogue a été une expérience stimulante et enrichissante. Cela m'a rappelé l'importance de penser de manière créative et de ne pas avoir peur d'essayer différentes approches lors du débogage d'un problème. Et tout comme le lien fort entre Sherlock et Watson, cela m'a également rappelé le pouvoir de la collaboration et du travail d'équipe - sans l'aide de l'équipe backend, je n'aurais peut-être jamais été en mesure de résoudre ce problème.
J'espère que cette histoire de mon travail de détective servira de rappel aux autres développeurs pour qu'ils soient toujours à l'affût d'indices et qu'ils ne renoncent jamais à résoudre un problème difficile. Comme Sherlock Holmes l'a dit un jour, "Une fois que vous avez éliminé l'impossible, tout ce qui reste, aussi improbable soit-il, doit être la vérité." Dans cet esprit, je sais que n'importe quel bogue peut être conquis, peu importe à quel point cela peut sembler délicat au début.