Ce projet a pour but de répliquer tout ou une partie des données d'une base de données postgreSQL:
- via une sauvegarde / restauration
- d'une manière incrémentale
Des enrichissements peuvent être fait à la fin de l'import.
Les données de pix-editor/lcms sont également répliquées.
A la fin du processus, nous notifions par webhooks des systèmes externes.
Ces étapes se font dans l'ordre et sont executées sequentiellement dans des jobs bull.
Ce projet est prévu pour être déployé sur une application Scalingo associée à une base de donnée PostgreSQL.
Des variables d'environnement sont mises en place afin de garder un seul repository partagé par les applications.
Alimenter les variables d'environnement documentées dans le fichier sample.env
Pour satisfaire les contraintes de déploiement Scalingo, le Procfile déclare un conteneur de type web qui démarre un serveur Web "vide".
Une fois l'application créée et déployée une première fois, il faut :
- mettre à 0 le nombre de conteneurs de type
web - mettre à 1 le nombre de conteneurs de type
background
Connectez-vous à bull
scalingo --region osc-secnum-fr1 --app pix-datawarehouse-production run bull-repl
connect --uri #valeur de REDIS_URL# "Replication queue"
#connect "Incremental replication queue"
#connect "Learning Content replication queue"
failed
statsAlternativement, se connecter à redis
scalingo --region osc-secnum-fr1 --app pix-datawarehouse-production redis-console
KEYS *
GET <KEY>En local,
docker exec -it pix-db-replication-redis-1 redis-cliUne fois que la cause du problème a été corrigée:
- s'il est important que les données soient disponibles le jour même, il est possible de lancer le traitement manuellement
- sinon ne rien faire, le traitement sera exécuté la nuit prochaine
🧨 Le traitement peut avoir des impacts sur les temps de réponses des applications, car il utilise les ressources BDD. Monitorez le % CPU BDD et le temps de réponse des requêtes HTTP pour arrêter le traitement si besoin. Pour cela, stopper le conteneur
background.
Si la sauvegarde/restauration/enrichissement a échoué :
npm run restart:full-replicationSi la réplication incrémentale a échoué :
npm run restart:incremental-replicationSi la réplication de LCMS a échoué :
npm run restart:learning-content-replicationSi la réplication de LCMS Modulix a échoué :
npm run restart:modulix-learning-content-replicationSi les notifications de fin ont échoué :
npm run restart:notificationInstallez le dépôt
git clone git@github.com:1024pix/pix-db-replication.git && cd pix-db-replication
nvm use
npm run preinstallDémarrer le serveur de BDD
docker-compose up --detachCréer et charger les BDD
npm run local:setup-databasesVérifiez que la source et la cible sont accessibles et qu'elles contiennent des données
psql postgres://source_user@localhost/source_database
psql postgres://target_user@localhost/target_databaseCréer un fichier .env à partir du fichier sample.env
Modifier le .env
DATABASE_URL=postgresql://target_user@localhost/target_database
BACKUP_MODE={}
RESTORE_FK_CONSTRAINTS=trueLancer la réplication
node -e "require('./src/steps/backup-restore').run(require ('./src/config/extract-configuration-from-environment')())"Au bout de 5 minutes, vous devez obtenir le message
{"msg":"enrichment.add - Ended","time":"2021-01-08T08:26:13.000Z","v":0}
{"msg":"Import and enrichment done","time":"2021-01-08T08:26:13.000Z","v":0}Pensez à recréer le backup sur le filesystem local, supprimé par la restauration
git checkout data/source.pgsqlSupprimer les FK sortantes des tables à copier
psql postgresql://target_user@localhost/target_databaseALTER TABLE answers DROP CONSTRAINT "answers_assessmentid_foreign";
ALTER TABLE "knowledge-elements" DROP CONSTRAINT "knowledge_elements_answerid_foreign";
ALTER TABLE "knowledge-elements" DROP CONSTRAINT "knowledge_elements_assessmentid_foreign";
ALTER TABLE "knowledge-elements" DROP CONSTRAINT "knowledge_elements_userid_foreign";Modifier le .env
SOURCE_DATABASE_URL=postgresql://source_user@localhost/source_database
TARGET_DATABASE_URL=postgresql://target_user@localhost/target_database
BACKUP_MODE='{"knowledge-elements":"incremental", "knowledge-element-snapshots":"incremental","answers":"incremental"}'
RESTORE_FK_CONSTRAINTS=falseIl est possible de faire tourner l'ordonnanceur en local.
Mettez la planification à toutes les minutes dans le fichier .env
SCHEDULE=* * * * *
Démarrez l'ordonnanceur
node ./src/main.js | ./node_modules/.bin/bunyan
Vérifiez que le traitement se lance
[2021-06-11T14:11:01.944Z] INFO: pix-db-replication/83294 on OCTO-TOPI: Starting job in Learning Content replication queue: 10Vérifiez que bull a pu joindre redis
redis-cli
keys bull:*Connectez-vous au CLI Bull pour suivre l'avancement (bull-repl).
En local :
npx bull-replPour se connecter via Scalingo, utiliser le connect avec les 4 options ci-dessous.
connect [options] <queue>
-h, --host <host> Redis host for connection
-p, --port <port> Redis port for connection
-d, --db <db> Redis db for connection
--password <password> Redis password for connectionPuis saisir le nom de la queue.
Pour la réplication par dump
bull-repl
connect "Replication queue"
statsPour la réplication incrémentale
bull-repl
connect "Incremental replication queue"
statsPour l'import LCMS
bull-repl
connect "Learning Content replication queue"
statsVous obtenez, par exemple
- en cours d'exécution d'un traitement
- après 14 exécutions avec succès
┌───────────┬────────┐
│ (index) │ Values │
├───────────┼────────┤
│ waiting │ 0 │
│ active │ 1 │
│ completed │ 14 │
│ failed │ 0 │
│ delayed │ 0 │
│ paused │ 0 │
└───────────┴────────┘Une partie du code n'est pas testable de manière automatisée.
Il est donc important d'effectuer un test manuel en RA avant de merger une PR, même si la CI passe.
Récupérer les données de LCMS :
node -e "require('./src/steps/learning-content').run(require ('./src/config/extract-configuration-from-environment')())"-
Par défaut :
- la review app réplique les données de la base de données de l'environnement d'intégration
Pix. Vous pouvez changer la source de données en modifiant la variable d'environnement
SOURCE_DATABASE_URL - aucune table n'est configurée en incremental (la base destination étant vide au départ). Après une 1ère réplication
complète, il est possible d'ajouter une configuration incrémentale sur certaines tables en modifiant la variable
d'environnement
BACKUP_MODE(ex :"answers":"incremental"et"knowledge-elements":"incremental")
- la review app réplique les données de la base de données de l'environnement d'intégration
Pix. Vous pouvez changer la source de données en modifiant la variable d'environnement
-
Déterminer le nom de l'application de RA Scalingo de db-replication
NOM_APPLICATION=pix-datawarehouse-pr<NUMERO-PR>- Lancer le process de réplication sur la RA
scalingo run --region osc-fr1 --app $NOM_APPLICATION npm run restart:full-replication- Vérifier le résultat dans la bdd répliquée
scalingo -a $NOM_APPLICATION pgsql-consoleSELECT id, email FROM "users" LIMIT 5;Déroulement :
- une BDD est créée en local sur l'URL
$TEST_POSTGRES_URL(par défaut :postgres://postgres@localhost), instancepix_replication_test - la table
test_tableest créée et chargée avec 100 000 enregistrements (1 colonne, PK) - un export est effectué par
pg_dump --cdans un dossier temporaire - la restauration à tester est appelée depuis
steps.js/restoreBackup - les assertions SQL sont effectuées par un
runSql, un wrapper autour depsql
le dump Scalingo est créé avec des options
pg_dumpdifférentes
- Se connecter à la BDD de test :
psql postgres://postgres@localhost/pix_replication_testLa CI exécute l'intégralité des tests (unitaire et intégration).
Les logs en production sont parsés sur Datadog, et l'ensemble des éléments remontent dans des logs structurés. Il est ainsi possible de filtrer sur les status des logs pour obtenir les informations désirées.
L'analyse de ce qui prend du temps est complexe sur les logs brutes s'il y a :
- plusieurs jobs de restauration (variable d'environnement
PG_RESTORE_JOBS) - beaucoup de tables.
Pour faciliter l'analyse, utilisez le script d'analyse de log.
Étapes :
- récupérer les logs
scalingo --region osc-secnum-fr1 --app <NOM_APPLICATION> logs --lines 100000 > /tmp/logs.txt-
déterminer la date d'exécution au format
YYYY-MM-DDDD, par exemple :2020-10-13 -
exécuter
node utils/parse-replication-logs.js ./logs.txt <DATE_EXECUTION>Exemples de résultat sur pix-datawarehouse-production le 26/01/2025
node utils/parse-replication-logs.js ./logs.txt 2020-10-22# Dans le fichier /tmp/pix-datawarehouse-ex-production-logs.txt
Durée de création du backup: 0h 50min 20s
Durée du drop des tables: 0h 0min 2s
Durée de la création des vues: 0h 0min 0s
Durée de l'enrichissement: 0h 0min 19s
Durée de la mise à jour des authentication-methods: NaNh NaNmin NaNs
Durée du restore: 1h 44min 60s
Durée de l'incrémentale: 0h 2min 30s
Durée du Learning Content: 0h 1min 38s
Durée totale: 2h 39min 49sS'il y a eu :
- plusieurs exécutions le même jour
- une exécution incomplète (pas de message
Start restoreouRestore done)
Alors vous obtiendrez le message suivant TypeError: Cannot read property '0' of null
Afin de pouvoir alimenter une base de données contenant uniquement le schéma de BDD, notamment pour des besoins de Data Catalog,
le script db-schema-exporter.sh peut être utilisé.
En définissant les variables suivantes :
DB_SCHEMA_EXPORTER_ENABLED=true
DB_SCHEMA_EXPORTER_DATABASE_TARGET=postgres://user:password@database:port/dbTous les jours à midi, le schéma de la base actuelle sera dupliqué sur la BDD distante.