La versione di Discourse che stai utilizzando include una versione di aws-sdk-s3 che dovrebbe fornire Aws::S3::TransferManager.
Stai utilizzando l’installazione Docker ufficiale di Discourse? Se stai usando la configurazione Docker ufficiale, il contenitore è stato completamente ricostruito come parte dell’aggiornamento?
Sì, credo di utilizzare l’installazione Docker ufficiale di Discourse. C’è un modo per esserne sicuro? È passato un po’ di tempo dall’installazione.
Per aggiornare, ho eseguito ./launcher rebuild app. Presumo che questo significhi che il container è stato completamente ricostruito, ma potrei sbagliarmi?
Alcuni dettagli aggiuntivi che potrebbero essere rilevanti:
In esecuzione Ubuntu 24.04.4 LTS
app.yml installa i plugin ufficiali docker_manager e discourse-doc-categories nell’hook after_code. Non ci sono altri plugin definiti in app.yml.
Sto cercando di archiviare i backup in un archiviazione compatibile con S3 fornita da Backblaze, e questo funzionava in precedenza.
Un elemento che potrebbe aiutare a restringere il campo è verificare quale gem aws-sdk-s3 viene effettivamente caricata all’interno del container in esecuzione.
La modifica a Discourse che ha introdotto Aws::S3::TransferManager ha anche aggiornato aws-sdk-s3 da 1.182.0 a 1.227.0:
Nella revisione di Discourse che hai linkato, Gemfile.lock dovrebbe ancora utilizzare aws-sdk-s3 1.227.0, che fornisce Aws::S3::TransferManager.
Potresti provare a entrare nel container:
cd /var/discourse
./launcher enter app
Poi, all’interno del container:
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
'
Potrebbe essere utile anche controllare l’applicazione stessa sotto 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
'
Poi esci dal container con:
logout
Se ciò riporta una versione più vecchia di aws-sdk-s3, oppure se TransferManager non è presente,
questo spiegherebbe l’eccezione del backup e suggerirebbe che le gem installate nel container non corrispondono all’attuale Gemfile.lock di Discourse.
Se riporta 1.227.0 e risolve correttamente Aws::S3::TransferManager, allora il problema è più insolito e sapremo di dover esaminare cosa differisce tra il processo di backup di Sidekiq e quell’ambiente interattivo.
Dato che stai usando ./launcher rebuild app, sembra proprio che tu stia seguendo il flusso di lavoro standard di discourse_docker; i comandi sopra ci diranno più precisamente cosa è effettivamente finito nel container ricostruito.
Mentre indagavo su questo, mi è venuto in mente di aver usato questa soluzione temporanea per aggirare un problema con l’AWS SDK che non funzionava con Backblaze. Aggiornandomi sull’argomento, sembra che Backblaze abbia aggiornato la propria API, il che rende la soluzione temporanea non necessaria.
Dopo aver rimosso la soluzione temporanea, il backup ha avuto esito positivo! Grazie per l’aiuto.
Un pensiero in merito: i modelli di compatibilità temporanei come questo potrebbero essere più sicuri se dotati di una sorta di condizione di auto-scadenza o di protezione, anziché continuare a sovrascrivere le dipendenze di Discourse all’infinito.
Ad esempio, per i backport temporanei del codice sorgente, ho in programma di utilizzare hook in produzione che prima controllino se la correzione upstream è già presente e applichino la patch solo se è ancora necessaria.
In questo caso, qualcosa di simile avrebbe potuto potenzialmente impedire che il pin di aws-sdk-s3 1.177.0 rimanesse attivo una volta che Discourse stesso ha iniziato a dipendere da funzionalità più recenti dell’SDK:
hooks:
after_bundle_exec:
- exec:
cd: $home
cmd:
- |
if grep -q "Aws::S3::TransferManager" lib/s3_helper.rb; then
echo "Discourse ora richiede Aws::S3::TransferManager; salto il downgrade obsoleto di Backblaze aws-sdk-s3"
else
echo "Applico il pin temporaneo di compatibilità Backblaze aws-sdk-s3"
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
Quel controllo specifico è solo esemplificativo: una verifica di versione più generale o un errore esplicito quando Discourse supera la versione SDK prevista sarebbero probabilmente preferibili.
Anche un errore esplicito sarebbe probabilmente preferibile rispetto alla generazione silenziosa di un container i cui gem non corrispondono più alle versioni attese da Discourse.
Sebbene concordassi che sarebbe stato preferibile un errore esplicito, il fatto era che volevo che i gem non corrispondessero alle versioni richieste da Discourse, poiché la versione più recente di aws-sdk-s3 inviava intestazioni non supportate da Backblaze e desideravo che i backup funzionassero.
Non so se esistesse un controllo che avrei potuto impostare preventivamente per ricevere una notifica quando la soluzione temporanea non fosse più necessaria. Ho implementato la soluzione temporanea un anno e mezzo fa, ad aprile 2025, prima che fosse disponibile una correzione.
Penso che la cosa migliore che avrei potuto fare fosse aggiungere una data di scadenza, per costringermi a verificare se la soluzione temporanea fosse ancora necessaria. Una funzionalità del genere potrebbe essere utile. Oppure, forse, la responsabilità ricade su di me per essere più proattivo e impostare promemoria per verificare se la soluzione temporanea sia ancora necessaria. Avere alcune note mi è stato utile in questo senso.