Probleme bei der Migration von S3

When migrating from S3 to local storage, we see a number of issues.

The main issue is that the migrate_from_s3 rake task is not taking the Uploads table as a starting point, but the posts. This causes it to skip a lot of uploads which are being left on S3.

  • uploads used as logo’s because they are not referenced in a post
  • uploads for avatars because they are not referenced in a post
  • uploads that are (for some reason) referenced by their CDN URL in raw because they do not match the regex that is being used to identify the uploads
  • uploads that are on non-AWS S3 storage because they do not match the regex because it requires amazonaws in the URL
  • uploads that for some reason do not match the second, different regex (we’re seeing this with non-image uploads like mp3 files, not sure why this is happening)
2 „Gefällt mir“

We’re working on improving the way we associate uploads to posts (by using the upload:// scheme) that will make these storage migrations much more bulletproof. There’s little point to fixing these rake tasks before that’s done.

7 „Gefällt mir“

I recently opened a new PR to allow migrating fewer posts at a time (such as testing one at a time) and added tests for the task.

It feels like it makes sense to start with posts, since you want to rebake posts to change the URL in the cooked post after each migration; migrating all the uploads and then starting the rebakes would leave the site very broken for potentially a long time for a large site (I need to migrate about 100GB from S3 to local, so I care). But what I wrote might help start writing a migrate_uploads_from_s3 task that would be run after migrate_from_s3 in order to clean up uploads that weren’t part of posts.

@zogstrip What’s the current status of “We’re working on…” — is this still in flux or is this migration now worth paying attention to?

5 „Gefällt mir“

We’ve done lots of work on the uploads front to ensure we have better posts <=> uploads associations.

These migration tasks can be improved at will :+1:

2 „Gefällt mir“

I’ll find out whether it’s worth my time looking into non-post uploads after I am able to use the batch uploads to migrate my site in off hours! :slight_smile: Thanks for the PR review!

1 „Gefällt mir“

I have two things to address next: The first is that the limit is helpful but is only a limit on the search space; next I want to be able to specify a max number of posts to modify. So I’ll want to add a max number of posts to modify as well as a limit for the query.

Also, when specifying max, it makes sense to be verbose about what is being processed for debugging purposes, so I’d like to make the output verbose if max is not nil — this will let people validate the process before continuing, since that’s the primary use case for this work.

I think what I’ll do is specific max as the first argument, and an optional limit as the second, because really the max is the most important thing; limit is just to make “one ping only” cheaper.

The second is non-upload: uploads. A bit over a year ago, I tried uploading a video to the Discourse site I was joining, as I was floundering around trying to figure out how to write the migration from Google+ to Discourse, and saw that what was written was https://#{SiteSettings.absolute_base_url}/original/3X/b/a/ba9e06ebc2f4397f26793bb5cd4e169308dd371d.mp4

Today, when I upload a video, I get something like ![file_example_MP4_480_1_5MG|video](upload://caJ9ykkpshw3PFK4464VUIPWJ4l.mp4) instead.

At least in my most recent test, migrate_from_s3 completely mangled those URLs, making them not even be URLs any more, so that definitely needs to be fixed. Then, I think that this task is unlikely in practice to run into ![text](non-upload-url-to-migrate) so as a first pass I’d like to just add the link markdown around the magic upload protocol, rather than making the regex handle both cases and be even harder to read as a result. But I might change my mind on that.

It looks like the video or audio tag is added in javascript by regex match, so I’ll have to copy the regexes in from app/assets/javascripts/discourse/app/lib/uploads.js into the task to identify them properly. I’ll include the source of the regexes so the next person to find them knows where to update them from. :stuck_out_tongue:

Tonight, I made some time to work on this, and I have a draft PR underway. It is not finished yet; I know there are bugs left in it. I don’t think I’ve changed any behavior for upload: pseudo-protocol URLs (normal for images) at this point, though I added a sanity check.

With the changes in this PR, I’ve successfully migrated both normal upload: pseudo-protocol uploads and videos that are currently referenced explicitly by reference to S3 (well, digital ocean spaces in my case). I’m using this to modify only one post at a time with this command:

bin/rake uploads:batch_migrate_from_s3[1,1000]

Note that this will not go beyond the first 1000 posts returned somewhat randomly from the database query; the low limit is just for speed doing the query while migrating just one post at a time, reviewing that post for correct behavior and then starting over to find another one. This command works this way only with the PR I’m currently working on!

I’m continuing to add diagnostic output as I work on this, and I am starting to think that it is important for more than development. I’m seeing a lot of transient download failures from digital ocean spaces where some but not all of the downloads in a post get migrated, which in the original will just print a . and keep going and then say Done but really the task won’t be done. I had to do something like five or six passes on one post before it migrated all the files. (I wasn’t counting because I thought I was debugging a local bug at first.) I’m expecting to have to run this migration repeatedly with the same limit until the diagnostics are clean. Therefore, I’m making verbose progress print only if max is set, but printing useful warning messages either way.

Right now, I’m using the following hack for discourse spaces intermittently failing downloads, which in practice has been improving my success rate tremendously (3 retries has been entirely sufficient across hundreds of migrated posts so far).

https://github.com/johnsonm/discourse/commit/7dfac12a2ea6ec04ba4e0616b4e0dbd1d806cff7

Also, I discovered that somehow we ended up with videos larger than the limit I set when I imported from Google+ — I have had to temporarily increase both SiteSettings.max_image_size_kb and SiteSettings.max_attachment_size_kb while doing one-shot migrations of a few oversized videos that it’s not clear to me how they ended up on the site, but I don’t want to break them now… No idea if the bug that allowed oversized uploads was in my import script, discourse, or merely my memory of what changes I made to settings over time. :wink:

Because much of what I’m migrating was an import from G+, some of my posts ended up failing current validations. I got a few Unhandled failure: Validation failed: Sorry, new users can only put one image in a post and didn’t initially understand why they didn’t recur. It turns out that the uploads were successfully moved to local, and they all used the upload: pseudo-protocol, so the raw didn’t change. However, post.save! still failed with that error on validations, which prevented post.rebake! from firing, so I have a few posts out of 30K with images that need to be rebaked; sadly, I have no record of which posts those are. I have now switched to post.save!(validate: false) as another fix, so this particular problem should not recur. I’m very glad I made the migration start bailing out on unhandled errors though, or this would have potentially done lots more damage than a few posts.

To keep my site usable, including delivering notifications, while running the migration, I don’t want to spam the sidekiq queues. I know naming things is one of two hardest problems in computer science, along with cache invalidation and off-by-one errors, but I’m proposing DISCOURSE_MIGRATION_MAX_ENQUEUED as an environment variable for how many total queue slots (not job slots) are allowed to be filled when proceeding to migrate another item after a rebake during a migration, to avoid spamming the queues, so that the site will continue to function. I have a patch that adds this, defaulting to zero, for all the per-post rebaking in lib/tasks/uploads.rake. I am using this on my production migration.

https://github.com/discourse/discourse/blob/59a761851b9c8786d3a9692f8c595372b0534f77/lib/tasks/uploads.rake

4 „Gefällt mir“

@zogstrip Do you mind reviewing this PR since you have context from recent review on my last one in this area? FIX: Make migrations from S3 more robust; fix bare URL migration by johnsonm · Pull Request #10093 · discourse/discourse · GitHub

I’ve included in it the fixes I’ve been doing while running this relatively large migration. I haven’t tried to add tests for every fix; I’m not sure how to inject every form of error. But at least the new functionality is tested.

@RGJ I think that my PR as it stands now might deal with all but your first two points, except that I’m not sure about CDN. My site used CDN and migrated videos that had CDN urls but that might have been a side effect of the naming with discourse spaces. If you have additional cases, hopefully my PR will give you an easy scaffolding for adding to the regex and adding test cases for the additional variations.

I think that it is right to first migrate by post, because after migrating the uploads in a post the post needs to be rebaked so that the cooked post has the right URLs in it. After I finish migrating my posts (which might take less than two weeks now that I’ve changing my rate-limiting to check the queue length directly), I’ll be looking at any remaining work to do to clean up.

Because multiple posts can share references to the same content if more than one person upload the same file, there needs to be a second pass that checks the cooked data for old URLs and rebakes those posts to pick up new location. It can use the same rate-limiting to avoid soaking queues.

I probably won’t see any broken logos at makerforums because we tweaked branding after we stopped putting new content in “s3” (for us, digital ocean spaces) but I probably will see a bunch of uploads still in S3 for avatars at least. Migrating an uploads not associated with a post should be started only after all posts have been migrated, and I’ll probably have to write that up after I finish migrating uploads in posts.

@pfaffman I see Bizarre Problems with migrate_from_s3 - #5 which describes errors that didn’t repeat. Without my fixes in the current PR, errors are silently eaten, including validation failures. I think work here will address at least some of the problems you saw then.

@hosna the problems you raise in https://meta.discourse.org/t/what-does-rake-uploads-migrate-from-s3-exactly-do/97285 are either partially or completely solved so far in this PR. If they aren’t completely solved, I have added tests that will make it easier to add further tests to validate additional fixes.

@sam since you put the 2.6 label on the PR, I’m assuming it won’t get merged for at least a few days; should I pull my rate-limit feature work into the PR along with the fixes? Or do you have a preference to keep fixes and feature work in separate PRs? I can do either way. The rate limiting feature is working really well; I’m migrating about three times as fast, without site availability impact, now that I’m waiting for the sidekiq queue to drain, so it makes sense to pull it in, I think, if it’s something that is normally accepted in PRs. Otherwise, I need to wait the PR on merging the work it is based on, so either way it would be good to hear.

..

I DRYed out my migration rate limit patch and pulled it into the PR. It’s working in practice, and sar tells me that I’m seeing nearly zero idle time continuously, while the site continues to function, during the live migration. One benefit of the batch mode is that I can check for new Discourse versions after each full batch of migrations; I upgraded my site to 2.6.0beta1 at the first opportunity after it was cut, and have been running the migrations successfully on 2.6.0beta1 with my migration PR on top since the update.

I think that the PR is ready for review now; I’ll be planning to submit another PR for the last few stages, but getting this in place will improve the general migration experience for everyone even before I finish out the last pieces.

5 „Gefällt mir“

Well, that was a long time ago. . .

I’m anxious to see this worked out. Right now I’ve got several sites on multisite that need to pull images from s3 (right now, I think some images are local and others are on s3), and then push to s3.

1 „Gefällt mir“

@pfaffman It’s probably a good thing that when I started my migration project I didn’t know what I since think I have figured out. It looks like if I had used minio client to copy all of the S3 bucket into the local uploads folder, modified all Upload.url to nil in the rails console, and rebaked the site, everything would have been migrated in hours without having to regenerate all the images. (Instead, I’m rate-limited by running all the image conversions again, as if local CPU is cheaper than just copying all the processed images from S3.)

And then, if it had been that easy, I wouldn’t have done any of this work to make migrations more reliable in general, and no one else would have benefited. :slight_smile:

4 „Gefällt mir“

Oh. That sounds like what I want to know. Maybe I’ll give that a shot.

1 „Gefällt mir“

I would… definitely take a backup before trying that route, since I’m just speculating. I don’t want to mislead you.

Oh, and one more thing: that would have completely failed for audio and video uploads, and I wouldn’t have noticed until later, and then I would have been trying to figure it out and write custom code. So if you have audio and video uploads, you definitely want to start there, and it won’t work right without the PR that’s open and won’t merge until after the 2.5 release since @sam tagged it 2.6.

2 „Gefällt mir“

My apologies for joining the conversation this late. I just looked at your PR and I am wondering why you are recreating the Upload model instead of just changing their URL ? And why not just iterate through the OptimizedImages and doing the same?

2 „Gefällt mir“

@RGJ I didn’t change that at all; recreating Upload was a bug fix from @zogstrip in Cannot execute the rake uploads:migrate_from_s3 - #11

I’m just trying to make the code that was already there work, and I don’t know discourse internals well; I’ve been stumbling around in the dark a lot. My only ruby experience is the few PRs I’ve done for discourse. Following the pattern of the existing code does seem to be not the most efficient route (see my conversation with @pfaffman above about short-circuiting), I completely agree. As you can tell from the fact that earlier today I didn’t even realize that OptimizedImages.url would also need to be modified to a /uploads path and etag set to nil (and I don’t know what else) I’m still flying blind.

Still need to iterate across posts first at least for fixing up old literal URLs in posts. Still need some of the other fixes, like not revalidating posts and not silently eating errors. Still want to rate limit, I think, to limit impact on live sites.

For your first two concerns involving non-pots updates, here’s my work in progress, not yet tested on a live site (commit) that might help, but which I won’t get to testing on my live site until all the post upload migration is finished.

Tweaking something that used to work was all I had appetite for. If you’d like to do a faster migrate I’m all for it; it might make sense to merge my slower-but-at-least-better work as a pareto improvement, and then you could completely replace it with something much better and I’d be the first to celebrate, even if I’m no longer in a position to use it at that point.

1 „Gefällt mir“

@mcdanlj Thank you for your explanation. I was sincerely asking a question though, not implying that there are any issues now. I don’t know if the way I suggested is any “better” at all - maybe it would introduce a lot of new issues. I assume that the code like it is now - no matter who wrote it - is like it is for a reason.

3 „Gefällt mir“

@RGJ gleichermaßen, ich bin aufrichtig der Meinung: Wenn jemand mit Sicherheit weiß, wie man das Fiasko des Neuaufbaus aller Bilder vermeidet, bin ich dafür. Und wenn ich ein erfahrener Discourse-Entwickler wäre und wüsste, wie man das einfach umsetzt, hätte ich das wahrscheinlich von Anfang an so gemacht.

Meine Vermutung ist, dass die Migration weg von S3 für diejenigen mit vielen Bildern kein häufiger Fall ist, sodass es sich im Verhältnis zu allgemein nützlicheren Features für Discourse kaum lohnt, die Zeit dafür aufzuwenden. Ich hatte beim Import von Google+ nach MakerForums etwa 100 GB hochgeladene Dateien. Wir entschieden uns für S3 mit der Idee, dass viele Nutzer aus diesen Communities zu MakerForums wechseln könnten. Am Ende zogen jedoch nur wenige Communities aktiv mit, sodass das weitere Wachstum den Verbleib bei S3 letztlich nicht mehr rechtfertigte. Ich gehe davon aus, dass dies ein eher extremer Ausreißer ist und die Neubearbeitung der Bilder nur einmalige Kosten verursacht.

Schließlich bin ich Ihnen sehr dankbar, dass Sie dieses Thema überhaupt eröffnet haben, denn sonst hätte ich nicht-postbezogene Uploads sehr leicht übersehen.

@RGJ Sie haben eindeutig recht, dass das Zerstören und Neuerstellen keine gute Lösung ist. Ich habe eine Prüfung hinzugefügt: raise "Error: upload url #{url} changed to #{new_upload.short_url}, should be unchanged." if url != new_upload.short_url, die zumindest Probleme mit beschädigten Quellen meldet. Der heutige Ausfall von Digital Ocean Spaces hat dazu geführt, dass mir beschädigte Daten gesendet wurden, wodurch dieser Fehler bei vielen Uploads ausgelöst wurde – ich weiß nicht, wie viele. Da jedoch der alte Upload bereits zerstört war, habe ich nun einige beschädigte Seiten. Mir ist das erst aufgefallen, nachdem ich den Scrollback mit den Logs verloren hatte, die mir mitteilten, welche Seiten beschädigt sind. Daher kann ich sie nicht einmal manuell aus einem Backup reparieren.

Meine Arbeit ist also zwar eine Verbesserung gegenüber dem alten Weg, da sie zumindest einige Fehler meldet, aber es wäre viel besser, die Dateien herunterzuladen, die SHA1-Prüfsummen der heruntergeladenen Dateien zu prüfen und sie dann in lokale Dateien zu schreiben. In der Zwischenzeit habe ich meinen PR so angepasst, dass die Migration bei jedem unbehandelten Fehler gestoppt wird, um Datenverlust zumindest zu begrenzen.

Ich bin immer noch der Meinung, dass meine Arbeit als Pareto-Verbesserung gemergt werden sollte, da sie die Situation nicht verschlechtert, sondern verbessert. Es wäre jedoch deutlich besser, es einfach richtig zu machen. Ich denke, das wäre die Erstellung von lib/file_store/from_s3_migration.rb, die parallel zu lib/file_store/to_s3_migration.rb arbeitet, aber das übersteigt derzeit meine Möglichkeiten.

Da mein PR noch nicht überprüft wurde, habe ich noch mehr darauf aufgesetzt. Ich habe eine Aufgabe uploads:report_missing_uploads hinzugefügt, die in raw nach Vorkommen von upload://... sucht, bei denen das Upload-Objekt nicht vorhanden ist. Zumindest in meinem Fall kann ich dank Backups durch diese suchen, die verwaisten Dateien finden und sie auf die Site wiederherstellen, um dann diese Beiträge neu zu rendern und die fehlenden Bilder wiederherzustellen. Ich habe 678 solcher Fälle gefunden, von denen ich bisher alle außer 10 in den Backups wiedergefunden habe. Daher bin ich froh, dass ich diesen Test geschrieben habe! Ich muss das noch erledigen, bevor ich in die Phase übergehen kann, in der ich die restlichen Beiträge neu rendern werde.

Ich habe meine erste Migrationsphase abgeschlossen, ohne die betroffenen Beiträge mit geteilten Uploads neu zu rendern und ohne nicht-postbezogene Uploads. Nach Abschluss eines weiteren Remote-Backups plane ich, diese Funktionen ebenfalls zu testen und sie meinem PR hinzuzufügen.

Ich habe nun mit dem Testen der nächsten Migrationsphasen begonnen: Neu-Rendering und Migration nicht-postbezogener Uploads. Meine erste Lektion war, dass das Neu-Rendering als nächster Schritt aufgrund von Avatar-Bildern in Zitaten, die nicht-postbezogene Uploads betreffen, fehlschlägt. Daher muss das Neu-Rendering der Beiträge der letzte Schritt sein.

Nächste Entdeckung: Danke für die Fremdschlüsselbeschränkungen! Während der Migration nicht-postbezogener Uploads stellte ich fest, dass ich mindestens Profile vor der allgemeinen Migration nicht-postbezogener Uploads migrieren muss.

ActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR:  update or delete on table "uploads" violates foreign key constraint "fk_rails_1d362f2e97" on table "user_profiles"

Die Profil-Migration war knifflig, da ich zwei mit dem Profil verbundene Uploads migrieren musste. In einigen Fällen verwendeten die Benutzer jedoch dasselbe Bild für beide, sodass ich diese Arbeit in drei Schritten erledigen musste. Ich habe alle Profile auf meiner Site mit S3-URLs erfolgreich migriert.

Ich habe alle nicht-postbezogenen, nicht-profilbezogenen Uploads migriert. @RGJ, wenn Sie den von mir geposteten Branch testen möchten, ist er mit meiner Arbeit auf dem neuesten Stand. Alles darin wurde bereits für eine abgeschlossene Site-Migration verwendet.

@cvx Ich weiß nicht, wann Sie Zeit für eine Überprüfung haben werden, aber ohne meinen PR ist migrate_from_s3 definitiv voller schweigsamer Datenvernichtungsfehler. Was ich getan habe, ist nicht perfekt, aber es schützt vor vielen Fehlern, auf die ich in der Praxis gestoßen bin.

Ich habe hier all die Arbeit erledigt, die ich derzeit vorhatte. Ich habe meine Site migriert, was bedeutet, dass ich selbst keine effektiv bewerteten Änderungen mehr vornehmen kann. Wenn Sie diesen PR ablehnen, schlage ich dringend vor, stattdessen die bestehende Migration zu löschen, da sie für Benutzer Daten stillschweigend zerstören wird.

Bezüglich des PR: Manchmal treten in CI (in der aktuellen Version) Testfehler auf, ähnlich wie hier:

7867 examples, 0 failures, 11 pending, 1 error occurred outside of examples

##[error]Process completed with exit code 1.

Dies lässt sich bei mir lokal (bisher) nicht reproduzieren, und ich sehe in den CI-Logs keine Informationen darüber, was in CI falsch läuft. Daher werde ich meine Zeit nicht weiter damit verschwenden, CI-Ausgaben nach versteckten Informationen zu durchsuchen.

Eine letzte Anmerkung: Nach Abschluss der Migration stellten wir fest, dass die Profilbilder einiger Benutzer bei der Migration verloren gingen und sie diese manuell wiederherstellen. Ich vermute, dass zusätzlicher Code erforderlich gewesen wäre, um dies erfolgreich abzuschließen. Da ich das jedoch erst zu spät herausfand, habe ich keinen Testfall, um dies zu validieren. Das ist also ein verbleibender Fehler, der in einigen Konfigurationen Probleme verursachen könnte, aber ich bin nicht mehr in der Lage, diese zusätzliche Korrektur zu schreiben.

5 „Gefällt mir“

Da mein PR, der die stille Datenkorruption behebt, die migrate_from_s3 betrifft, noch nicht einmal einen kurzen Blick erhalten hat, kann migrate_to_s3 dann zumindest als Einbahnstraße dokumentiert werden?

Derzeit ist es ehrlich gesagt eine Falle für Anfänger.

@cvx @zogstrip Was ist eure Präferenz? Den PR prüfen oder migrate_from_s3 einfach komplett entfernen und offen zugeben, dass es eine Einbahnstraße ist?

5 „Gefällt mir“

Entschuldigung, hier liegt mein Fehler. Ich werde den PR diese Woche prüfen.

7 „Gefällt mir“

Der Review-Inhalt besagte im Wesentlichen, dass der aktuelle Ansatz so völlig falsch ist, dass er von Grund auf neu und auf eine andere Art und Weise aufgebaut werden muss; dass der Versuch, ihn so zu beheben, wie er zuvor geschrieben wurde, nicht in Ordnung ist. Ich bin nicht bereit, das zu tun, daher bin ich der festen Überzeugung, dass migrate_from_s3 vollständig entfernt werden sollte und migrate_to_s3 als Einbahnstraße gekennzeichnet werden muss, bei der man wirklich sicher sein sollte, dass man sich dauerhaft darauf festlegt. Aktuell ist das Vorhandensein von migrate_from_s3 im Quellcode überhaupt ein Fehler der Datenintegrität in Discourse.

Ich habe während meiner Arbeit am Migrationsprozess kein zeitnahes Review erhalten, und da ich die Migration längst durchgeführt habe (mit einigen fehlerhaften Ergebnissen, wie etwa beschädigten Avataren), verfüge ich über keine sinnvolle Testumgebung mehr. Ich habe null Vertrauen, dass ich es richtig machen würde, daher habe ich mich aus diesem Streit zurückgezogen. Es liegt nun am nächsten Pechvogel, der dachte, es wäre eine gute Idee, Bilder in einem S3-ähnlichen Objektspeicherdienst abzulegen, um das Problem zu lösen. Entschuldigung!

2 „Gefällt mir“

@CxV Da du das vorherige Migration als vollständig falsch durchgeführt und von vorne zu beginnen abgelehnt hast, bitte prüfe und merge diese Entfernung des Datenkorruptions-Fehlers:

2 „Gefällt mir“

Wie bereits erwähnt, bin ich bei der von mir durchgeführten Migration auf einige Probleme gestoßen. Dies stützt @cvxs Aussage, dass ich die Migration völlig falsch geschrieben habe, und solange niemand sie korrekt durchführt, sollte die Entfernung der bestehenden Migration, die voller stiller Datenkorruptionen ist, wirklich zusammengeführt werden. (Es ist ein sehr einfacher Patch, die Überprüfung sollte trivial sein. Je schneller er zusammengeführt wird, desto unwahrscheinlicher ist es, dass jemand seine Website zerstört, indem er versucht, durch eine Einwegtür rückwärts zu gehen. Ich weiß nicht, wie ich noch eindringlicher für eine Zusammenführung plädieren könnte; wenn ich es könnte, würde ich es tun. Edit: Danke @cvx für die Genehmigung, die Zusammenführung und das Follow-up, um sicherzustellen, dass die Massenmigration als irreversibel markiert ist.)

Hier sind die bekannten Probleme, auf die ich gestoßen bin:

  • Zumindest der Discobot-Avatar wurde nicht angezeigt; alle Discobot-Teilnahmen zeigten den generischen Personen-Avatar (hellgrauer Kopf und Schultern auf weißem Hintergrund).
  • Die Avatare einiger anderer Benutzer wurden nicht korrekt migriert. Viele wurden manuell behoben.
  • Während die Website konfiguriert wurde, experimentierte der ursprüngliche Administrator mit Änderungen an der „S3“-Konfiguration (in unserem Fall Digital Ocean Spaces, mit und ohne CDN), was zu einigen verwaisten optimierten Bildern führte, die bei der Migration nicht behoben wurden.

Für alle, die meinen Branch ausprobiert haben und dabei Bilder verloren haben, habe ich einen Hack in der Rails-Konsole ausgeführt, der einige Dinge behoben hat. Dies ist nicht der richtige Weg, dies zu tun; ich kenne das Modell einfach nicht gut genug, um es richtig zu machen. Mein Ruby-Wissen ist sehr schwach; ich berühre Ruby nicht außerhalb meiner kleinen Beiträge zu Discourse.

So wie es ist, hat dieser schreckliche Hack jedoch defekte Bilder (durch die anfänglichen Konfigurationsfehler) repariert und zumindest den Discobot-Avatar wiederhergestellt (und möglicherweise andere, aber alle, von denen ich zuvor wusste, waren bereits repariert).

Was hier nicht zu sehen ist, ist alles, was ich zwischen den Schritten getan habe, wobei ich jede Gruppe, während ich weiterging, betrachtet habe. Dies war Teil einer Session zum „Erkunden, was in der Rails-Konsole vorhanden ist“ und kein Skript, das ich geschrieben und ausgeführt habe. Es gibt keine Fehlerbehandlung, und ich habe vor Beginn dieser Arbeiten ein vollständiges Website-Backup erstellt.

Ich weiß nicht, wie ich deutlicher sagen soll, dass dieser Code nicht die idiomatische Ruby-on-Rails-Methode zur Reparatur ist. Ich wollte nur teilen, wie ich zumindest einen Teil des Schadens behoben habe, den ich mir bei meinem vorherigen Versuch zugefügt habe, meine Website von Digital Ocean Spaces zu migrieren.

require 'set'

uploadids = Set.new
optimizedimages = Set.new
OptimizedImage.where("url like '%UNIQUEPARTOFS3URL%'").each do |oi|
  uploadids.add(oi.upload_id)
  optimizedimages.add(oi)
end

postids = Set.new
uploadids.each do |u|
  PostUpload.where(upload_id: u).each do |pu|
    postids.add(pu.post_id)
  end
end

optimizedimages.each do |oi|
  oi.delete
end

postids.each do |pid|
  Post.where(id: pid).each do |p|
    p.rebake!
  end
end
2 „Gefällt mir“