La versión de Discourse que estás ejecutando incluye una versión de aws-sdk-s3 que debería proporcionar Aws::S3::TransferManager.
¿Estás utilizando la instalación oficial de Docker de Discourse? Si estás usando la configuración oficial de Docker, ¿se reconstruyó completamente el contenedor como parte de la actualización?
Sí, creo que estoy usando la instalación oficial de Discourse con Docker. ¿Hay alguna forma de asegurarme de ello? Ha pasado bastante tiempo desde que realicé la instalación.
Para actualizar, ejecuté ./launcher rebuild app. Supongo que esto significa que el contenedor se reconstruyó por completo, pero ¿podría estar equivocado?
Algunos detalles adicionales que podrían ser relevantes:
Estoy ejecutando Ubuntu 24.04.4 LTS.
app.yml instala los plugins oficiales docker_manager y discourse-doc-categories en el gancho after_code. No hay otros plugins definidos en app.yml.
Estoy intentando almacenar las copias de seguridad en un almacenamiento compatible con S3 proporcionado por Backblaze, y esto había funcionado antes.
Una cosa que podría ayudar a acotar el problema es comprobar qué gem aws-sdk-s3 se está cargando realmente dentro del contenedor en ejecución.
El cambio en Discourse que introdujo Aws::S3::TransferManager también actualizó aws-sdk-s3 de la versión 1.182.0 a la 1.227.0:
En la revisión de Discourse que enlazaste, Gemfile.lock debería seguir utilizando aws-sdk-s3 1.227.0, que sí proporciona Aws::S3::TransferManager.
¿Podrías intentar entrar en el contenedor:
cd /var/discourse
./launcher enter app
Luego, dentro del contenedor:
cd /var/www/discourse
bundle info aws-sdk-s3
bundle exec ruby -e '
require "aws-sdk-s3"
puts "gem: #{Gem.loaded_specs["aws-sdk-s3"]&.full_name}"
puts "path: #{Gem.loaded_specs["aws-sdk-s3"]&.full_gem_path}"
p Aws::S3.autoload?(:TransferManager)
p Aws::S3::TransferManager
'
También podría ser útil comprobar la propia aplicación bajo Rails:
RAILS_ENV=production bundle exec rails runner '
puts "aws-sdk-s3: #{Gem.loaded_specs["aws-sdk-s3"]&.version}"
p Aws::S3.autoload?(:TransferManager)
p Aws::S3::TransferManager
'
Luego sal del contenedor con:
logout
Si eso informa de una versión más antigua de aws-sdk-s3, o si TransferManager no está presente, eso explicaría la excepción de la copia de seguridad y sugeriría que las gem instaladas en el contenedor no coinciden con el Gemfile.lock actual de Discourse.
Si informa de la versión 1.227.0 y resuelve correctamente Aws::S3::TransferManager, entonces el problema es más inusual y sabríamos que debemos buscar qué diferencia hay entre el proceso de copia de seguridad de Sidekiq y ese entorno interactivo.
Dado que estás usando ./launcher rebuild app, eso suena como el flujo de trabajo estándar de discourse_docker; los comandos anteriores deberían decirnos con más precisión qué terminó realmente en el contenedor reconstruido.
Al investigar esto, me acordé de que usé este workaround para evitar un problema con AWS SDK que no funcionaba con Backblaze. Al ponerme al día con el tema, parece que Backblaze actualizó su API, lo que hace innecesario el workaround.
Después de eliminar el workaround, ¡la copia de seguridad se completó con éxito! Gracias por la ayuda.
Una reflexión sobre esto: las plantillas de compatibilidad temporal como esta podrían ser más seguras si incluyen algún tipo de condición de autoexpiración o de protección, en lugar de seguir sobrescribiendo las dependencias de Discourse de forma indefinida.
Por ejemplo, con los backports temporales de código fuente, planeo usar hooks en producción que primero comprueben si la corrección ya está presente en la versión upstream y solo apliquen el parche si aún es necesario.
En este caso, algo a lo largo de estas líneas podría haber impedido que el pin fijo de aws-sdk-s3 1.177.0 continuara una vez que Discourse empezó a depender de funcionalidades más nuevas del SDK:
hooks:
after_bundle_exec:
- exec:
cd: $home
cmd:
- |
if grep -q "Aws::S3::TransferManager" lib/s3_helper.rb; then
echo "Discourse ahora requiere Aws::S3::TransferManager; omitiendo la degradación obsoleta de aws-sdk-s3 de Backblaze"
else
echo "Aplicando pin de compatibilidad temporal de aws-sdk-s3 de Backblaze"
bundle config set frozen false
sed -i 's/gem "aws-sdk-s3", require: false/gem "aws-sdk-s3", "1.177.0", require: false/' Gemfile
bundle update aws-sdk-s3
bundle add aws-sdk-core --version 3.215
fi
Esa comprobación en particular es solo ilustrativa; una comprobación de versión más general o un fallo explícito cuando Discourse supere la versión de SDK esperada probablemente sería mejor.
Incluso fallar de forma explícita sería preferible a generar silenciosamente un contenedor cuyos gem ya no coincidan con las versiones esperadas por Discourse.
Aunque estoy de acuerdo con que habría sido deseable que fallara de forma explícita, lo cierto es que antes yo quería que las gemas no coincidieran con las versiones esperadas por Discourse, porque la versión más reciente de aws-sdk-s3 enviaba cabeceras que Backblaze no soportaba y yo quería que las copias de seguridad funcionaran.
No sé si existía alguna comprobación que pudiera haber configurado proactivamente con antelación para notificarme cuando el workaround ya no fuera necesario. Implementé el workaround hace un año y medio, en abril de 2025, antes de que estuviera disponible una solución.
Creo que lo mejor que habría podido hacer es añadir una fecha de expiración, para obligarme a comprobar si el workaround seguía siendo necesario o no. Sería agradable contar con una funcionalidad así. O tal vez la responsabilidad sea mía, por no ser más proactivo y programar recordatorios para verificar si el workaround sigue siendo necesario. Tener algunas notas me ayudó en este aspecto, en ese sentido.