Skip to main content

En novembre 2020, a ouvert un nouvel emplacement en Belgique pour son service Realtime Database RTDB. Vous pouvez en lire plus ici.

Les bêtas sur firebase sont généralement vouées à rester et à passer en état stable. Ça peut faire un peu peur car ils stipulent bien que « Use of multiple Realtime Database instances in different locations is a beta feature. This means that the functionality might change in backward-incompatible ways. A beta release is not subject to any SLA or deprecation policy ».

Bon, on y va.

Step 1 : Réfléchir

On utilise 3 produits Firebase :

  • Auth
  • RTDB Database
  • Functions

Notre idée est de ne pas changer le projet firebase, juste l’emplacement de RTDB, donc ça résout le souci de Auth, vu que c’est lié au projet.

La migration de RTDB nécessite plusieurs choses :

  • Changer la configuration de notre appli React et du SSR
  • Changer la configuration des Hooks RTDB et des endpoints HTTPS

Nous avons décidé de ne pas migrer l’emplacement de nos Cloud Functions car cela change l’URL. On a des liens hard codés dans nos emails donc on ne voulait pas avoir à les changer, mais il fallait quand même qu’on redéploie les fonctions pour qu’elles pointent sur le nouvel emplacement RTDB.

Ben change juste la base de données par défaut ?

Ben non. Impossible de trouver l’option dans firebase. Apparemment la base par défaut est celle qui porte le nom de votre projet. Il nous faudra spécifier la localisation dans tous nos Hooks RTDB.

via GIPHY

Bah du coup, il n’y a qu’à restaurer la base dans une nouvelle base?

Ben apparemment non ! Notre base de données fait plus d’1Gb et Firebase ne peut pas prendre des imports de plus de 256Mb via leur API REST. Par contre, ils spécifient que « If you are having trouble restoring a backup from a very large database, please reach out to our support team. », ici. Merci Firebase!

via GIPHY

Step 2 : Planifier et tester

Migrer RTDB

Pour éviter un délai trop long et des allers/retours avec l’équipe de support de Firebase, on a décidé d’utiliser leur API REST pour télécharger notre base et la restaurer dans le nouvel emplacement à la mano. On a utilisé l’API REST car les quotas sont plus gros que sur le SDK pour une quelconque raison.

Pour simplifier cette étape, on a utilisé les legacy tokens en authentification.

Du coup on a écrit un script node.js pour récupérer la structure de notre RTDB, avec le shallow flag. (Je peux monter le code mais il n’est pas vraiment open source ready)

Après ça, on a récupéré les nœuds un par un. Firebase répond avec une erreur HTTP 413 quand vous essayez de télécharger un noeud trop gros. Du coup on a géré ce cas-là et on a récupéré les nœuds fils et hop là, nos données étaient prêtes à être restaurées.

La restauration a nécessité un peu de doigté. On a vu que certains nœuds au-dessus de 80MB (pour 250MB max) avaient parfois du mal à être digérés par firebase donc on a du chunker les données en nœuds de 25MB.

Firebase a eu du mal à manger certains de nos nœuds du coup on devait prévoir de les migrer à la main parce qu’ils étaient mal conçus et apparemment trop complexes pour Firebase.

Aussi, les tableaux Firebase c’est toujours aussi nul. Si vous faites un trou dans le tableau, firebase ne le reconstruit pas et ne l’importera pas.

Avec toutes ces considérations, on avait réglé le cas de RTDB

Migrer les  Cloud Functions

Il y a plusieurs petites choses à prendre en compte quand on migre des Cloud Functions

Migrer les hooks firebase sur une nouvelle instance

Firebase RTDB est une base de données réactive, c’est-à-dire que vous pouvez déclencher des fonctions sur un changement de données.

Malheureusement, ils utilisent la base de données par défaut donc il a fallu migrer tous nos hooks

On a dû remplacer tous nos appels

avec


Pour bien gérer la prochaine fois, on a stocké ça dans une variable globale. Ca facilite aussi la configuration en fonction de l’environnement.

Du coup on a pu importer ça comme ça dans nos hooks.

Quelques « replaces » ici et là, et c’était réglé.

Utiliser la bonne instance RTDB dans vos fonctions

Une fois que vous appelez Firebase.initializeApp avec la bonne configuration pour databaseURL, tous les appels RTDB seront faits à la bonne base, donc pas grand chose à faire là.

Test the deploy

On a plus de 250 fonctions.

Si vous avez fait un peu de Firebase, vous avez dû tomber sur l’erreur : « You have exceeded your deployment quota, please deploy your functions in batches by using the –only flag, and wait a few minutes before deploying again. Go to https://firebase.google.com/docs/cli/#deploy_specific_functions to learn more ».

Le rate limiting des déploiements Cloud Functions est rapidement dépassé, vu que c’est 80 appels WRITE par minute.

Pour outrepasser ça, on a découpé nos commandes de deploy en petites parties, avec le flag –only.

C’est un problème commun avec firebase, mais une petite piqûre de rappel ne fait pas de mal.

Step 3 : Migrer!

Avec Vincent qui vit à la Réunion, on a décidé que je devais me lever tôt pour qu’on soit synchronisés pour faire ça à 7h le Mercredi.

Notre plan était de :

  • Mettre la webapp en mode travaux (1 min)
  • Supprimer des nœuds inutiles pour alléger notre export(1 min)
  • Backuper la RTDB (5 min)
  • Faire tourner le script de migration (5 mins)
  • Exporter les quelques nœuds que Firebase ne voulait pas importer via le script(5 mins)
  • Importer ces quelques nœuds à la main dans la nouvelle instance (5 min)
  • Déployer les nouvelles fonctions par parties (à peu près 7 min par partie, on pouvait les lancer en parallèle quand le rate limiting était remis à zéro)
  • Redéployer la webapp avec les nouvelles variables d’environnement (15-20 min)

On avait prévu une fenêtre de tir d’une heure.

Ça s’est bien passé !

Step 4 : Nettoyer

C’est la partie un peu douloureuse. On voulait supprimer l’ancienne base pour éviter la confusion.

En théorie on peu juste lancer ça.

Un article de blog décrit comment cette commande marche mais en gros, elle récupère les nœuds en shallow pour récupérer la structure et détecte toute seule les gros nœuds et les supprime par partie de manière efficace.

En réalité, le découpage en partie peut prendre plus de temps pour les nœuds moyens.

Il y a quelques subtilités à propos de ça mais si vous avez des nœuds moyens de taille moyenne que Firebase supprimerait par partie, lancez cette commande avec le flag –debug, identifiez quels nœuds moyens prennent du temps à supprimer et supprimez les manuellement avec un appel REST ou un via le SDK avec ref().set(null).

Nous n’avons pas essayé d’augmenter le paramètre defaultWriteSizeLimit de la base RTDB. Je pense que ça aurait pu nous aider à supprimer la donnée par plus gros bouts.

Réflexions et conclusion

Nous avions un peu peur de tout devoir faire à la main et de migrer sur un produit en beta. Cependant, nous estimons qu’avoir les données plus près de nos serveurs clever-cloud et de nos utilisateurs ne pourra être que bénéfique pour la plateforme.

On était aussi déçus de voir le manque d’outils de migration intégrés à Firebase, surtout la migration de données d’une instance à une autre et le changement d’une base de données par défaut. Ça nous aurait fait gagner énormément de temps.

Merci d’avoir pris le temps de me lire et on espère que notre serveur qui tourne aux frites vous plaira autant que celui de l’oncle Sam !

 

WeLoveDevs.com

Équipe, stack, locaux…
Découvrez pourquoi les développeurs
aiment WeLoveDevs.com sur leur page entreprise.

Découvrir la page de WeLoveDevs.com
Clément Devos

Auteur Clément Devos

Plus d'articles de Clément Devos

Laisser un commentaire