Hallo, dieses Thema gibt einige Hintergrundinformationen zur Migration, die ich langsam plane und teste. Ich habe am vergangenen Freitag endlich den Drupal-Importer auf einem Test-VPS mit einer Kombination aus diesem und diesem ausprobiert. Der Importer läuft noch, während ich das hier tippe, daher konnte ich die Funktionalität der Testseite noch nicht wirklich testen, aber sie wird bald fertig sein.
Das größte Problem, mit dem ich konfrontiert bin, ist ein “duplicate key value” bei 8 scheinbar zufälligen Nodes (das Äquivalent von Themen in Discourse) von insgesamt ca. 80.000 Nodes. Hier sind die spezifischen nid-Nummern, falls es sich um einen seltsamen Y2K-ähnlichen mathematischen Fehler handelt:
42081, 53125, 57807, 63932, 66756, 76561, 78250, 82707
derselbe Fehler tritt immer bei denselben nids auf, wenn der Importer erneut ausgeführt wird:
Traceback (most recent call last):
19: from script/import_scripts/drupal.rb:537:in `<main>'
18: from /var/www/discourse/script/import_scripts/base.rb:47:in `perform'
17: from script/import_scripts/drupal.rb:39:in `execute'
16: from script/import_scripts/drupal.rb:169:in `import_forum_topics'
15: from /var/www/discourse/script/import_scripts/base.rb:916:in `batches'
14: from /var/www/discourse/script/import_scripts/base.rb:916:in `loop'
13: from /var/www/discourse/script/import_scripts/base.rb:917:in `block in batches'
12: from script/import_scripts/drupal.rb:195:in `block in import_forum_topics'
11: from /var/www/discourse/script/import_scripts/base.rb:224:in `all_records_exist?'
10: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activerecord-7.0.3.1/lib/active_record/transactions.rb:209:in `transaction'
9: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activerecord-7.0.3.1/lib/active_record/connection_adapters/abstract/database_statements.rb:316:in `transaction'
8: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activerecord-7.0.3.1/lib/active_record/connection_adapters/abstract/transaction.rb:317:in `within_new_transaction'
7: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
6: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
5: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'
4: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
3: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activerecord-7.0.3.1/lib/active_record/connection_adapters/abstract/transaction.rb:319:in `block in within_new_transaction'
2: from /var/www/discourse/script/import_scripts/base.rb:231:in `block in all_records_exist?'
1: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/pg.rb:56:in `exec'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/pg.rb:56:in `exec': ERROR: duplicate key value violates unique constraint "import_ids_pkey" (PG::UniqueViolation)
DETAIL: Key (val)=(nid:42081) already exists.
20: from script/import_scripts/drupal.rb:537:in `<main>'
19: from /var/www/discourse/script/import_scripts/base.rb:47:in `perform'
18: from script/import_scripts/drupal.rb:39:in `execute'
17: from script/import_scripts/drupal.rb:169:in `import_forum_topics'
16: from /var/www/discourse/script/import_scripts/base.rb:916:in `batches'
15: from /var/www/discourse/script/import_scripts/base.rb:916:in `loop'
14: from /var/www/discourse/script/import_scripts/base.rb:917:in `block in batches'
13: from script/import_scripts/drupal.rb:195:in `block in import_forum_topics'
12: from /var/www/discourse/script/import_scripts/base.rb:224:in `all_records_exist?'
11: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activerecord-7.0.3.1/lib/active_record/transactions.rb:209:in `transaction'
10: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activerecord-7.0.3.1/lib/active_record/connection_adapters/abstract/database_statements.rb:316:in `transaction'
9: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activerecord-7.0.3.1/lib/active_record/connection_adapters/abstract/transaction.rb:317:in `within_new_transaction'
8: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
7: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
6: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'
5: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
4: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activerecord-7.0.3.1/lib/active_record/connection_adapters/abstract/transaction.rb:319:in `block in within_new_transaction'
3: from /var/www/discourse/script/import_scripts/base.rb:243:in `block in all_records_exist?'
2: from /var/www/discourse/script/import_scripts/base.rb:243:in `ensure in block in all_records_exist?'
1: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/pg.rb:56:in `exec'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/pg.rb:56:in `exec': ERROR: current transaction is aborted, commands ignored until end of transaction block (PG::InFailedSqlTransaction)
Der einzige Weg, wie ich ihn weitermachen konnte, war durch Hacking der SQL-Bedingungen:
...
LEFT JOIN node_counter nc ON nc.nid = n.nid
WHERE n.type = 'forum'
AND n.status = 1
AND n.nid != 42081
AND n.nid != 53125
AND n.nid != 57807
AND n.nid != 63932
AND n.nid != 66756
AND n.nid != 76561
AND n.nid != 78250
AND n.nid != 82707
LIMIT #{BATCH_SIZE}
OFFSET #{offset};
...
Ich habe den ersten fehlgeschlagenen Node sowie die vorherigen und nächsten nids auf beiden Seiten im Quell-Drupal-Datenbank untersucht und kann nichts Falsches erkennen. Der nid ist als Primärschlüssel gesetzt und hat AUTO_INCREMENT, und die ursprüngliche Drupal-Seite funktioniert einwandfrei, sodass es kein grundlegendes Problem mit der Integrität der Quelldatenbank geben kann.
Abgesehen von dem oben genannten Fehler sind dies die Einschränkungen, die ich mit dem Skript habe:
-
Permalinks: Es scheint, dass das Importer-Skript Permalinks für die ehemaligen Node-URLs
example.com/node/XXXXXXXerstellt. Ich muss aber auch Links zu bestimmten Kommentaren innerhalb dieser Nodes beibehalten, die das Format haben:example.com/comment/YYYYYYY#comment-YYYYYYY(YYYYYYYist in beiden Fällen gleich). Das Drupal-URL-Schema enthält nicht die Node-ID, mit der der Kommentar verknüpft ist, während Discourse dies tut (example.com/t/topic-keywords/XXXXXXX/YY), was eine große Komplikation darstellt. -
Benutzername-Beschränkungen: Drupal erlaubt Leerzeichen in Benutzernamen. Ich verstehe, dass Discourse dies nicht tut, zumindest erlaubt es neuen Benutzern nicht, sie auf diese Weise zu erstellen. Dieser Beitrag deutet darauf hin, dass das Importer-Skript die problematischen Benutzernamen automatisch “konvertiert”, aber ich kann keinen Code dafür inUpdate: Tatsächlich scheint es, dass Discourse dies automatisch und korrekt gehandhabt hat./import_scripts/drupal.rbfinden. -
Gesperrte Benutzer: Es scheint, dass das Skript alle Benutzer importiert, einschließlich gesperrter Konten. Ich könnte wahrscheinlich recht einfach eine Bedingung zur SQL-Auswahl
WHERE status = 1hinzufügen, um nur aktive Benutzerkonten zu importieren, aber ich bin mir nicht sicher, ob dies Probleme mit der Serialisierung der Datensätze verursachen würde. Vor allem möchte ich diese zuvor gesperrten Kontonamen mit ihren zugehörigen E-Mail-Adressen dauerhaft blockiert halten, damit dieselben problematischen Benutzer sich nicht erneut auf Discourse anmelden. -
Benutzerprofilfelder: Weiß jemand, ob es in einem anderen Importer Beispielcode zum Importieren von persönlichen Informationsfeldern aus Benutzerprofilen gibt? Ich habe nur ein Profilfeld (“Standort”), das ich importieren muss.
-
Avatare (nicht Gravatars): Es erscheint etwas seltsam, dass im Drupal-Importer Code zum Importieren von Gravataren vorhanden ist, aber nicht für die weitaus häufiger verwendeten lokalen Avatarbilder.
-
Private Nachrichten: Fast alle Drupal 7-Foren werden wahrscheinlich das Drittanbieter-Modul privatemsg verwenden (es gibt keine offizielle Drupal PM-Funktionalität). Der Importer unterstützt den Import von PMs nicht. In meinem Fall muss ich etwa 1,5 Millionen davon importieren.
Vielen Dank im Voraus für Ihre Hilfe und dafür, dass Sie das Drupal-Importer-Skript zur Verfügung gestellt haben.




