こんにちは。このトピックは、私がゆっくりと計画とテストを進めている移行の背景情報を提供しています。このとこのを組み合わせて、先週金曜日にテスト環境のVPSでDrupalインポーターを試しました。インポーターは私がこれを書いている間も実行中なので、テストサイトの実際の機能はまだテストできていませんが、もうすぐ完了します。
私が直面している最大の課題は、約80,000ノード(Discourseのトピックに相当)のうち、8つのランダムに見えるノードでの「重複キー値」エラーです。念のため、Y2Kのような奇妙な数学的バグが関与している可能性も考慮して、問題のnid番号を以下に示します。
42081, 53125, 57807, 63932, 66756, 76561, 78250, 82707
インポーターを再実行すると、常に同じnidで同じエラーが発生します。
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)
SQL条件をハッキングすることでしか進行させることができませんでした。
...
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};
...
最初の失敗したノードと、その前後のnidをソースDrupalデータベースで調べましたが、問題は見つかりませんでした。nidは主キーとして設定されており、AUTO_INCREMENTが付いています。元のDrupalサイトは正常に動作しているので、ソースデータベースの整合性に根本的な問題はないはずです。
上記のバグを除けば、スクリプトで直面している制限は以下の通りです。
-
パーマリンク: インポーター スクリプトは、以前のノード URL
example.com/node/XXXXXXXのパーマリンクを作成するようです。しかし、これらのノード内の特定のコメントへのリンクも維持する必要があります。その形式はexample.com/comment/YYYYYYY#comment-YYYYYYYです(YYYYYYYは両方の箇所で同じです)。Drupal の URL スキームには、コメントが関連付けられているノード ID が含まれていませんが、Discourse には含まれています (example.com/t/topic-keywords/XXXXXXX/YY)。これは大きな複雑さをもたらすようです。 -
ユーザー名制限: Drupal ではユーザー名にスペースを含めることができます。Discourse では、少なくとも新しいユーザーがそのように作成することはできないと理解しています。この投稿では、インポーター スクリプトが問題のあるユーザー名を自動的に「変換」すると示唆されていますが、更新: 実際には、Discourse がこれを自動的に正しく処理したようです。/import_scripts/drupal.rbにそのコードは見当たりません。 -
禁止ユーザー: スクリプトは、禁止されているアカウントを含むすべてのユーザーをインポートするようです。SQL の選択条件に
WHERE status = 1を追加して、アクティブなユーザーアカウントのみをインポートするように簡単に条件を追加できるかもしれませんが、それがレコードのシリアライゼーションに問題を引き起こすかどうかはわかりません。何よりも、以前禁止されていたアカウント名を、関連するメールアドレスとともに永久にブロックし、同じ問題のあるユーザーが Discourse で再度サインアップしないようにしたいと考えています。 -
ユーザープロファイルフィールド: 個人情報フィールドをユーザープロファイルからインポートする例が、他のインポーターにあるかどうか、どなたかご存知ですか?インポートする必要があるプロファイルフィールドは「場所」の1つだけです。
-
アバター(Gravatar以外): Drupal インポーターに Gravatar をインポートするコードがあり、より一般的に使用されているローカルアカウントのアバター画像用のコードがないのは奇妙な気がします。
-
プライベートメッセージ: ほとんどの Drupal 7 フォーラムでは、サードパーティのprivatemsgモジュールを使用していると思われます(公式のDrupal PM機能はありません)。インポーターは PM のインポートをサポートしていません。私の場合は、約150万件の PM をインポートする必要があります。
ご協力と Drupal インポーター スクリプトの提供に感謝いたします。




