Migrate a phpBB3 forum to Discourse

phpBBフォーラムを既存のDiscourseフォーラムにインポートしてマージすることは可能ですか?カテゴリのマッピングに関する設定に基づいていると仮定します。

注意すべき問題はありますか?

同じメールアドレスを持つユーザーはマージされますか?

「いいね!」 1

はい。設定ファイルで独自のカテゴリマッピングを行わない場合、インポート中に必要に応じて新しいカテゴリが作成されます。phpBBのカテゴリ名と一致する既存のDiscourseカテゴリがある場合、カテゴリはマージされます。

はい、あります。私が遭遇したことを詳述したスレッドはこちらです。いくつかヒントと、インポーターの結合されたアップデートを含むリポジトリがあります。

正確な条件は覚えていませんが、はい、ユーザーはインポート中に自動的にマージされます。

「いいね!」 2

phpbb3フォーラムをDiscourseにマージして、インポートされたすべてのトピックを読み取り専用にすることは可能かどうか、興味があります。スレッドを検索しましたが、これについては言及されていませんでした。よろしくお願いします。

インポートスクリプトを変更して、作成されたすべてのトピックをアーカイブすることもできます。または、スクリプト実行後に一括処理する方が簡単な場合もあります。例については、Administrative Bulk Operations を参照してください。

「いいね!」 2

こんにちは。

インポーターの起動時に問題が発生しているようです。ユーザーのインポート中、またはその直後に発生しているようです。スタックトレースと、出力の20秒程度の短いビデオを添付しました。

アドバイスをお願いします。

0x00007fe87a88bb10 /var/www/discourse/script/import_scripts/phpbb3/importers/user_importer.rb:87}
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.7/lib/active_record/validations.rb:80:in `raise_validation_error': Validation failed: Name can't be blank (ActiveRecord::RecordInvalid)
        from /var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.7/lib/active_record/validations.rb:53:in `save!'
        from /var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.7/lib/active_record/transactions.rb:302:in `block in save!'
        from /var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.7/lib/active_record/transactions.rb:354:in `block in with_transaction_returning_status'
        from /var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.7/lib/active_record/connection_adapters/abstract/database_statements.rb:314:in `transaction'
        from /var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.7/lib/active_record/transactions.rb:350:in `with_transaction_returning_status'
        from /var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.7/lib/active_record/transactions.rb:302:in `save!'
        from /var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.7/lib/active_record/suppressor.rb:54:in `save!'
        from /var/www/discourse/script/import_scripts/base.rb:361:in `block in create_user'
        from /var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.7/lib/active_record/connection_adapters/abstract/transaction.rb:319:in `block in within_new_transaction'
        from /var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activesupport-7.0.7/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
        from /var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activesupport-7.0.7/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'
        from /var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activesupport-7.0.7/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
        from /var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activesupport-7.0.7/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
        from /var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.7/lib/active_record/connection_adapters/abstract/transaction.rb:317:in `within_new_transaction'
        from /var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.7/lib/active_record/connection_adapters/abstract/database_statements.rb:316:in `transaction'
        from /var/www/discourse/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.7/lib/active_record/transactions.rb:209:in `transaction'
        from /var/www/discourse/script/import_scripts/base.rb:360:in `create_user'
        from /var/www/discourse/script/import_scripts/base.rb:278:in `block in create_users'
        from /var/www/discourse/vendor/bundle/ruby/3.2.0/gems/rack-mini-profiler-3.1.1/lib/patches/db/mysql2/alias_method.rb:8:in `each'
        from /var/www/discourse/vendor/bundle/ruby/3.2.0/gems/rack-mini-profiler-3.1.1/lib/patches/db/mysql2/alias_method.rb:8:in `each'
        from /var/www/discourse/script/import_scripts/base.rb:266:in `create_users'
        from /var/www/discourse/script/import_scripts/phpbb3/importer.rb:106:in `block in import_anonymous_users'
        from /var/www/discourse/script/import_scripts/base.rb:948:in `block in batches'
        from /var/www/discourse/script/import_scripts/base.rb:947:in `loop'
        from /var/www/discourse/script/import_scripts/base.rb:947:in `batches'
        from /var/www/discourse/script/import_scripts/phpbb3/importer.rb:293:in `batches'
        from /var/www/discourse/script/import_scripts/phpbb3/importer.rb:102:in `import_anonymous_users'
        from /var/www/discourse/script/import_scripts/phpbb3/importer.rb:33:in `execute'
        from /var/www/discourse/script/import_scripts/base.rb:47:in `perform'
        from /var/www/discourse/script/import_scripts/phpbb3/importer.rb:22:in `perform'
        from script/import_scripts/phpbb3.rb:35:in `<module:PhpBB3>'
        from script/import_scripts/phpbb3.rb:16:in `<module:ImportScripts>'
        from script/import_scripts/phpbb3.rb:15:in `<main>'

編集:
匿名ユーザーに関連しているようです。データベースを確認してみます。

 def map_anonymous_user(row)
      username = row[:post_username]

      {
        id: @settings.prefix(username),
        email: "anonymous_#{SecureRandom.hex}@no-email.invalid",
        username: username,
        name: @settings.username_as_name ? username : "",
        created_at: Time.zone.at(row[:first_post_time]),
        active: true,
        trust_level: TrustLevel[0],
        approved: true,
        approved_by_id: Discourse.system_user.id,
        approved_at: Time.now,
        post_create_action:
          proc do |user|
            row[:user_inactive_reason] = Constants::INACTIVE_MANUAL
            row[:ban_reason] = "Anonymous user from phpBB3" # TODO i18n
            suspend_user(user, row, true)
          end,
      }
    end

編集
map_anonymous_userメソッドのこの行を変更することで、エラーを回避することができました。デフォルトではユーザー名を空文字列に設定していたため、単語を追加しました。

これを変更しました

name: @settings.username_as_name ? username : "",

これを変更しました

name: @settings.username_as_name ? username : "Anonymous ",
「いいね!」 3

インクリメンタルインポートを実行する前に、古い投稿を削除してもよいですか?開発環境にインポートを正常に実行し、Dockerインストールを実行しているサーバーに復元しました。サーバーで新しい投稿のインポートを実行する予定です。しかし、すでにインポートされた投稿を無視しても、サーバーでのインポートには数時間かかります。私のフォーラムはかなり大きく(130万件の投稿)、サーバーのディスクは遅いため、.sqlファイルをロードするだけで数時間かかります。

ローカルで DELETE FROM phpbb_posts WHERE post_id < 2926807 のようなことを実行してから、それをサーバーにダンプしてアップロードし、通常どおりインポートを実行すると問題が発生しますか?

一部のスクリプトに IMPORT_AFTER 設定を追加し、特定の日付以降のデータのみを取得するようにしました。そのため、投稿を取得する SQL を、最後のデータダンプの1日前以降のものを取得するように変更します。

しかし、ディスクの速度が非常に遅い場合、Discourse のホスティングに問題が発生する可能性が高いです。現在お持ちのデータでパフォーマンスは許容範囲内ですか?

「いいね!」 1

はい、通常の利用ではより高速なディスクを使用しますが、データベースのコピーを同時に複数ホストするには十分な大きさではないため、import.yml の volumes セクションで /shared/import をより大きく低速なディスクにルーティングしています。このトリックは最初のバックアップの復元にはうまくいきましたが、18G の空き容量と 6G のデータベースがあるにもかかわらず、スペース不足で復元が失敗したため、復元後に /shared/tmp を低速ディスクにリルーティングしました(復元中にデータベースのコピーが 3 つ作成されるとどこかで言及されていたかと思います)。しかし、その段階ではダウンタイムは問題ではありませんでした。

そのため、日常的にはサイズも速度も問題ありません。私のフォーラムはかなり静かで、古いだけです。

スクリプトの SQL を変更してみます。ありがとうございます!

「いいね!」 2

settings.yml の MySQL 接続内容は以下の通りです。


データベース名はどこに入力すればよいですか?

データベース名は schema パラメータに入力する必要があります。そのパラメータ名は少し紛らわしいですね。コードのこちらで、データベース名として渡されていることが確認できます。

「いいね!」 2

https://www.loom.com/share/1f66315779af4cf7b286c8541d4f3f09

こんにちは!インポートで発生している問題について、簡単なビデオを作成しました。約65万件の投稿を移行しています。

ありがとうございます!

https://www.loom.com/share/1f66315779af4cf7b286c8541d4f3f09?sid=11a46d3c-8510-43a1-82e9-1a3524cbb365

こんにちは。行ごとにインポートを実行する方法はありますか。スクリプトが完了しないという問題が発生しています。ユーザーやアバターなど、一部は機能しますが、他のものは機能しません。インポートエラー後にクリーンインストールが必要だとどこかで読んだため、サーバーを約4回再イメージしました。

その他の詳細は、投稿したビデオに記載されています。どのような支援でも感謝いたします。

こんにちは。移行を開始してから約18時間経ちましたが、移行を機能させるには何も進んでいません。私のビデオを見て、何かヒントやコツがあるか、または設定に不足しているものがないかアドバイスをいただけますでしょうか。投稿、トピック、プライベートメッセージ、カテゴリが必要です。アバターとユーザーは機能しています。サーバーはクリーンなUBUNTU 22.04です。

より簡単な解決策は、サイトを作成した後にバックアップを作成し、それを復元できるようにすることです。クリーンなデータベースを取得する別の方法は、rake db:drop db:create db:migrate を実行することですが、それを可能にするにはいくつかのことを行う必要があります。エラーメッセージからそれらを推測できない場合は、バックアップ/復元ソリューションが最善の方法であり、いずれにしてもより速いかもしれません。

デバッグ用の puts ステートメントを追加できますが、phpbb3 スクリプトの構造は、Ruby をよく知らない人には少し混乱する可能性があります。

また、スクリプトを複数回実行すると、すでに完了した項目はスキップされるため、データベースを完全に消去する必要はありません。ただし、インポート済みのデータに対して異なる処理が必要になるような変更を加えた場合は、消去が必要になる場合があります。

それは無料では対応できません。予算がある場合は、直接連絡するか、Marketplace に投稿してください。

インポートスクリプトが機能していないようです。問題はビデオにあります。ディスコース移行チームの誰かが調査できれば幸いです。

サポートが有料の場合、移行の費用をリストしていただけますか?これはスクリプトの動作方法に関する質問をする場所だと理解していました。料金については問題ありません。これはオープンソースプロジェクトであり、質問をする場所だと思っていました。

私はボランティアであり、不合理なビデオ嫌いのせいで、無料のビデオを見るつもりはないと言っています。しかし、私だけではありません。多くの人がビデオを見るのが好きです。

つまり、実行するたびに、以前の実行で作成されたユーザーの重複が作成されるということですか?どうしてそんなことが起こるのか想像もできません。本当ですか?それは本来の動作ではありません。

インポートされたものは再度インポートされているように見えますが、インポートされたものにはすでに import_id カスタムフィールドが設定されており、再度インポートされないようになっているため、実際には何もしていないので、はるかに高速です。実行ごとにデータが重複している場合、非常に奇妙な問題が発生しています。

そうです。時には、無料では得られない以上の助けが必要な場合や、助けを求めている場合があります。

「いいね!」 2

承知いたしました。移行の料金を教えていただけますでしょうか。スクリプトが機能しないようで、有料サポートが必要であると理解しております。それは全く問題ありません。

「いいね!」 1

移行は非常に複雑です。フォーラムのデータはそれぞれユニークであるため、すべての移行には異なる課題があります。移行の問題のデバッグには時間がかかり、ログ、データベース、コードなどを詳細に調べる必要があります。これらの投稿を見ただけで行うのは難しいため、あまりお役に立てず申し訳ありません!こちらが移行に関するFAQです:Migrating to Discourse | Discourse - Civilized Discussion

リンクをありがとうございます。問題が解決したようで、インポートスクリプトが現在実行されています。現在、100000/666357件の投稿を処理中です。Chat GPTは、権限関連のエラーなどの特定に役立ちました。

「いいね!」 2