Error de actualización - rake db:migrate índice en theme_field_id

En las últimas notas de la versión (3.2.0.beta1), noté el plugin discourse-ai que no había visto antes, así que intenté agregar este plugin y actualizar mi instancia de Discourse al mismo tiempo.

Como se menciona en el título, actualmente estoy viendo un error en el arranque donde rake db:migrate no puede crear un índice único en theme_field_id. Aquí hay algunos detalles sobre cómo llegué a ese punto…

Intento de actualización inicial (error de patch-package)

Estoy ejecutando una instalación de contenedor dividida, así que:

  • Edité mi web_only.yml para agregar el nuevo plugin discourse-ai

    por ejemplo, Añadí una línea extra a los hooks de plugins
    ## Los plugins van aquí
    ## ver https://meta.discourse.org/t/19157 para detalles
    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
    
  • Ejecuté ./launcher bootstrap web_only

    Falló con un mensaje sobre que patch-package no se encontraba.

Git Pull → bootstrap (error de pg-vector)

Pensé que me aseguraría de tener las últimas actualizaciones del lanzador, ya que no haría daño antes de volver a intentarlo:

  • Ejecuté un git pull para asegurarme de tener las últimas actualizaciones relacionadas con el lanzador
  • Ejecuté ./launcher bootstrap web_only de nuevo

Esta vez recibí mensajes de error relacionados con pg-vector.

:page_facing_up: Fragmento de registro del arranque con discourse-ai

Anoté mis versiones de PostgreSQL para tenerlas para mis registros cuando decidiera volver a visitar el plugin discourse-ai.

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

Eliminar el plugin discourse-ai → Bootstrap

Y luego eliminé el plugin discourse-ai del archivo web_only.yml y volví a ejecutar un arranque.

Sorprendentemente, todavía estaba viendo errores, pero esta vez parecen estar relacionados con que rake db:migrate no puede crear un índice único index_javascript_caches_on_theme_field_id con el detalle: Key (theme_field_id)=(3) is duplicated.

:page_facing_up: Fragmento de registro del arranque sin discourse-ai

¿Tu ayuda? :folded_hands:

Eso me trae aquí buscando ayuda. Pensé que debería hacer una pausa y obtener algunas ideas de la comunidad antes de profundizar más, en caso de que alguien más haya visto esto antes.

Como referencia, tengo instalado 3.2.0.beta1-dev (993ed10cf0 ~ 9 de agosto).

Y aunque no creo que esté relacionado con esto, creo que no hace daño mencionar que migré entre máquinas host a principios de este año… aunque he realizado varias actualizaciones de Discourse a través de la interfaz de administración desde entonces.

Enfoque de migración

Según recuerdo, esto fue básicamente actualizar la instancia de origen a la última versión de Discourse, instalar Discourse en el nuevo host, congelar el origen, hacer una copia de seguridad de Discourse en el origen, rsync imágenes/etc entre hosts, restaurar la copia de seguridad en el nuevo host.

Para los errores de índice duplicado, creo que si puedes reiniciar web_only y tratarlos desde la UI es mucho más simple que hacerlo en la base de datos. Aunque no creo haber visto uno en theme_field_id antes.

La línea justo encima de rake aborted! en los registros menciona que discourse-voting ahora es discourse-topic-voting. ¿Podrías intentar actualizar el enlace en la sección de plugins al actual y ver si eso ayuda?

¿Puedes aclarar a qué recurso se refiere como que tiene un ID duplicado? No estaba seguro de a qué se refiere exactamente theme_field_id.

Para que conste, no había apagado el contenedor web_only. Normalmente arranco el contenedor primero para minimizar la ventana de inactividad:

Lo intentaré. Sospecho que no ayudará, ya que pensaría que GitHub está redirigiendo las cosas silenciosamente detrás de escena y es solo una advertencia del lado de Discourse. :slight_smile:

Si tienes un sitio en funcionamiento con el explorador de temas instalado, creo que deberías poder ver a qué puede referirse usando esta consulta:

SELECT *
FROM theme_fields
WHERE id = 3
1 me gusta

No estaba al tanto de ese plugin, ¡es genial! No lo tengo instalado, pero puedo ingresar al contenedor de datos y ejecutar consultas.

¡Esa es una gran pista! Sin embargo, si estoy leyendo correctamente el mensaje de error, no creo que sea en la tabla theme_fields, ya que esa tabla en particular no tiene un theme_field_id. No he revisado el código fuente, pero me atrevería a suponer que el primer argumento de add_index() es el nombre de la tabla y el segundo es la columna.

Basado en eso, parece que sería la tabla 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})

Así que revisé la estructura de esa tabla y tiene la columna 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

Pude consultar esa tabla (con los campos de contenido acortados para poder leerlos) y veo los duplicados. Pero no estoy seguro de cuáles son las implicaciones de estos duplicados.

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

El contenido me resultó familiar, así que fui a Customize → Theme → My Theme → Common → Head, hice un pequeño ajuste y guardé, y puedo ver que una de las entradas se actualizó y una de ellas sigue siendo antigua…

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)

De nuevo, no estoy seguro de cuáles son las implicaciones de estos duplicados, si es seguro eliminar el ‘antiguo’, o si hay alguna otra forma de ‘reconstruir’ las cachés que limpie esto.

Para ser sincero, hasta ahora tengo 0/2 en esto, así que probablemente no soy la mejor fuente de información para esto. :slight_smile:

Hay un par de temas anteriores donde ha sucedido algo similar para index_tags_on_name si pudieran ser de alguna utilidad? por ejemplo.

1 me gusta

Reconstruye tu contenedor de datos. El plugin de IA requiere una extensión que aún no tienes.

¡Aprecio tu ayuda! Parece que me llevaste por el camino correcto. :star_struck:

Hice una copia de seguridad de la tabla con pg_dump, eliminé la entrada duplicada antigua y el arranque se completó con éxito. :+1:

¡Gracias por la confirmación! Pensé que podría necesitar actualizar el contenedor de datos (o de lo contrario, instalar pgvector). Me estaba conteniendo de hacerlo ya que no quería lidiar con el tiempo de inactividad.

Por el hilo de discourse-ai, parece que PG15 está en el horizonte, así que quizás espere un poco para eso.

Parece que la dependencia de pgvector podría ser para la función de Embeddings que no planeaba usar, pero desafortunadamente, parece que todo está empaquetado junto. Principalmente solo quería jugar con algunas de las funciones de reescritura mágica de OpenAI / ChatGPT, así que quizás una razón más para esperar hasta la próxima gran actualización del contenedor de datos. :slight_smile:

1 me gusta

Puedes esperar si quieres, pero las personas que usan un solo contenedor (que es la gran mayoría de los autoalojados) actualizan su postgres potencialmente cada vez que hacen una actualización, así que no hay mucha razón para esperar aparte de unos minutos adicionales de inactividad. Necesitarás reconstruir (o quizás simplemente destruir e iniciar) el contenedor web_only después de la reconstrucción de la base de datos.

1 me gusta

Esa es la razón principal. Incluso si son solo unos minutos, preferiría minimizarlo si no es crítico.

En ese sentido, probablemente debería abstenerme de usar un plugin beta por el potencial de inactividad. :stuck_out_tongue:

He seguido vagamente algunas de las discusiones sobre actualizaciones de “cero inactividad”. Quizás sean solo las gafas de color de rosa mirando hacia el pasado reciente, pero siento que he podido usar /admin/upgrade para la mayoría de las actualizaciones durante el último año, así que me he centrado en proyectos más críticos por el momento y he perdido interés en el enfoque de cero inactividad.

Cuando migré a un host más grande en enero, fue de “cero inactividad” en el sentido de que los usuarios podían seguir accediendo al contenido del sitio, pero hubo un breve período en el que las cosas solo se podían leer mientras hacíamos la transición. Supongo que podría usar ese enfoque para una actualización importante del contenedor de data si realmente quisiera minimizar la inactividad durante la próxima gran actualización de data.

PD. He leído muchas de tus publicaciones en la comunidad aquí a lo largo de los años. ¡Gracias por todos tus esfuerzos para apoyar a la comunidad! :star2:

¡Realmente lo parece! No he hecho una actualización para mis clientes de “reconstrucciones cuando las necesitas” en bastante tiempo. Para sitios como el tuyo, mi panel de control hará la reconstrucción y realizará las migraciones posteriores a la actualización después de que se haya lanzado el nuevo contenedor (si tu contenedor existente tiene esas migraciones configuradas para no ejecutarse la primera vez).

1 me gusta