{"id":20489765,"url":"https://github.com/1024pix/pix-db-replication","last_synced_at":"2025-06-23T03:40:20.268Z","repository":{"id":38824322,"uuid":"191579459","full_name":"1024pix/pix-db-replication","owner":"1024pix","description":"Brique décisionelle: import des sources de données (BDD, LCMS)","archived":false,"fork":false,"pushed_at":"2025-06-20T12:26:59.000Z","size":1553,"stargazers_count":4,"open_issues_count":5,"forks_count":1,"subscribers_count":19,"default_branch":"dev","last_synced_at":"2025-06-20T13:36:16.014Z","etag":null,"topics":["airtable","database","pix-captains"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/1024pix.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-06-12T13:44:50.000Z","updated_at":"2025-06-20T12:27:02.000Z","dependencies_parsed_at":"2023-02-12T22:16:52.744Z","dependency_job_id":"92ebb4f4-96e7-403c-be05-2554912e3c7b","html_url":"https://github.com/1024pix/pix-db-replication","commit_stats":null,"previous_names":[],"tags_count":88,"template":false,"template_full_name":null,"purl":"pkg:github/1024pix/pix-db-replication","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/1024pix%2Fpix-db-replication","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/1024pix%2Fpix-db-replication/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/1024pix%2Fpix-db-replication/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/1024pix%2Fpix-db-replication/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/1024pix","download_url":"https://codeload.github.com/1024pix/pix-db-replication/tar.gz/refs/heads/dev","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/1024pix%2Fpix-db-replication/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261406773,"owners_count":23153835,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["airtable","database","pix-captains"],"created_at":"2024-11-15T17:14:06.790Z","updated_at":"2025-06-23T03:40:15.246Z","avatar_url":"https://github.com/1024pix.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Réplication des données de production de Pix\n\nCe projet a pour but de répliquer tout ou une partie des données d'une base de données postgreSQL:\n\n- via une sauvegarde / restauration\n- d'une manière incrémentale\n\nDes enrichissements peuvent être fait à la fin de l'import.\n\nLes données de pix-editor/lcms sont également répliquées.\n\nA la fin du processus, nous notifions par webhooks des systèmes externes.\n\nCes étapes se font dans l'ordre et sont executées sequentiellement dans des jobs [bull](https://github.com/OptimalBits/bull).\n\n## Pré-requis\n\nCe projet est prévu pour être déployé sur une application Scalingo associée à une base de donnée PostgreSQL.\n\nDes variables d'environnement sont mises en place afin de garder un seul repository partagé par les applications.\n\n## Utilisation sur Scalingo\n\n### Installation\n\nAlimenter les variables d'environnement documentées dans le fichier [sample.env](sample.env)\n\nPour satisfaire les contraintes de déploiement Scalingo, le [Procfile](Procfile) déclare un conteneur de type `web` qui démarre un serveur Web \"vide\".\n\nUne fois l'application créée et déployée une première fois, il faut :\n- mettre à 0 le nombre de conteneurs de type `web`\n- mettre à 1 le nombre de conteneurs de type `background`\n \n### Résolution de problèmes\n\n#### Analyse de la cause\n\nConnectez-vous à `bull`\n\n```bash\nscalingo --region osc-secnum-fr1 --app pix-datawarehouse-production run bull-repl\nconnect --uri #valeur de REDIS_URL# \"Replication queue\"\n#connect \"Incremental replication queue\"\n#connect \"Learning Content replication queue\"\nfailed\nstats\n```\n\nAlternativement, se connecter à `redis`\n\n```bash\nscalingo --region osc-secnum-fr1 --app pix-datawarehouse-production redis-console\nKEYS *\nGET \u003cKEY\u003e\n```\n\n#### Relance\n\nUne fois que la cause du problème a été corrigée:\n\n- s'il est important que les données soient disponibles le jour même, il est possible de lancer le traitement manuellement\n- sinon ne rien faire, le traitement sera exécuté la nuit prochaine\n\n\u003e 🧨 Le traitement peut avoir des impacts sur les temps de réponses des applications, car il utilise les ressources BDD.\n\u003e 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`.\n\nSi la sauvegarde/restauration/enrichissement a échoué :\n\n``` bash\nnpm run restart:full-replication\n```\n\nSi la réplication incrémentale a échoué :\n\n``` bash\nnpm run restart:incremental-replication\n```\n\nSi la réplication de LCMS a échoué :\n\n``` bash\nnpm run restart:learning-content-replication\n```\n\nSi les notifications de fin ont échoué :\n\n``` bash\nnpm run restart:notification\n```\n\n## Développement et exécution en local\n\n### Installation\n\nInstallez le dépôt\n\n``` bash\ngit clone git@github.com:1024pix/pix-db-replication.git \u0026\u0026 cd pix-db-replication\nnvm use\nnpm run preinstall\n```\n\nDémarrer le serveur de BDD\n\n````bash\ndocker-compose up --detach\n````\n\nCréer et charger les BDD\n\n````bash\nnpm run local:setup-databases\n````\n\nVérifiez que la source et la cible sont accessibles et qu'elles contiennent des données\n\n````bash\npsql postgres://source_user@localhost/source_database\npsql postgres://target_user@localhost/target_database\n````\n\n### Paramétrage\n\nCréer un fichier `.env` à partir du fichier [sample.env](sample.env)\n\n### Exécution\n\n#### Réplication complète\n\nModifier le .env\n\n``` bash\nDATABASE_URL=postgresql://target_user@localhost/target_database\nBACKUP_MODE={}\nRESTORE_FK_CONSTRAINTS=true\n```\n\nLancer la réplication\n\n``` bash\nnode -e \"require('./src/steps/backup-restore').run(require ('./src/config/extract-configuration-from-environment')())\"\n```\n\nAu bout de 5 minutes, vous devez obtenir le message\n\n``` json\n{\"msg\":\"enrichment.add - Ended\",\"time\":\"2021-01-08T08:26:13.000Z\",\"v\":0}\n{\"msg\":\"Import and enrichment done\",\"time\":\"2021-01-08T08:26:13.000Z\",\"v\":0}\n```\n\nPensez à recréer le backup sur le filesystem local, supprimé par la restauration\n\n``` bash\ngit checkout data/source.pgsql\n```\n\n#### Réplication incrémentale\n\n##### Initialiser l'environnement\n\nSupprimer les FK sortantes des tables à copier\n\n``` bash\npsql postgresql://target_user@localhost/target_database\n```\n\n```sql\nALTER TABLE answers DROP CONSTRAINT \"answers_assessmentid_foreign\";\nALTER TABLE \"knowledge-elements\" DROP CONSTRAINT \"knowledge_elements_answerid_foreign\";\nALTER TABLE \"knowledge-elements\" DROP CONSTRAINT \"knowledge_elements_assessmentid_foreign\";\nALTER TABLE \"knowledge-elements\" DROP CONSTRAINT \"knowledge_elements_userid_foreign\";\n```\n\n##### Paramétrer\n\nModifier le .env\n\n``` bash\nSOURCE_DATABASE_URL=postgresql://source_user@localhost/source_database\nTARGET_DATABASE_URL=postgresql://target_user@localhost/target_database\nBACKUP_MODE='{\"knowledge-elements\":\"incremental\", \"knowledge-element-snapshots\":\"incremental\",\"answers\":\"incremental\"}'\nRESTORE_FK_CONSTRAINTS=false\n```\n\n#### Ordonnanceur\n\nIl est possible de faire tourner l'ordonnanceur en local.\n\nMettez la planification à toutes les minutes dans le fichier `.env`\n\n`SCHEDULE=* * * * *`\n\nDémarrez l'ordonnanceur\n\n`node ./src/main.js | ./node_modules/.bin/bunyan`\n\nVérifiez que le traitement se lance\n\n```bash\n[2021-06-11T14:11:01.944Z]  INFO: pix-db-replication/83294 on OCTO-TOPI: Starting job in Learning Content replication queue: 10\n```\n\nVérifiez que bull a pu joindre redis\n\n```bash\nredis-cli\nkeys bull:*\n```\n\nConnectez-vous au CLI Bull pour suivre l'avancement.\n\nPour se connecter via Scalingo, utiliser le connect avec les 4 options ci-dessous.\n\n``` bash\nconnect [options] \u003cqueue\u003e\n    -h, --host \u003chost\u003e      Redis host for connection\n    -p, --port \u003cport\u003e      Redis port for connection\n    -d, --db \u003cdb\u003e          Redis db for connection\n    --password \u003cpassword\u003e  Redis password for connection\n```\n\nPuis saisir le nom de la queue.\n\nPour la réplication par dump\n\n```bash\nbull-repl\nconnect \"Replication queue\"\nstats\n```\n\nPour la réplication incrémentale\n\n```bash\nbull-repl\nconnect \"Incremental replication queue\"\nstats\n```\n\nPour l'import LCMS\n\n```bash\nbull-repl\nconnect \"Learning Content replication queue\"\nstats\n```\n\nVous obtenez, par exemple\n- en cours d'exécution d'un traitement\n- après 14 exécutions avec succès\n\n```bash\n┌───────────┬────────┐\n│  (index)  │ Values │\n├───────────┼────────┤\n│  waiting  │   0    │\n│  active   │   1    │\n│ completed │   14   │\n│  failed   │   0    │\n│  delayed  │   0    │\n│  paused   │   0    │\n└───────────┴────────┘\n```\n\n\n## Tests\n\nUne partie du code n'est pas testable de manière automatisée.\n\nIl est donc important d'effectuer un test manuel en RA avant de merger une PR, même si la CI passe.\n\n### Manuels\n\n#### Local\n\nRécupérer les données de LCMS :\n\n``` bash\nnode -e \"require('./src/steps/learning-content').run(require ('./src/config/extract-configuration-from-environment')())\"\n```\n\n#### RA Scalingo\n\n- Faire un backup des données d'une application Scalingo hors `osc-secnum-fr1`\npour éviter les considérations de sécurité des données\n\n- Vérifier les données présentes dans la BDD à exporter (exemple pour les données d'une review app)\n\n``` bash\nscalingo -a pix-api-review-prxxx pgsql-console\n```\n\n- Lancer un backup (ou ne rien faire, le dernier est utilisé par défaut)\n\n- Déterminer le nom de l'application de RA Scalingo de db-replication\n\n``` bash\nNOM_APPLICATION=pix-datawarehouse-pr\u003cNUMERO-PR\u003e\n```\n\n- Lancer le process de création et d'import du backup sur cette RA\n\n``` bash\nscalingo run --region osc-fr1 --app $NOM_APPLICATION npm run restart:full-replication\n```\n\n- Vérifier le résultat dans la bdd répliquée\n\n``` bash\nscalingo -a $NOM_APPLICATION pgsql-console\n```\n\n```sql\nSELECT id, email FROM \"users\" LIMIT 5;\n```\n\n### Automatisés\n\n#### Local\n\n##### Intégration\n\nDéroulement :\n\n- une BDD est créée en local sur l'URL `$TEST_POSTGRES_URL` (par défaut : `postgres://postgres@localhost`), instance `pix_replication_test`\n- la table `test_table` est créée et chargée avec 100 000 enregistrements (1 colonne, PK)\n- un export est effectué par `pg_dump --c` dans un dossier temporaire\n- la restauration à tester est appelée depuis `steps.js/restoreBackup`\n- les assertions SQL sont effectuées par un `runSql`, un wrapper autour de `psql`\n\n\u003e le dump Scalingo est créé avec des options `pg_dump` [différentes](https://doc.scalingo.com/databases/postgresql/dump-restore)\n\n- Se connecter à la BDD de test :\n\n``` bash\npsql postgres://postgres@localhost/pix_replication_test\n```\n\n#### CI\n\nLa CI exécute l'intégralité des tests (unitaire et intégration).\n\n## Parser les logs\n\n### Datadog\n\nLes logs en production sont parsés sur Datadog, et l'ensemble des éléments remontent dans des logs structurés.\nIl est ainsi possible de filtrer sur les status des logs pour obtenir les informations désirées.\n\n### A la main\n\nL'analyse de ce qui prend du temps est complexe sur les logs brutes s'il y a :\n\n- plusieurs jobs de restauration (variable d'environnement`PG_RESTORE_JOBS`)\n- beaucoup de tables.\n\nPour faciliter l'analyse, utilisez le script d'analyse de log.\n\nÉtapes :\n\n- récupérer les logs\n\n```bash\nscalingo --region osc-secnum-fr1 --app \u003cNOM_APPLICATION\u003e logs --lines 100000 \u003e /tmp/logs.txt\n```\n\n- déterminer la date d'exécution au format `YYYY-MM-DDDD`, par exemple : `2020-10-13`\n\n- exécuter\n\n```bash\nnode utils/parse-replication-logs.js ./logs.txt \u003cDATE_EXECUTION\u003e\n```\n\nExemples de résultat sur `pix-datawarehouse-production` le 26/01/2025\n\n```bash\nnode utils/parse-replication-logs.js ./logs.txt 2020-10-22\n```\n\n```1 ↵\n# Dans le fichier /tmp/pix-datawarehouse-ex-production-logs.txt\nDurée de création du backup: 0h 50min 20s\nDurée du drop des tables: 0h 0min 2s\nDurée de la création des vues: 0h 0min 0s\nDurée de l'enrichissement: 0h 0min 19s\nDurée de la mise à jour des authentication-methods: NaNh NaNmin NaNs\nDurée du restore: 1h 44min 60s\nDurée de l'incrémentale: 0h 2min 30s\nDurée du Learning Content: 0h 1min 38s\nDurée totale: 2h 39min 49s\n```\n\nS'il y a eu :\n\n- plusieurs exécutions le même jour\n- une exécution incomplète (pas de message `Start restore` ou `Restore done`)\n\nAlors vous obtiendrez le message suivant `TypeError: Cannot read property '0' of null`\n\n## Duplication des schémas uniquement\n\nAfin de pouvoir alimenter une base de données contenant uniquement le schéma de BDD, notamment pour des besoins de Data Catalog,\nle script `db-schema-exporter.sh` peut être utilisé.\n\nEn définissant les variables suivantes :\n\n```bash\nDB_SCHEMA_EXPORTER_ENABLED=true\nDB_SCHEMA_EXPORTER_DATABASE_TARGET=postgres://user:password@database:port/db\n```\n\nTous les jours à midi, le schéma de la base actuelle sera dupliqué sur la BDD distante.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F1024pix%2Fpix-db-replication","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F1024pix%2Fpix-db-replication","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F1024pix%2Fpix-db-replication/lists"}