TL;DR: Abbiamo sbagliato un aggiornamento e cerchiamo aiuto
Con Home Assistant utilizziamo Discourse per gestire la nostra community. Lo gestiamo con il metodo discourse_docker su un’istanza EC2 di AWS.
Essendo un progetto open source, la manutenzione del forum è stata trascurata e ci siamo ritrovati con una versione obsoleta, aggiornata per l’ultima volta all’inizio del 2019.
Per peggiorare le cose, in un precedente aggiornamento avevamo bloccato Postgres alla versione 9.5 perché non disponevamo dello spazio su disco necessario per passare a Postgres 10. Non abbiamo mai risolto quel problema.
Inoltre, avevamo apportato una modifica al template di Cloudflare e l’avevamo committata nel repository; questo ha impedito al ramo docker_discourse di aggiornarsi all’ultima versione.
Ieri abbiamo deciso di procedere con l’aggiornamento…
Durante la migrazione del database, abbiamo riscontrato un problema: veniva utilizzata una sintassi non compatibile con la versione 9.5:
== 20200429095034 AddTopicThumbnailInformation: migrating =====================
-- execute("ALTER TABLE posts\nADD COLUMN IF NOT EXISTS image_upload_id bigint\n")
Abbiamo capito rapidamente il problema legato al blocco su 9.5, quindi abbiamo deciso di migrare a Postgres 10. Non ha funzionato e abbiamo ricevuto questo errore:
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.
Avevamo 47 GB disponibili, quindi era strano. Ci siamo poi resi conto che discourse_docker era obsoleto, quindi l’abbiamo aggiornato all’ultima versione. Sorpresa: Postgres 12 era appena stato rilasciato.
Dopo aver eseguito di nuovo rebuild, questa volta abbiamo ottenuto questo errore:
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.
È un po’ più spazio, ma va bene. Aumentiamo semplicemente lo spazio su disco a 300 GB e riproviamo.
Questa volta pg_upgrade si è interrotto durante la migrazione:
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
Quando abbiamo esaminato il file pg_upgrade_dump_16384.log, abbiamo visto il seguente errore:
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 no.
A questo punto abbiamo deciso di fare un passo indietro. Potremmo semplicemente riportare i forum online e metterli in sola lettura mentre risolviamo la questione del backup? Siamo riusciti a farlo correggendo alcuni problemi di permessi sia per postgres che per redis, e i forum sono tornati online sulla versione vecchia. Non tutto funziona, ad esempio andare su admin → user → groups ci restituisce questo errore:
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'
Ma il resto sembra funzionare.
A questo punto abbiamo deciso che, dato che dovevamo correggere i permessi per tornare a un’istanza funzionante, era meglio avviare una nuova istanza e importare il nostro backup.
Quindi abbiamo avviato una nuova istanza EC2, seguito le istruzioni di avvio per discourse_docker e iniziato l’importazione. Poi ci siamo imbattuti in un problema strano: non è stato possibile creare un indice perché i dati non corrispondevano ai requisiti di unicità dell’indice:
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'
Ma quando siamo entrati nella console rails della nostra istanza in esecuzione, non era un duplicato:
[7] pry(main)> IncomingDomain.where(name: "homeassistant.home")
=> [#<IncomingDomain:0x000055e5cabc3760 id: 8648, name: "homeassistant.home", https: false, port: 8123>]
Quindi è qui che ci troviamo ora. E siamo un po’ persi.
- Abbiamo un’istanza funzionante con un DB errato rispetto al codice Ruby, che non riesce a migrare su versioni più recenti di Postgres
- Abbiamo un backup che non può essere importato in una nuova istanza
Abbiamo esplorato la possibilità di passare a un Discourse ospitato a pagamento, ma dato che abbiamo 3 milioni di visualizzazioni di pagina e un milione di post, i prezzi enterprise sono un impegno troppo grande per noi.
Quindi dobbiamo trovare una soluzione. Preferibilmente potremmo importare il nostro backup, ma anche migrare la nostra vecchia istanza andrebbe bene.
Qualcuno ha idee? Non abbiamo problemi a pagare qualcuno per aiutarci.