Plugin causando errores durante la reconstrucción

Hoy intenté actualizar mi instalación de Discourse, de 2.9.0.beta9 a 2.9.0.beta10. Pero esto salió terriblemente mal.

  1. Mi primer intento fue en la consola
cd /var/discourse
sudo git pull
sudo ./launcher rebuild app

Esto finalmente se interrumpió, con el siguiente mensaje en algún lugar en medio de todos los registros

PG::InvalidParameterValue: ERROR:  cannot extract elements from a scalar
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/pg.rb:110:in `exec'

Pude restaurar el foro simplemente iniciando la imagen antigua (que todavía andaba por ahí).

  1. Mi segundo intento fue a través de la consola web (/admin/upgrade). Pero esto finalmente se atascó con el mismo tipo de error: ERROR: cannot extract elements from a scalar. Al volver al panel de actualización, me dijo que todos los componentes se habían actualizado correctamente. Pero después de reiniciar el contenedor, el servidor ahora arrojó un error HTTP 500 :frowning_face:

  2. Hice una instalación limpia en una máquina separada, empezando desde cero. Pude instalar la versión beta10, pero intentar restaurar desde una copia de seguridad causó exactamente el mismo error.

¿Alguien por ahí que pueda ayudar?

Encontré la consulta que está fallando

INSERT INTO question_answer_votes (post_id, user_id, created_at)

	SELECT
	  X.post_id AS post_id,
	  (X.value->>'user_id')::int AS user_id,
	  (X.value->>'created_at')::timestamp AS created_at
	FROM (
	  SELECT
	    post_id,
	    jsonb_array_elements(value::jsonb) AS value
	  FROM post_custom_fields WHERE name = 'vote_history'
	) AS X
	WHERE (X.value->>'action') != 'destroy'
	ORDER BY (X.value->>'created_at')::timestamp DESC
	ON CONFLICT DO NOTHING

Si entiendo correctamente, esto sucede porque la función de psql jsonb_array_elements espera una matriz, pero recibe un valor NULL.

Ha habido un par de informes sobre esto:

Creo que puede tener que ver con tener instalado previamente el plugin Pavilion Question/Answer.

Veré si puedo conseguir que alguien le eche un vistazo más a fondo. :+1:

Estamos usando este plugin: https://github.com/angusmcleod/discourse-question-answer.

  • Parece estar relacionado con el plugin Pavilion Question and Answer.
  • Es un fork del plugin discourse/discourse-upvotes.
1 me gusta

Solo para comprobar, ¿qué complementos tienes en tu app.yml?

1 me gusta

El sitio que vi tenía un montón de esos Post Custom Fields que contenían un montón de cadenas que habían sido codificadas varias veces para que fueran inutilizables.

Algunas soluciones, en orden de complejidad:

  • dejar de usar el plugin (y quizás cambiar a los nuevos votos positivos)
  • eliminarlos todos
  • eliminar los malos
  • editar esos campos para que los datos vuelvan a ser cadenas json válidas.

El sitio que vi tenía datos malos de años de antigüedad. Esto parece ser un error que existió hace años y que ahora se está descubriendo.

Podría ser posible escribir código para arreglar las cadenas json rotas, pero no pude ver cómo hacerlo en 10 minutos.

Ver Question Answer Plugin - #301 by pfaffman para ejemplos

2 Me gusta

Había pensado en esto también, pero una rápida comprobación con el fork de Angus, no parece que se hayan realizado migraciones de datos. https://github.com/angusmcleod/discourse-question-answer/compare/main...discourse:discourse-upvotes:main

Esto se siente como contaminación de datos de las antiguas publicaciones de preguntas y respuestas, como dijiste. También me parece gracioso que esto aparezca ahora, dado que esa migración es de noviembre de 2021. ¿Supongo que es porque JayJay solo está cambiando al nuevo plugin ahora? En cualquier caso, volveremos a examinar esa migración.

1 me gusta
          - git clone https://github.com/discourse/docker_manager.git
          - git clone https://github.com/discourse/discourse-solved.git
          - git clone https://github.com/unfoldingWord-dev/discourse-mermaid.git
          - git clone https://github.com/angusmcleod/discourse-question-answer.git
          - git clone https://github.com/discourse/discourse-checklist.git
          - git clone https://github.com/discourse/discourse-cakeday.git
          - git clone https://github.com/discourse/discourse-canned-replies.git
          - git clone https://github.com/discourse/discourse-footnote.git
          - git clone https://github.com/discourse/discourse-staff-notes.git
          - git clone https://github.com/discourse/discourse-graphviz.git
          - git clone https://github.com/discourse/discourse-assign.git
          - git clone https://github.com/discourse/discourse-voting.git
          - git clone https://github.com/discourse/discourse-yearly-review.git
          - git clone https://github.com/discourse/discourse-saved-searches.git

1 me gusta

@nat No voy a cambiar al nuevo plugin en absoluto. Todavía estoy usando el conjunto de plugins que hemos tenido durante bastante tiempo.

Al menos una vez al mes, ejecutamos nuestras actualizaciones, así que no es como si hubiera una gran brecha entre versiones.

2 Me gusta

Solo como una pequeña nota al margen de la cuestión de preguntas y respuestas, ahora también hay un reemplazo para las respuestas predeterminadas:

Y creo que ahora también hay un componente de tema oficial de #Mermaid:

1 me gusta

Gracias. Lo miraré después de que se solucione mi problema original :smile:

1 me gusta

Si eliminara el plugin, restaurar la copia de seguridad aún ejecutaría la consulta que causa el problema.
Por lo tanto, necesitaría eliminar tanto el plugin como cualquier tabla + consulta que sea utilizada por este plugin.
¿Cómo sabría las tablas involucradas?

¿Ha comentado la línea del plugin e intentado una reconstrucción para confirmarlo?

2 Me gusta

Voy a intentarlo ahora. He revisado el archivo dump.sql, que forma parte de la copia de seguridad, y no hay ninguna mención de ninguna tabla question_answer_* en absoluto. Así que esto me da esperanzas…

1 me gusta

¡He tenido éxito en mi sistema de prueba!

  • Deshabilité el plugin
  • sudo ./launcher rebuild app
  • Restauré la copia de seguridad

Voy a trabajar en mi sistema en producción. Te mantendré informado.

1 me gusta

Los datos corruptos se encuentran en la tabla PostCustmField. Pero si no tienes el plugin, no intentará migrar esos datos a la nueva tabla.

El problema no es la migración en sí, sino que en algún momento del pasado los datos se corrompieron. Se ha roto, pero se rompió de una manera que pasó desapercibida durante años. Creo que quizás cada nuevo voto positivo la corrompió aún más. Una solución razonable podría ser ignorar los datos corruptos, quizás marcándolos como corruptos (quizás renombrando el campo personalizado) para que las futuras migraciones puedan ignorarlos y alguien pueda arreglarlos manualmente si así lo desea.

2 Me gusta

Éxito en producción también. Desactivé el plugin y seguimos adelante.
Todavía me pregunto por qué no me encontré con este problema antes. Como dije, cada mes, como rutina, actualizamos todos nuestros sistemas, así que debería haber visto este problema antes.

¿Cómo podría conectarme yo mismo a la base de datos de Discourse para verificar qué hay en la tabla post_custom_fields?

@Jaap-Jan_Swijnenburg Lamento que hayas experimentado un problema.

Respetuosamente no estoy de acuerdo contigo en eso :slight_smile:

El antiguo plugin QnA utilizaba el tipo de datos de campo personalizado estándar de Discourse, que está diseñado para manejar la conversión de ese campo a JSON. Pero eso simplemente no funciona en algunos casos (como este), por lo que (idealmente) necesitas incluir verificaciones de formato cuando trabajas con campos personalizados de Discourse (particularmente si estás trabajando con código y datos bastante antiguos como este). Sugeriría que eso es lo que el plugin Upvotes necesita hacer aquí, que de hecho es de donde proviene el error inmediato.

Puedes usar el plugin Data Explorer para verificar lo que tienes allí.

Bueno, en su mayor parte te cedo la razón en esto, y creo que estamos de acuerdo. Creo que es cierto que la migración funciona si los datos no están rotos. Estamos de acuerdo en que si los datos están rotos, debería fallar de manera más elegante de lo que lo hace ahora.

Sí, pero es probable que los datos se corrompieran hace años (ese es el caso en el sitio que conozco), pero no te diste cuenta porque no falló catastróficamente. Estoy bastante seguro de que no estaba gestionando los votos positivos como se esperaba, pero nadie se dio cuenta.

Lo haría desde rails, algo como esto:

./launcher enter app
rails c

Luego, cosas como esta:

all_votes=PostCustomField.where(name: "vote_history")
likely_broken_votes=PostCustomField.where(name: "vote_history").where("value like '\\\"%'")

Mira solo el id y los datos:

all_votes.pluck(:id,:value)

Obtén solo un pcf:

pcf=PostCustomField.find(1234)

Arréglalo

pcf.value='the stuff you really want in it'
pcf.save

Lo que sucede aquí es lo siguiente:

  1. Algunas personas tienen una versión muy antigua del plugin de preguntas y respuestas con mi nombre de usuario personal de GitHub en la URL del repositorio en su archivo app.yml.

  2. Hace años transferí el plugin QnA a paviliondev. Github redirige las URL de los repositorios cuando se transfieren, por lo que las URL antiguas con mi nombre de usuario personal siguieron funcionando.

  3. Años después, Pavilion transfirió el Plugin de Preguntas y Respuestas a Discourse. Discourse inicialmente mantuvo el nombre discourse-question-answer.

  4. Hace unos meses creé mi propia bifurcación (fork) del plugin alojado en discourse, mientras todavía se llamaba discourse-question-answer.

  5. Las personas con enlaces muy antiguos al plugin QnA con mi cuenta personal de GitHub ahora estaban clonando mi nueva bifurcación del discourse-question-answer significativamente actualizado alojado en discourse. En otras palabras, un enlace muy antiguo ahora apuntaba a una bifurcación de un nuevo plugin. A pesar de los años transcurridos, debería haberlo previsto, así que disculpas por ello. He eliminado esa bifurcación.

  6. Discourse cambió el nombre de discourse-question-answer a discourse-upvotes. Este cambio de nombre no ha tenido un impacto material en su caso @Jaap-Jan_Swijnenburg, pero es la razón por la que ahora está clonando (inesperadamente) una bifurcación de ese repositorio.

  7. Una migración en discourse/discourse-upvotes (anteriormente discourse-question-answer) asume que la columna value en post_custom_fields es segura para JSON.

  8. Los datos antiguos creados por el plugin cuando era angusmcleod/discourse-question-answer (hace años) no se guardaron como JSON válido por la preocupación HasCustomFields en discourse/discourse. Supongo, pero es probable que estos datos se agregaran antes de que se agregara la verificación de tipo JSON hace 4 años (todavía es posible terminar con JSON no válido en campos personalizados registrados como JSON en casos extremos).

Por lo tanto:

  1. Cuando las personas con la URL (obsoleta desde hace años) angusmcleod/discourse-question-answer en su app.yml actualizan su Discourse, se clona la migración en la nueva versión del plugin, se ejecuta la migración y potencialmente se crea este error.

Hay algunas soluciones para esto:

  1. @Jaap-Jan_Swijnenburg en su caso, solo necesita eliminar la referencia a mi antiguo plugin QnA y podrá reconstruir su sitio. Eso es todo; nada más. Parece que eso es lo que ha hecho :+1:

  2. La migración del plugin discourse/discourse-upvotes (anteriormente discourse-question-answer) podría actualizarse para manejar valores no JSON en la columna value en post_custom_fields.

Observaría que la opción 2 también manejaría el caso adicional de personas que realmente desean cambiar de una versión antigua del plugin QnA a discourse-upvotes. En ese caso, la migración se ejecutará y fallará si alguna entrada en la columna value de post_custom_fields no es JSON válido.

5 Me gusta