TL;DR : Nous avons fait une erreur lors d’une mise à niveau et cherchons de l’aide
Avec Home Assistant, nous utilisons Discourse pour alimenter notre communauté. Nous l’exécutons avec la méthode discourse_docker sur une instance EC2 chez AWS.
En tant que projet open source, la maintenance du forum a été négligée et nous nous sommes retrouvés avec une ancienne version, dernière mise à jour début 2019.
Pour aggraver les choses, lors d’une précédente mise à niveau, nous avions figé Postgres sur la version 9.5 car nous n’avions pas l’espace disque nécessaire pour passer à Postgres 10. Nous n’avons jamais résolu ce problème.
Nous avions également modifié le modèle Cloudflare et l’avions engagé dans le dépôt, ce qui a empêché la branche docker_discourse de se mettre à jour vers la dernière version.
Hier, nous avons décidé de procéder à la mise à niveau…
Lors de la migration de la base de données, nous avons rencontré un problème : une syntaxe utilisée n’était pas compatible avec la version 9.5 :
== 20200429095034 AddTopicThumbnailInformation: migrating =====================
-- execute("ALTER TABLE posts\nADD COLUMN IF NOT EXISTS image_upload_id bigint\n")
Nous avons rapidement réalisé le problème de la version 9.5 figée. Nous avons donc décidé de migrer vers Postgres 10. Cela n’a pas fonctionné et nous avons reçu l’erreur suivante :
I, [2020-06-12T00:30:55.448351 #1] INFO -- : Upgrading PostgreSQL from version 9.5 to 10
WARNING: Upgrading PostgresSQL would require an addtional 89M of disk space
Please free up some space, or expand your disk, before continuing.
Nous avions 47 Go disponibles, ce qui était étrange. Nous avons alors réalisé que discourse_docker était obsolète et l’avons mis à jour vers la dernière version. Surprise, Postgres 12 venait tout juste d’être publié.
Après avoir relancé rebuild, cette fois nous avons obtenu cette erreur :
I, [2020-06-12T00:41:17.378129 #1] INFO -- : Upgrading PostgreSQL from version 9.5 to 12
WARNING: Upgrading PostgresSQL would require an addtional 92G of disk space
Please free up some space, or expand your disk, before continuing.
C’est un peu plus d’espace, mais bon. Augmentons simplement notre espace disque à 300 Go et relançons.
Cette fois, pg_upgrade a échoué pendant la migration :
Restoring database schemas in the new cluster
template1
discourse
*failure* Consult the last few lines of "pg_upgrade_dump_16384.log" for the probable cause of the failure. Failure, exiting
En examinant le fichier pg_upgrade_dump_16384.log, nous avons constaté l’erreur suivante :
pg_restore: creating VIEW "postgres_exporter.pg_stat_activity"
pg_restore: [archiver (db)] Error while PROCESSING TOC:
pg_restore: [archiver (db)] Error from TOC entry 721; 1259 678554 VIEW pg_stat_activity postgres
pg_restore: [archiver (db)] could not execute query: ERROR: column pg_stat_activity.waiting does not exist
LINE 27: "pg_stat_activity"."waiting",
^
Command was:
-- For binary upgrade, must preserve pg_type oid
SELECT pg_catalog.binary_upgrade_set_next_pg_type_oid('678556'::pg_catalog.oid);
-- For binary upgrade, must preserve pg_type array oid
SELECT pg_catalog.binary_upgrade_set_next_array_pg_type_oid('678555'::pg_catalog.oid);
-- For binary upgrade, must preserve pg_class oids
SELECT pg_catalog.binary_upgrade_set_next_heap_pg_class_oid('678554'::pg_catalog.oid);
CREATE VIEW "postgres_exporter"."pg_stat_activity" AS
SELECT "pg_stat_activity"."datid",
"pg_stat_activity"."datname",
"pg_stat_activity"."pid",
"pg_stat_activity"."usesysid",
"pg_stat_activity"."usename",
"pg_stat_activity"."application_name",
"pg_stat_activity"."client_addr",
"pg_stat_activity"."client_hostname",
"pg_stat_activity"."client_port",
"pg_stat_activity"."backend_start",
"pg_stat_activity"."xact_start",
"pg_stat_activity"."query_start",
"pg_stat_activity"."state_change",
"pg_stat_activity"."waiting",
"pg_stat_activity"."state",
"pg_stat_activity"."backend_xid",
"pg_stat_activity"."backend_xmin",
"pg_stat_activity"."query"
FROM "pg_stat_activity";
Oh non.
C’est à ce moment-là que nous avons décidé de faire quelques pas en arrière. Pourrions-nous simplement remettre les forums en ligne et les passer en mode lecture seule pendant que nous réglons ce problème de sauvegarde ? Nous y sommes parvenus en corrigeant certains problèmes de permissions pour postgres et redis, et les forums sont revenus en ligne sur l’ancienne version. Tout ne fonctionne pas, par exemple aller dans admin → utilisateur → groupes nous donne cette erreur :
NoMethodError (undefined method `automatic_membership_retroactive' for #<Group:0x00007fcaca3045e8>)
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activemodel-6.0.1/lib/active_model/attribute_methods.rb:431:in `method_missing'
Mais le reste semble fonctionner.
À ce stade, nous avons décidé que, puisque nous avions dû changer les propriétaires (chown) pour revenir à une instance fonctionnelle, nous devions simplement démarrer une nouvelle instance et importer notre sauvegarde.
Nous avons donc lancé une nouvelle instance EC2, suivi les instructions de démarrage de discourse_docker et lancé notre import. Ensuite, nous avons rencontré un problème étrange : il n’a pas pu créer un index car les données ne correspondaient pas aux exigences d’unicité de l’index :
ERROR: could not create unique index "index_incoming_domains_on_name_and_https_and_port"
DETAIL: Key (name, https, port)=(homeassistant.home, f, 8123) is duplicated.
EXCEPTION: psql failed: DETAIL: Key (name, https, port)=(homeassistant.home, f, 8123) is duplicated.
/var/www/discourse/lib/backup_restore/database_restorer.rb:95:in `restore_dump'
Mais lorsque nous avons accédé à la console Rails de notre instance en cours d’exécution, il n’y avait pas de doublon :
[7] pry(main)> IncomingDomain.where(name: "homeassistant.home")
=> [#<IncomingDomain:0x000055e5cabc3760 id: 8648, name: "homeassistant.home", https: false, port: 8123>]
Voilà où nous en sommes actuellement. Et nous sommes un peu perdus.
- Nous avons une instance en cours d’exécution avec une base de données défectueuse par rapport au code Ruby, incapable de migrer vers des versions plus récentes de Postgres
- Nous avons une sauvegarde qui ne peut pas être importée dans une nouvelle instance
Nous avons exploré la possibilité de passer à un Discourse hébergé payant, mais avec 3 millions de vues de pages et un million de messages, la tarification entreprise représente un engagement trop important pour nous.
Nous devons donc trouver une issue, de préférence en important notre sauvegarde, mais la migration de notre ancienne instance fonctionnerait aussi.
Des idées ? Nous ne sommes pas contre payer quelqu’un pour nous aider.