Rake uploads:migrate_from_s3 schlägt fehl

Ich habe die Schritte hier befolgt, meine gesamte Seite gesichert, meinen AWS S3-Bucket geklont, den Bucket-Namen in den Discourse-Einstellungen vom Original-Bucket in den Backup-Bucket geändert und das Kontrollkästchen „Uploads zu S3" in den Einstellungen deaktiviert.

Jetzt bin ich endlich bereit, mit der Migration von S3 zu beginnen … und sie schlägt fehl. :frowning:

Die Fehlermeldung

root@ubuntu:/var/www/discourse# rake uploads:migrate_from_s3
Migrating uploads from S3 to local storage for '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
(See full trace by running task with --trace)

(Hier ist die Zeile auf GitHub, an der der Fehler auftritt – ich vermute, es kann den Wert von s3_bucket nicht abrufen?)

Weitere Versuche

  • Ich habe versucht, die Zugangsdaten über die Befehlszeile hinzuzufügen, aber das hat nichts geändert. Also:
    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

  • Ich habe auch versucht, den S3-Bucket-Namen in meinen Einstellungen wieder auf den ursprünglichen Bucket-Namen zurückzusetzen, aber leider ohne Erfolg, das Ergebnis ist dasselbe.

  • Ich habe zudem versucht, die Anwendung neu zu erstellen. Gleiches Ergebnis.

@vinothkannans, weißt du, was hier los ist?

Bitte helft mir, Discourse-Freunde!

P.S. Kleine Randnotiz: rake --tasks listet diesen Task oder irgendeinen Task, der mit uploads beginnt, nicht auf. Ich bin mir nicht sicher, ob das etwas bedeutet.

Possible related issue? cc @mcdanlj

@pnoeric yes that looks like exactly the same thing. I haven’t heard back in that issue on precisely what the intent is for SiteSettings vs. GlobalSettings for S3, so I don’t have any more help to give right now than to add it to SiteSettings via configuration (point 1 in my post).

Hey, thanks for this reply… I’m not even sure what SiteSettings vs GlobalSettings means – I’m not that good a RoR coder and don’t understand the full setup well enough. I’m just following the basic instructions. :wink:

But hopefully @vinothkannans will jump in too; I think he wrote the code for the migrate tasks. Or anyone else from the @team that might know…

Let’s keep our eyes on this topic…

s3_bucket is in GlobalSettings which is set from the config/discourse.conf file normally created from environment variables in the app.yml file. SiteSettings are things you change from the Admin Settings in the app.

It looks like when this was first created, you could only change S3 by rebuilding the app, and more recently it became possible to fill in the data in the Admin Settings. I can’t tell what was intended by not just doing a wholesale migration when setting S3 in SiteSettings was added.

[Edit: I inadvertently reversed the two when first posting this response]

1 „Gefällt mir“

Hmmm @mcdanlj just to confirm, though, you haven’t been able to work out how to make the migrate_from_s3 actually work, correct?

I’m fine with editing whatever settings or low-level files or whatnot that is necessary… I just need to move off S3 ASAP since it’s costing me an arm and a leg.

Hi @pnoeric and @mcdanlj,

One debugging approach might be to enter into the rails console and then take a peek at the s2 site settings?

For example, in a plain ole OOTB discourse docker single container standalone app:

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)> 

comparing the SiteSettings (via the rails console) against the defaults, listed here:

Perhaps debugging in this manner might be helpful (no idea really, as we don’t use AWS or S3)? Maybe the rails console might help a bit?

1 „Gefällt mir“

the rake --tasks only shows tasks that have a description. You can view all available tasks through rake -AT

I don’t think it’ll help because I very recently had run these tasks on a test site. Both seem to depend on S3 variables being defined in the env however, it was a couple months ago and migrate_from_s3 didn’t really work for me.

1 „Gefällt mir“

Tricky question. I did set s3_bucket in config/discourse.conf as mentioned in the post you linked to, which did resolve this particular error, as I noted there.

This file is inside the container (./launcher enter app). Note that for this to survive ./launcher rebuild app you need also to add DISCOURSE_S3_BUCKET to the env section of your containers/app.yml file.

The fact that I fixed it was why it was a dev post, not a support request; I was asking what developers think is the right solution as I continue to hack at this.

I have about 100GB of files in S3 so I’m moving very carefully. I implemented a limit for posts to look at, and I next need to implement a limit for posts to modify. I’ve been trying one thing at a time. The fact that this appears to be rarely-used code and I’ve seen this error repeatedly makes me concerned about code rot and I don’t want to suddenly deface my entire site due to a bug, and this looks like it could be a good way to make that mistake.

  • For upload:// (for me, this means non-video) uploads, so far, it appears to be working. I’m doing one at a time and then reviewing the affected post to make sure everything works.

  • For uploads that don’t use the upload:// syntax (for me, this means video uploads as far as I can tell), where there is a literal reference to the URL in S3, it is mangling the URLs. That’s not a hard bug to fix as soon as I figure out for sure what I’m supposed to change them to but I haven’t done that yet. So that’s likely to be one of the PRs I post soon.

This is a spare time project for me, so no promises on timing.

1 „Gefällt mir“

Aha, thank you! I’ll give it a crack.

Ugh so no luck, @neounix @mcdanlj @vinothkannans. Still failing. But at least there’s a new/different error message…

Here’s what I tried today:

  1. Upgrade to latest Discourse, just to be sure.

  2. Add my s3_bucket in config/discourse.conf

  3. ./launcher enter app

  4. Edit containers/app.yml and added DISCOURSE_S3_BUCKET var

  5. Tried rake uploads:migrate_from_s3 and now it fails with a new error message (before it was downcase causing the problem, now it appears to be 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. So then I tried ./launcher rebuild app

  2. And again ./launcher enter app, rake uploads:migrate_from_s3

Same problem exactly:

/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)

Any other ideas?

Doing this process is a real drag btw-- I have to pre-schedule and announce the forum outage days in advance, then on the day of, change the main site so folks can’t get into the forum, and then I have to shut down the forum server on Dig Ocean and take a snapshot before proceeding. That’s ~30 minutes right there. Then I start it up again and then I can try the steps above. I am SO regretting setting up Amazon S3 for media storage! I’ve burned hours trying to undo that choice and still no luck (and still a big $$$ bill from Amazon each month). I’d love to get to the bottom of this. How can I help?

That line is:

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

Looks like it wants s3_region also; not clear to my why I didn’t run into that.

I’m not sure I follow your logic; my own migration of ~100GB of content I plan to do live, after a normal site backup. But I’m starting small, which is why I’ve been working on limiting the amount migrated at once. One warning: the code seems wrong for literal URL translations, as I see for video uploads, so if you allowed video uploads you might have a problem there with the code in its current state.

2 „Gefällt mir“

So maybe I should repeat all the steps I did above, but I’ll put s3_bucket, s3_region, s3_cnd_url, s3_secret_access_key etc. (basically, every variable I have) into the conf and yml files? I’d rather give it more than it (maybe) needs, just so the thing will actually work.

I saw where someone on the Discourse team had suggested to back up the entire local site before starting this transition. Which requires me to take my Digital Ocean server offline. :frowning:

Right. I’m starting small too… every time I try I am migrating 0 files. :grin:

Luckily members are only allowed to upload JPG, GIF and PNG in my forum so it should be ok.

Fingers crossed.

Backup and snapshot are not the same. A snapshot is the crudest form of backup. The Admin console has a backup facility. Make sure that you configure it to back up thumbnails in the configuration first.

Now that you know that you don’t have to take your site down, you should be able to relax. You can use batch_migrate_from_s3 to migrate at most a certain number of uploads. Right now it limits the posts that are considered rather than the migrations done, a bug for me to resolve in a future PR. But I need to also resolve the video upload bug, and I’d like to consider printing feedback because one of the points of the limit is to be able to confirm in affected posts that the migration was successful.

I’m likely to do this all over the next 1-2 months, so if you want to wait on that it might be worth paying a few more months of S3, up to you and I’m not making promises just stating intent.

2 „Gefällt mir“

@pnoeric Da dir die Verfügbarkeit der Seite wichtig ist, wollte ich dir mitteilen, was ich bisher gelernt habe.

Wie bereits erwähnt, habe ich die Migration live durchgeführt. Wenn ich die Migration nicht drossle, werden die Warteschlangen, die Aufgaben wie das Benachrichtigen von Nutzern über Aktivitäten anderer erledigen, verstopft, und die Benutzererfahrung auf der Seite leidet.

Ich habe etwa 500 Beiträge mit Videos und rund 30.000 Beiträge mit Bildern migriert, was insgesamt etwa zwei Wochen in Anspruch nahm.

Falls du den von mir verwendeten Code ausprobieren möchtest, findest du ihn aktuell hier:

Du kannst ihn herunterladen und in deine App kopieren, um den aktuellen Inhalt von lib/tasks/uploads.rake zu ersetzen.

Mit diesem Code kannst du beispielsweise Folgendes tun:

bin/rake uploads:batch_migrate_from_s3[100,1000]

Dadurch werden nur insgesamt 1000 Beiträge mit Uploads berücksichtigt, und Dateien werden von maximal 100 Beiträgen migriert, bevor der Vorgang gestoppt wird. Jedes Mal, wenn ein Beitrag nach der Migration seiner Uploads tatsächlich geändert wird, wartet das Skript, bis die Warteschlange leer ist, bevor es mit dem nächsten fortfährt.

Wenn du die Datei einfügst, wird dies zukünftige Site-Updates unterbrechen, bis du die Änderung rückgängig machst. Der einfachste Weg, dies nach Abschluss deiner Arbeit rückgängig zu machen, ist ./launcher rebuild app (obwohl ich als Entwickler git checkout HEAD lib/tasks/uploads.rake verwende, um meine Änderungen rückgängig zu machen…)

Ich habe festgestellt, dass ich zumindest bei Digital Ocean Spaces manchmal einige Wiederholungen durchführen muss, bevor eine Migration erfolgreich ist. Das aktuelle Skript gibt dir in diesem Fall keine Warnung aus; du musst es einfach weiterhin ausführen und abwarten, ob es klappt. Ich habe jedoch einen Pull Request (PR) eingereicht, der in dieser Hinsicht Fehlermeldungen ausgibt, damit du zumindest weißt, wenn etwas schiefgelaufen ist.

Ich habe eine einfache kurze Wiederholungsschleife sowie die Fehlermeldung hinzugefügt, und es scheint, dass die Wiederholungsschleife das Problem löst. Außerdem wurde die Validierung gemäß den aktuellen Regeln bisher auf den Rohinhalt vergangener Beiträge angewendet, was die Migration unterbrechen und Beiträge, die neu gerendert werden mussten, stillschweigend unberührt lassen konnte; auch das habe ich behoben. Du solltest auf keinen Fall eine Migration durchführen, ohne mindestens die Validierungskorrektur zu erhalten, die einer der Commits in meinem derzeit zur Prüfung stehenden PR ist.

Meine Migration ist, soweit ich weiß, abgeschlossen. Mein PR enthält den gesamten Code, den ich für den Abschluss meiner Migration verwendet habe. Er wurde noch nicht geprüft. Falls du möchtest, empfehle ich dir, unter Migrate_from_s3 problems mitzuverfolgen.

2 „Gefällt mir“

Danke! Ich werde das in den nächsten Tagen ausprobieren.

Ich habe gerade einen Hinweis in diesem Beitrag hinzugefügt, dass noch ein Fehler besteht, den wir heute entdeckt haben: Bei einigen Nutzern fehlen die Profilbilder. Ich weiß nicht, warum das passiert ist. Wir haben es mit einem Schulterzucken abgetan und bitten die betroffenen Nutzer, eine Wiederherstellung vorzunehmen, entschuldigen uns aber für das Problem.

Ich habe während dieses Vorgangs definitiv häufige Sicherungen durchgeführt! :smiling_face:

Viel Erfolg!

1 „Gefällt mir“

Ernsthaft, könnte mich das noch verrückter machen? :crazy_face:

Hier ist, was ich gemacht habe:

  1. Ich habe deinen neuen Code lib/tasks/upload.rake in mein Discourse kopiert.
  2. Ich habe ALLE meine Amazon s3_-Variablen zu config/discourse.conf hinzugefügt.
  3. Ich habe sie auch zu app.yml hinzugefügt (unklar, ob das etwas bringt, aber warum nicht).
  4. Ich habe diesen Befehl ausgeführt und bekam…
root@:/var/www/discourse/config# rake uploads:batch_migrate_from_s3[100,1000]
You must disable S3 uploads before running that task.

Und habe bestätigt:

Also, okay. Ich habe die Datei uploads.rake bearbeitet und einfach diese Prüfung entfernt.

Jetzt bekomme ich:

root@:/var/www/discourse/lib/tasks# rake uploads:batch_migrate_from_s3[100,1000]
Migrating uploads from S3 to local storage for 'default'...
Migrating up to 100 of 1000 posts...
... (viele Ausgaben hier) ...
Modified 91/100: 28795: 28486/1 - https://example.com/t/topic-title-here/28486/1
... (viele Ausgaben hier) ...

Es schien also zu funktionieren! Juhu!

Nachdem der erste Batch von 100 erledigt war, habe ich Sidekiq geprüft und sah, dass mein Testbeitrag in die Warteschlange gestellt wurde, also habe ich gewartet, bis das abgeschlossen war…

…bin dann zurückgegangen und habe nachgeprüft… und dieser Beitrag zieht sein Bild immer noch von Amazon S3. :frowning: Ich habe “HTML neu erstellen” für den Beitrag versucht, aber das hat nichts geändert.

Dann habe ich den gesamten Prozess erneut durchlaufen, von rake bis zum Ende, und bekam die gleichen Ergebnisse – die gleichen 100 Beiträge wurden verarbeitet, die gleichen Dinge in Sidekiq in die Warteschlange gestellt, und nachdem ich es laufen ließ, kommt das Bild in diesem Testbeitrag immer noch von S3.

Hmm, ich bin mir nicht sicher, was ich als Nächstes versuchen soll. :man_shrugging:t2:

@mcdanlj, ich wäre für jeden Vorschlag oder Rat dankbar, den du hast :wink:

1 „Gefällt mir“

Das ist genau das, was ich erwarten würde, wenn Sie diese Prüfung entfernen. Ich bin mir nicht sicher, warum Sie sich entschieden haben, sie zu entfernen. Es ist absichtlich. Schalten Sie vor Beginn der Migration die Uploads nach S3 ab.

1 „Gefällt mir“

Sie waren aus – völlig aus. (Das Bild des Kontrollkästchens in meinem Beitrag ist die richtige Einstellung, oder?) Ich habe sie sogar ein- und wieder ausgeschaltet. Keine Reaktion.