Errore di aggiornamento - rake db:migrate index on theme_field_id

Nelle ultime note di rilascio (3.2.0.beta1), ho notato il plugin discourse-ai che non avevo mai visto prima, quindi ho tentato di aggiungere questo plugin e aggiornare la mia istanza di discourse contemporaneamente.

Come menzionato nel titolo, sto attualmente riscontrando un errore nel bootstrap in cui rake db:migrate non riesce a creare un indice univoco su theme_field_id. Ecco alcuni dettagli su come sono arrivato a questo punto, però…

Primo tentativo di aggiornamento (errore patch-package)

Sto eseguendo un’installazione con container separati, quindi:

  • Ho modificato il mio web_only.yml per aggiungere il nuovo plugin discourse-ai

    es. Aggiunta di una riga extra agli hook dei plugin
    ## I plugin vanno qui
    ## vedi https://meta.discourse.org/t/19157 per i dettagli
    hooks:
      after_code:
        - exec:
            cd: $home/plugins
            cmd:
              - sudo -E -u discourse git clone https://github.com/discourse/docker_manager.git
              - sudo -E -u discourse git clone https://github.com/discourse/discourse-voting.git
              - sudo -E -u discourse git clone https://github.com/discourse/discourse-ai.git
    
  • Ho eseguito ./launcher bootstrap web_only

Si è verificato un errore con un messaggio relativo a patch-package non trovato.

Git Pull → bootstrap (errore pg-vector)

Ho pensato di assicurarmi di avere gli ultimi aggiornamenti del launcher, dato che non avrebbe fatto male prima di riprovare:

  • Ho eseguito un git pull per assicurarmi di avere gli ultimi aggiornamenti relativi al launcher
  • Ho eseguito nuovamente ./launcher bootstrap web_only

Questa volta ho ricevuto messaggi di errore relativi a pg-vector.

:page_facing_up: Frammento di log dal bootstrap con discourse-ai

Ho annotato le mie versioni di PostgreSQL in modo da averle per i miei archivi quando deciderò di rivisitare il plugin discourse-ai.

  • web_only:
    • client: psql (PostgreSQL) 13.10 (Debian 13.10-1.pgdg110+1)
  • data:
    • server: PostgreSQL 13.9 (Debian 13.9-1.pgdg110+1)

Rimozione del plugin discourse-ai → Bootstrap

E poi ho rimosso il plugin discourse-ai dal file web_only.yml ed ho eseguito nuovamente un bootstrap.

Con mia grande sorpresa, stavo ancora riscontrando errori, ma questa volta sembrano essere correlati a rake db:migrate che non è in grado di creare un indice univoco index_javascript_caches_on_theme_field_id con il dettaglio: Key (theme_field_id)=(3) is duplicated.

:page_facing_up: Frammento di log dal bootstrap senza discourse-ai

Il vostro aiuto? :folded_hands:

Questo mi porta qui a cercare aiuto. Ho pensato che fosse meglio fare una pausa e ottenere alcuni spunti dalla community prima di approfondire ulteriormente, nel caso in cui qualcun altro abbia già riscontrato questo problema.

Come riferimento, ho installato la versione 3.2.0.beta1-dev (993ed10cf0 ~ 9 agosto).

E anche se non penso che sia correlato a questo, immagino che non faccia male menzionare che ho migrato tra host all’inizio di quest’anno… anche se da allora ho effettuato diversi aggiornamenti di Discourse tramite l’interfaccia di amministrazione.

Approccio alla migrazione

A memoria, questo è stato fondamentalmente l’aggiornamento dell’istanza sorgente alla versione più recente di Discourse, l’installazione di Discourse sul nuovo host, il congelamento della sorgente, un backup di Discourse sulla sorgente, il trasferimento di immagini/ecc. tra gli host tramite rsync, il ripristino del backup sul nuovo host.

Per gli errori di indice duplicato, penso che se riesci a riavviare web_only e gestirli dall’interfaccia utente sia molto più semplice che farlo nel database. Anche se non ne ho mai visto uno su theme_field_id prima.

La riga appena sopra rake aborted! nei log menziona che discourse-voting ora è discourse-topic-voting. Potresti provare ad aggiornare il link nella sezione dei plugin a quello corrente e vedere se questo aiuta?

Puoi chiarire a quale risorsa si riferisce come avente un ID duplicato? Non ero sicuro a cosa si riferisse esattamente theme_field_id.

A verbale, non avevo spento il container web_only. Di solito avvio prima il container per ridurre al minimo la finestra di interruzione:

Ci proverò. Sospetto che non aiuterà poiché penserei che GitHub stia reindirizzando le cose silenziosamente dietro le quinte e sia solo un avviso dal lato Discourse. :slight_smile:

Se hai un sito funzionante con l’esploratore di temi installato, penso che dovresti essere in grado di dare un’occhiata a cosa potrebbe riferirsi utilizzando questa query:

SELECT *
FROM theme_fields
WHERE id = 3
1 Mi Piace

Non ero a conoscenza di quel plugin, è fantastico! Non ce l’ho installato, ma sono in grado di accedere al contenitore dei dati ed eseguire query.

Questo è un ottimo indizio! Se ho letto correttamente il messaggio di errore, non credo che riguardi la tabella theme_fields, poiché quella particolare tabella non ha un theme_field_id. Non ho controllato il codice sorgente, ma mi azzarderei a indovinare che il primo argomento di add_index() sia il nome della tabella e il secondo la colonna.

Sulla base di ciò, sembra che si tratti della tabella javascript_caches.

== 20230817174049 EnsureJavascriptCacheIsUniquePerTheme: migrating ===========
-- remove_index(:javascript_caches, :theme_id)
   -> 0.0208s
-- add_index(:javascript_caches, :theme_id, {:unique=>true})
   -> 0.0079s
-- remove_index(:javascript_caches, :theme_field_id)
   -> 0.0026s
-- add_index(:javascript_caches, :theme_field_id, {:unique=>true})

Quindi ho controllato la struttura di quella tabella e ha la colonna theme_field_id:

discourse=# \d javascript_caches
                                          Table "public.javascript_caches"
     Column     |            Type             | Collation | Nullable |                    Default
----------------+-----------------------------+-----------+----------+-----------------------------------------------
 id             | bigint                      |           | not null | nextval('javascript_caches_id_seq'::regclass)
 theme_field_id | bigint                      |           |          |
 digest         | character varying           |           |          |
 content        | text                        |           | not null |
 created_at     | timestamp without time zone |           | not null |
 updated_at     | timestamp without time zone |           | not null |
 theme_id       | bigint                      |           |          |
 source_map     | text                        |           |          |
Indexes:
    "javascript_caches_pkey" PRIMARY KEY, btree (id)
    "index_javascript_caches_on_digest" btree (digest)
    "index_javascript_caches_on_theme_field_id" btree (theme_field_id)
    "index_javascript_caches_on_theme_id" btree (theme_id)
Check constraints:
    "enforce_theme_or_theme_field" CHECK (theme_id IS NOT NULL AND theme_field_id IS NULL OR theme_id IS NULL AND theme_field_id IS NOT NULL)
Foreign-key constraints:
    "fk_rails_58f94aecc4" FOREIGN KEY (theme_id) REFERENCES themes(id) ON DELETE CASCADE
    "fk_rails_ed33506dbd" FOREIGN KEY (theme_field_id) REFERENCES theme_fields(id) ON DELETE CASCADE

Sono stato in grado di interrogare quella tabella (con i campi di contenuto abbreviati in modo da poterli leggere effettivamente) e posso vedere i duplicati. Ma non sono sicuro quale sia l’implicazione di questi duplicati.

discourse=# select id, theme_field_id, digest, substring(content from 1 for 64) as content_64, created_at, updated_at, theme_id, substring(source_map from 1 for 64) as source_64 from javascript_caches where theme_field_id = 3;
 id | theme_field_id |                  digest                  |                            content_64                            |         created_at         |         updated_at         | theme_id |                            source_64
----+----------------+------------------------------------------+------------------------------------------------------------------+----------------------------+----------------------------+----------+------------------------------------------------------------------
  1 |              3 | d0b6ec642d5649064ff0501cadc775a9217b16e0 | "define"in window&&define("discourse/theme-3/initializers/theme- | 2019-02-25 01:26:56.606537 | 2023-08-18 20:47:19.596923 |          | {"version":3,"sources":["discourse/initializers/theme-field-3-co
  2 |              3 | 7fd74ecf4448afccdbcd9ccde87acddb4ec6f514 | "define"in window&&define("discourse/theme-3/initializers/theme- | 2019-02-25 01:26:58.228209 | 2023-08-18 20:50:41.049209 |          | {"version":3,"sources":["discourse/initializers/theme-field-3-co

Il contenuto sembrava familiare, quindi sono andato su Customize → Theme → My Theme → Common → Head, ho apportato una piccola modifica e ho salvato e posso vedere che una delle voci è stata aggiornata e una è rimasta vecchia…

discourse=# select id, theme_field_id, digest, substring(content from 1 for 64) as content_64, created_at, updated_at, theme_id, substring(source_map from 1 for 64) as source_64 from javascript_caches where theme_field_id = 3;
 id | theme_field_id |                  digest                  |                            content_64                            |         created_at         |         updated_at         | theme_id |                            source_64
----+----------------+------------------------------------------+------------------------------------------------------------------+----------------------------+----------------------------+----------+------------------------------------------------------------------
  2 |              3 | 7fd74ecf4448afccdbcd9ccde87acddb4ec6f514 | "define"in window&&define("discourse/theme-3/initializers/theme- | 2019-02-25 01:26:58.228209 | 2023-08-18 20:50:41.049209 |          | {"version":3,"sources":["discourse/initializers/theme-field-3-co
  1 |              3 | 7f4132b1f9ced1b90b8f8fc24812cc11e81fea8d | "define"in window&&define("discourse/theme-3/initializers/theme- | 2019-02-25 01:26:56.606537 | 2023-09-13 21:56:56.312263 |          | {"version":3,"sources":["discourse/initializers/theme-field-3-co
(2 rows)

Di nuovo, non sono sicuro quale sia l’implicazione di questi duplicati, se sia sicuro eliminare quello “vecchio”, o se ci sia qualche altro modo per “ricostruire” le cache che potrebbe risolvere questo problema?

Ad essere onesti, finora sono 0/2, quindi probabilmente non sono la fonte migliore di informazioni per questo. :slight_smile:

Ci sono un paio di argomenti precedenti in cui è successa una cosa simile per index_tags_on_name, se potessero essere utili? ad es.

1 Mi Piace

Ricostruisci il tuo contenitore dati. Il plugin ai richiede un’estensione che non hai ancora.

Apprezzo il tuo aiuto! Sembra che mi hai guidato nella giusta direzione. :star_struck:

Ho eseguito un backup della tabella con pg_dump, ho eliminato la vecchia voce duplicata e il bootstrap è stato completato con successo. :+1:

Grazie per la conferma! Pensavo che avrei dovuto aggiornare il container dati (o in altro modo installare pgvector). Stavo rimandando perché non volevo affrontare il downtime.

Dal thread di discourse-ai, sembra che PG15 sia all’orizzonte, quindi potrei aspettare un po’ per quello.

Sembra che la dipendenza da pgvector possa essere per la funzionalità Embeddings che non avevo intenzione di utilizzare, ma sfortunatamente sembra che sia tutto raggruppato. Principalmente volevo solo giocare con alcune delle funzionalità di riscrittura magica di OpenAI / ChatGPT, quindi forse un altro motivo per aspettare il prossimo grande aggiornamento del container dati. :slight_smile:

1 Mi Piace

Puoi aspettare se vuoi, ma le persone che usano un singolo container (che è la stragrande maggioranza degli self-hoster) aggiornano il loro postgres potenzialmente ogni volta che fanno un aggiornamento, quindi non c’è molto motivo di aspettare se non qualche minuto in più di downtime. Dovrai ricostruire (o forse solo distruggere e avviare) il container web_only dopo la ricostruzione del database.

1 Mi Piace

Questa è la ragione principale. Anche se si tratta solo di pochi minuti, preferirei minimizzarlo se non è critico.

A tal proposito, probabilmente dovrei evitare di usare un plugin beta per il potenziale tempo di inattività. :stuck_out_tongue:

Ho seguito superficialmente alcune delle discussioni sui riavvii “senza tempi di inattività”. Forse sono solo occhiali color rosa che guardano al passato recente, ma mi sembra di essere riuscito a usare /admin/upgrade per la maggior parte degli aggiornamenti nell’ultimo anno, quindi mi sono concentrato su progetti più critici per il momento e ho perso interesse nell’approccio “senza tempi di inattività”.

Quando sono migrato a un host più grande a gennaio, è stato “senza tempi di inattività” nel senso che gli utenti potevano continuare ad accedere ai contenuti del sito, ma c’è stato un breve periodo in cui le cose erano in sola lettura mentre passavamo. Suppongo che potrei usare quell’approccio per un importante aggiornamento del contenitore data se volessi davvero minimizzare i tempi di inattività durante il prossimo grande aggiornamento di data.

PS. Ho letto un sacco dei tuoi post nella community qui nel corso degli anni. Grazie per tutti i tuoi sforzi nel supportare la community! :star2:

Davvero! Non faccio un aggiornamento per i miei clienti “ricostruisci quando ne hai bisogno” da un po’ di tempo. Per siti come il tuo, la mia dashboard eseguirà la ricostruzione ed eseguirà le migrazioni post-aggiornamento dopo il lancio del nuovo container (se il tuo container esistente ha quelle migrazioni impostate per non essere eseguite la prima volta).

1 Mi Piace