Rake uploads:migrate_from_s3 falla

Seguí los pasos aquí, hice una copia de seguridad de todo mi sitio, cloné mi bucket de AWS S3, cambié el nombre del bucket en la configuración de Discourse del bucket original al de la copia de seguridad y desmarqué la casilla “subidas a S3” en la configuración.

Así que ahora finalmente estoy listo para comenzar la migración fuera de S3… y falla. :frowning:

El mensaje de error

root@ubuntu:/var/www/discourse# rake uploads:migrate_from_s3
Migrando subidas de S3 a almacenamiento local para 'default'...
rake aborted!
NoMethodError: undefined method `downcase' for nil:NilClass
/var/www/discourse/app/models/global_setting.rb:107:in `s3_bucket_name'
/var/www/discourse/app/models/site_setting.rb:157:in `absolute_base_url'
/var/www/discourse/lib/tasks/uploads.rake:138:in `migrate_from_s3'
/var/www/discourse/lib/tasks/uploads.rake:118:in `block in migrate_all_from_s3'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rails_multisite-2.2.2/lib/rails_multisite/connection_management.rb:68:in `with_connection'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rails_multisite-2.2.2/lib/rails_multisite/connection_management.rb:78:in `each_connection'
/var/www/discourse/lib/tasks/uploads.rake:118:in `migrate_all_from_s3'
/var/www/discourse/lib/tasks/uploads.rake:93:in `block in <top (required)>'
/usr/local/bin/bundle:23:in `load'
/usr/local/bin/bundle:23:in `<main>'
Tasks: TOP => uploads:migrate_from_s3
(Véase el seguimiento completo ejecutando la tarea con --trace)

(Aquí está la línea en GitHub donde falla—supongo que no puede obtener el valor de s3_bucket?)

Otras cosas que intenté

  • Intenté agregar las credenciales a la línea de comandos, pero eso no marcó ninguna diferencia. Es decir:
    DISCOURSE_S3_BUCKET="dn-forum-storage-backup" DISCOURSE_S3_REGION="us-east-1" DISCOURSE_S3_ACCESS_KEY_ID="xxxxxxxxxxxxxxxxxxxx" DISCOURSE_S3_SECRET_ACCESS_KEY="xxxxxxxxxxxxxxxxxxxx" DISCOURSE_S3_CDN_URL="https://dn-forum-storage-backup.s3.us-east-1.amazonaws.com" rake uploads:migrate_from_s3

  • También intenté cambiar el nombre del bucket de S3 en mis configuraciones de nuevo al nombre del bucket original, pero sin suerte, mismo resultado.

  • También intenté reconstruir la aplicación. Mismo resultado.

@vinothkannans ¿sabes qué está pasando?

Por favor, ayudad, amigos de Discourse.

p.d. pequeña nota al margen: rake --tasks no lista esta tarea ni ninguna tarea que comience con uploads, no estoy seguro de si eso significa algo.

¿Posible problema relacionado? cc @mcdanlj

@pnoeric sí, eso parece exactamente lo mismo. No he recibido respuesta en ese problema sobre cuál es precisamente la intención de SiteSettings frente a GlobalSettings para S3, por lo que en este momento no puedo ofrecer más ayuda que añadirlo a SiteSettings mediante configuración (punto 1 de mi publicación).

¡Hola, gracias por esta respuesta…! Ni siquiera estoy seguro de lo que significa SiteSettings frente a GlobalSettings; no soy un programador de RoR muy experto y no entiendo la configuración completa lo suficiente. Solo estoy siguiendo las instrucciones básicas. :wink:

Pero espero que @vinothkannans también se una; creo que él escribió el código para las tareas de migración. O cualquier otra persona del @team que pueda saber…

Mantengamos el ojo puesto en este tema…

s3_bucket se encuentra en GlobalSettings, que se establece desde el archivo config/discourse.conf, normalmente creado a partir de variables de entorno en el archivo app.yml. SiteSettings son los ajustes que modificas desde la Configuración de Administrador en la aplicación.

Parece que, cuando se creó por primera vez, solo era posible cambiar la configuración de S3 reconstruyendo la aplicación, y más recientemente se hizo posible ingresar los datos en la Configuración de Administrador. No puedo determinar cuál fue la intención al no realizar una migración completa cuando se agregó la opción de configurar S3 en SiteSettings.

[Edición: Inadvertidamente invertí los dos conceptos al publicar esta respuesta por primera vez]

1 me gusta

Hmmm @mcdanlj, solo para confirmar, ¿no has podido averiguar cómo hacer que migrate_from_s3 funcione realmente, verdad?

No tengo problema en editar cualquier configuración, archivos de bajo nivel o lo que sea necesario… solo necesito salir de S3 lo antes posible, ya que me está costando un ojo de la cara.

Hola @pnoeric y @mcdanlj,

Un enfoque de depuración podría ser entrar en la consola de Rails y luego echar un vistazo a la configuración del sitio s2.

Por ejemplo, en una aplicación Discourse docker estándar OOTB de contenedor único independiente:

root@localhost:~# docker exec -it app rails c
[1] pry(main)> SiteSetting.s3_upload_bucket
=> ""
[2] pry(main)> SiteSetting.enable_s3_uploads
=> false
[3] pry(main)> 

comparando la Configuración del Sitio (vía la consola de Rails) con los valores predeterminados, listados aquí:

Quizás depurar de esta manera podría ser útil (realmente no tengo idea, ya que no usamos AWS ni S3). ¿Tal vez la consola de Rails podría ayudar un poco?

1 me gusta

rake --tasks solo muestra las tareas que tienen una descripción. Puedes ver todas las tareas disponibles mediante rake -AT.

No creo que ayude, porque ejecuté estas tareas recientemente en un sitio de prueba. Ambas parecen depender de que las variables de S3 estén definidas en el entorno; sin embargo, fue hace un par de meses y migrate_from_s3 no funcionó realmente para mí.

1 me gusta

Pregunta complicada. configuré s3_bucket en config/discourse.conf, como se mencionó en la publicación que enlazaste, lo cual resolvió este error en particular, tal como indiqué allí.

Este archivo está dentro del contenedor (./launcher enter app). Ten en cuenta que para que esto sobreviva a ./launcher rebuild app, también necesitas agregar DISCOURSE_S3_BUCKET a la sección env de tu archivo containers/app.yml.

El hecho de que yo lo haya solucionado es la razón por la que fue una publicación de desarrollo y no una solicitud de soporte; estaba preguntando qué opinan los desarrolladores sobre cuál es la solución correcta mientras sigo trabajando en esto.

Tengo alrededor de 100 GB de archivos en S3, así que estoy avanzando con mucho cuidado. Implementé un límite para los mensajes que se examinan, y ahora necesito implementar un límite para los mensajes que se modifican. He estado probando una cosa a la vez. El hecho de que este código parezca poco utilizado y que haya visto este error repetidamente me preocupa la degradación del código, y no quiero arruinar de repente todo mi sitio debido a un error; esto parece ser una buena manera de cometer ese error.

  • Para las cargas upload:// (en mi caso, esto significa cargas que no son de video), hasta ahora parece estar funcionando. Estoy procesando una a la vez y luego revisando el mensaje afectado para asegurarme de que todo funcione.

  • Para las cargas que no usan la sintaxis upload:// (en mi caso, esto significa cargas de video, según lo que he podido determinar), donde hay una referencia literal a la URL en S3, está deformando las URL. No es un error difícil de corregir en cuanto tenga claro a qué se supone que debo cambiarlas, pero aún no lo he hecho. Así que probablemente sea una de las PRs que publicaré pronto.

Este es un proyecto que hago en mi tiempo libre, así que no hay promesas sobre los plazos.

1 me gusta

¡Ajá, gracias! Lo intentaré.

Ugh, así que sin suerte, @neounix @mcdanlj @vinothkannans. Sigue fallando. Pero al menos hay un mensaje de error nuevo/distinto…

Esto es lo que intenté hoy:

  1. Actualizar a la última versión de Discourse, solo para asegurarme.

  2. Agregar mi s3_bucket en config/discourse.conf.

  3. ./launcher enter app.

  4. Editar containers/app.yml y agregar la variable DISCOURSE_S3_BUCKET.

  5. Intentar rake uploads:migrate_from_s3 y ahora falla con un nuevo mensaje de error (antes el problema era downcase, ahora parece ser start_with?):

/var/www/discourse# rake uploads:migrate_from_s3
Migrating uploads from S3 to local storage for 'default'...
rake aborted!
NoMethodError: undefined method `start_with?' for nil:NilClass
/var/www/discourse/app/models/site_setting.rb:161:in `absolute_base_url'
/var/www/discourse/lib/tasks/uploads.rake:138:in `migrate_from_s3'
/var/www/discourse/lib/tasks/uploads.rake:118:in `block in migrate_all_from_s3'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rails_multisite-2.3.0/lib/rails_multisite/connection_management.rb:68:in `with_connection'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rails_multisite-2.3.0/lib/rails_multisite/connection_management.rb:78:in `each_connection'
/var/www/discourse/lib/tasks/uploads.rake:118:in `migrate_all_from_s3'
/var/www/discourse/lib/tasks/uploads.rake:93:in `block in <main>'
/usr/local/bin/bundle:23:in `load'
/usr/local/bin/bundle:23:in `<main>'
Tasks: TOP => uploads:migrate_from_s3
(See full trace by running task with --trace)
  1. Entonces intenté ./launcher rebuild app.

  2. Y de nuevo ./launcher enter app, rake uploads:migrate_from_s3.

Exactamente el mismo problema:

/var/www/discourse# rake uploads:migrate_from_s3
Migrating uploads from S3 to local storage for 'default'...
rake aborted!
NoMethodError: undefined method `start_with?' for nil:NilClass
/var/www/discourse/app/models/site_setting.rb:161:in `absolute_base_url'
/var/www/discourse/lib/tasks/uploads.rake:138:in `migrate_from_s3'
/var/www/discourse/lib/tasks/uploads.rake:118:in `block in migrate_all_from_s3'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rails_multisite-2.3.0/lib/rails_multisite/connection_management.rb:68:in `with_connection'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rails_multisite-2.3.0/lib/rails_multisite/connection_management.rb:78:in `each_connection'
/var/www/discourse/lib/tasks/uploads.rake:118:in `migrate_all_from_s3'
/var/www/discourse/lib/tasks/uploads.rake:93:in `block in <main>'
/usr/local/bin/bundle:23:in `load'
/usr/local/bin/bundle:23:in `<main>'
Tasks: TOP => uploads:migrate_from_s3
(See full trace by running task with --trace)

¿Alguna otra idea?

Por cierto, hacer este proceso es realmente tedioso: tengo que programar y anunciar la interrupción del foro con días de antelación, luego, el día indicado, cambiar el sitio principal para que la gente no pueda acceder al foro, y después tengo que apagar el servidor del foro en DigitalOcean y tomar una instantánea antes de continuar. Eso ya son unos 30 minutos. Luego lo vuelvo a iniciar y entonces puedo intentar los pasos anteriores. ¡Me arrepiento muchísimo de haber configurado Amazon S3 para el almacenamiento de medios! He perdido horas intentando deshacer esa decisión y aún no tengo suerte (y además sigo teniendo una factura grande de Amazon cada mes). Me encantaría resolver esto. ¿Cómo puedo ayudar?

Esa línea es:

        if SiteSetting.Upload.s3_region.start_with?("cn-")

Parece que también requiere s3_region; no tengo claro por qué no me encontré con eso.

No estoy seguro de seguir tu lógica; mi propia migración de unos 100 GB de contenido la planeo realizar en vivo, después de una copia de seguridad normal del sitio. Pero estoy empezando poco a poco, por eso he estado trabajando en limitar la cantidad migrada de una sola vez. Una advertencia: el código parece incorrecto para las traducciones de URL literales, como veo en las cargas de video, así que si permitías cargas de video, podrías tener un problema allí con el código en su estado actual.

2 Me gusta

Así que tal vez debería repetir todos los pasos que hice arriba, pero incluiré s3_bucket, s3_region, s3_cnd_url, s3_secret_access_key, etc. (básicamente, todas mis variables) en los archivos conf y yml. Prefiero darle más de lo que (quizás) necesita, solo para asegurar que funcione.

Vi que alguien del equipo de Discourse sugirió hacer una copia de seguridad completa del sitio local antes de iniciar esta transición. Eso me obligaría a sacar de línea mi servidor de Digital Ocean. :frowning:

Correcto. Yo también estoy empezando poco a poco… cada vez que lo intento, estoy migrando 0 archivos. :grin:

Por suerte, en mi foro solo se permite a los miembros cargar JPG, GIF y PNG, así que debería estar bien.

Cruzo los dedos.

La copia de seguridad y la instantánea no son lo mismo. Una instantánea es la forma más básica de copia de seguridad. La consola de Administración tiene una herramienta de copia de seguridad. Asegúrate de configurarla para que incluya las miniaturas en la configuración primero.

Ahora que sabes que no necesitas dejar tu sitio fuera de línea, deberías poder relajarte. Puedes usar batch_migrate_from_s3 para migrar como máximo un cierto número de archivos subidos. Por ahora, limita los mensajes que se consideran en lugar de las migraciones realizadas; es un error que debo resolver en una futura PR. Pero también necesito solucionar el error de carga de videos, y me gustaría considerar imprimir retroalimentación, ya que uno de los objetivos del límite es poder confirmar en los mensajes afectados que la migración fue exitosa.

Es probable que haga todo esto durante los próximos 1-2 meses, así que si prefieres esperar, podría valer la pena pagar unos meses más de S3. La decisión es tuya; no estoy haciendo promesas, solo expresando mi intención.

2 Me gusta

@pnoeric, dado que te preocupa el tiempo de actividad del sitio, pensé en compartir contigo lo que he aprendido hasta ahora.

Realicé la migración en vivo, como mencioné. Si no aplico límites de velocidad a la migración, las colas que realizan tareas como notificar a los usuarios sobre la actividad de otros se saturan y la experiencia del usuario en el sitio se ve afectada.

Migré alrededor de 500 publicaciones con videos y aproximadamente 30.000 publicaciones con imágenes, lo que tomó unas dos semanas en completarse.

Si deseas probar el código que utilicé, actualmente está disponible en:

Puedes descargarlo y copiarlo en tu aplicación para reemplazar el contenido actual de lib/tasks/uploads.rake.

Con este código, puedes hacer algo como esto:

bin/rake uploads:batch_migrate_from_s3[100,1000]

Esto considerará solo 1000 publicaciones con archivos adjuntos en total y migrará archivos de un máximo de 100 antes de detenerse; cada vez que realmente modifique una publicación después de migrar sus archivos adjuntos, esperará a que la cola esté vacía antes de iniciar la siguiente.

Si copias el archivo, romperás las futuras actualizaciones del sitio hasta que deshagas el cambio. La forma más sencilla de deshacerlo una vez que estés satisfecho es simplemente ./launcher rebuild app (aunque como desarrollador, utilizo git checkout HEAD lib/tasks/uploads.rake para deshacer mis cambios…).

He notado que, al menos con los espacios de Digital Ocean, a veces tengo que reintentar varias veces antes de que una migración tenga éxito. El script tal como está actualmente no te avisa cuando eso sucede, y solo tienes que seguir ejecutándolo y esperar a ver. Tengo una solicitud de extracción (PR) pendiente de revisión que imprime errores en ese caso, para que al menos sepas que algo salió mal.

He añadido un sencillo bucle de reintento corto, así como el mensaje de error, y parece que el bucle de reintento resuelve el problema. Además, se estaba realizando la validación contra las reglas actuales sobre el contenido en bruto de publicaciones pasadas, lo que podía romper la migración y dejar silenciosamente publicaciones que necesitaban ser reprocesadas; también he solucionado eso. Definitivamente no querrás realizar una migración sin obtener al menos la corrección de validación, que es uno de los commits de mi PR actualmente en revisión.

He terminado mi migración, hasta donde sé. Mi PR contiene todo el código que utilicé para completar mi migración. Aún no ha sido revisado. Te sugiero seguir el hilo en Migrate_from_s3 problems si lo deseas.

2 Me gusta

¡Gracias! Voy a probar esto en los próximos días.

Acabo de agregar una nota en ese mensaje sobre un error que quedaba y que descubrimos hoy: las fotos de perfil han desaparecido para algunos usuarios, y no sé por qué. Nos encogimos de hombros y hemos estado pidiendo a los usuarios afectados que restauren, con disculpas por el problema.

¡Definitivamente hice copias de seguridad frecuentes durante este proceso! :smiling_face:

¡Mucha suerte!

1 me gusta

En serio, ¿esto podría volverme más loco? :crazy_face:

Esto es lo que hice:

  1. Copié el nuevo código de lib/tasks/upload.rake a mi Discourse
  2. Añadí TODAS mis variables de Amazon s3_ a config/discourse.conf
  3. También las añadí a app.yml (no estoy seguro de si eso hace algo, pero ¿por qué no?)
  4. Ejecuté este comando y obtuve…
root@:/var/www/discourse/config# rake uploads:batch_migrate_from_s3[100,1000]
Debes deshabilitar las subidas a S3 antes de ejecutar esa tarea.

Y confirmé:

Bueno, vale. Edité el archivo uploads.rake y simplemente eliminé esa verificación.

Ahora obtengo:

root@:/var/www/discourse/lib/tasks# rake uploads:batch_migrate_from_s3[100,1000]
Migrando subidas de S3 a almacenamiento local para 'default'...
Migrando hasta 100 de 1000 publicaciones...
... (muchos resultados aquí) ...
Modificado 91/100: 28795: 28486/1 - https://example.com/t/topic-title-here/28486/1
... (muchos resultados aquí) ...

¡Parecía que funcionaba! ¡Genial!

Después de procesar ese primer lote de 100, revisé Sidekiq y vi que mi publicación de prueba estaba en cola, así que esperé a que terminara…

…luego volví a revisar y… ¡esa publicación sigue obteniendo su imagen de Amazon S3. :frowning: Intenté “Reconstruir HTML” en la publicación y eso no cambió nada.

Entonces intenté todo el proceso de nuevo, desde el comando rake hasta el final, y obtuve los mismos resultados: se procesaron las mismas 100 publicaciones, se encolaron las mismas cosas en Sidekiq, y después de dejarlo ejecutarse, la imagen en esa publicación de prueba sigue viniendo de S3.

Hmmm, no estoy seguro de qué probar a continuación. :man_shrugging:t2:

@mcdanlj, agradezco cualquier sugerencia o consejo que puedas tener :wink:

1 me gusta

Eso es exactamente lo que esperaría si eliminas esa verificación. No estoy seguro de por qué decidiste eliminarla. Es intencional. Desactiva las cargas a S3 antes de iniciar la migración.

1 me gusta

Estaban apagados, completamente apagados. (¿La imagen de la casilla de verificación en mi publicación muestra la configuración correcta, verdad?) Incluso los encendí y los volví a apagar. No funcionó.