Решил быстро написать пост о том, как мы мигрировали наш форум с 25 000+ участников и 250 000+ сообщений с Flarum на Discourse.
Как вы, наверное, знаете, читая это, официального скрипта импорта из Flarum в Discourse нет. Однако @koen360 любезно поделился своей работой по модификации импортера FluxBB для переноса пользователей. Но нам также нужно было импортировать сообщения, поскольку значительная часть успеха нашего форума зависит от того, что пользователи ищут очень специфические термины, встречающиеся в постах. Вот что мы и сделали — после нескольких часов неудачных миграций, головной боли и некоторой кровопотери.
Я отнюдь не эксперт в написании скриптов миграции, но этот скрипт работает достаточно хорошо для текущей версии Flarum на момент написания (V0.1.0-beta.16). Скрипт (прикреплен ниже) потребует доступа к вашей базе данных MySQL/MariaDB, желательно к её копии, чтобы не повредить рабочую среду в случае сбоя. Просто замените тестовые значения в подключении к MySQL, и всё будет готово.
Обязательно сделайте полную резервную копию базы данных Flarum перед началом этого процесса. Если что-то пойдет не так, это, скорее всего, будет необратимо.
Если вам нужна помощь с миграцией с Flarum на Discourse, не стесняйтесь ответить в этой теме. Я не эксперт, но постараюсь помочь чем смогу.
Спасибо за создание скрипта, @Lecter! Можешь отправить его как PR в discourse/discourse? У нас пока нет скрипта для Flarum, поэтому это было бы полезно иметь в качестве основы.
Это отлично, спасибо за то, что вы продвинули этот импортер на новый уровень! Надеюсь, со временем его можно будет расширить, добавив поддержку тегов, а в идеале — вложений.
Насколько сложно будет добавить поддержку тегов? Я вижу, что в vBulletin 5 и, возможно, в нескольких других системах есть примеры того, как это работает, но я не знаю, насколько сильно это нужно будет адаптировать для Flarum. Спасибо за любые пояснения, которые кто-либо сможет дать, и не переживайте, если на этот вопрос невозможно ответить, не приступив к работе.
Кто-нибудь может помочь мне с миграцией, пожалуйста?
У меня установлен Discourse с пустыми постами и тремя категориями по умолчанию.
Когда я попытался импортировать SQL из Flarum в Discourse, получил эту ошибку:
su discourse -c 'bundle exec ruby script/import_scripts/flarum_import.rb'
Загрузка существующих групп...
Загрузка существующих пользователей...
Загрузка существующих категорий...
Загрузка существующих постов...
Загрузка существующих тем...
Создание пользователей
13 / 13 (100.0%) [281 элементов/мин] n]
Импорт категорий верхнего уровня...
39 / 39 (100.0%) [420 элементов/мин] n]
Импорт дочерних категорий...
39 / 39 (100.0%) [290 элементов/мин]
Создание тем и постов
Traceback (most recent call last):
19: from script/import_scripts/flarum_import.rb:162:in `<main>'
18: from /var/www/discourse/script/import_scripts/base.rb:47:in `perform'
17: from script/import_scripts/flarum_import.rb:32:in `execute'
16: from script/import_scripts/flarum_import.rb:101:in `import_posts'
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/flarum_import.rb:122:in `block in import_posts'
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/lib/active_record/transactions.rb:209:in `transaction'
9: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activerecord-7.0.3/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/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/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/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/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/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/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': ОШИБКА: дублирующееся значение ключа нарушает уникальное ограничение "import_ids_pkey" (PG::UniqueViolation)
ДЕТАЛИ: Ключ (val)=(7) уже существует.
20: from script/import_scripts/flarum_import.rb:162:in `<main>'
19: from /var/www/discourse/script/import_scripts/base.rb:47:in `perform'
18: from script/import_scripts/flarum_import.rb:32:in `execute'
17: from script/import_scripts/flarum_import.rb:101:in `import_posts'
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/flarum_import.rb:122:in `block in import_posts'
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/lib/active_record/transactions.rb:209:in `transaction'
10: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activerecord-7.0.3/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/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/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/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/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/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/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': ОШИБКА: текущая транзакция прервана, команды игнорируются до конца блока транзакции (PG::InFailedSqlTransaction)
Проблема заключается в Ключ (val)=(7) уже существует.
`exec': ОШИБКА: дублирующееся значение ключа нарушает уникальное ограничение "import_ids_pkey" (PG::UniqueViolation)
ДЕТАЛИ: Ключ (val)=(7) уже существует.
root@raspberrypi-app:/var/www/discourse# rake db:validate_indexes
Запуск postgres на порту: 11000
Ожидание запуска сервера PG...
Сервер PG готов, база данных загружена
Выполнение миграций на пустой базе данных!
Проверка индексов в базе данных по умолчанию
Отсутствующих индексов нет
Лишних индексов нет
ubuntu@ip-172-26-1-78:~/discourse$ bundle exec ruby script/import_scripts/flarum_import.rb
Загрузка существующих групп...
Загрузка существующих пользователей...
Загрузка существующих категорий...
Загрузка существующих постов...
Загрузка существующих тем...
создание пользователей
Пропущено 1000 уже импортированных пользователей
Пропущено 826 уже импортированных пользователей
импортирование категорий верхнего уровня...
34 / 34 (100.0%) [5728165 элементов/мин]
импортирование дочерних категорий...
34 / 34 (100.0%) [3194 элемента/мин]
создание тем и постов
Traceback (most recent call last):
19: from script/import_scripts/flarum_import.rb:162:in `<main>'
18: from /home/ubuntu/discourse/script/import_scripts/base.rb:47:in `perform'
17: from script/import_scripts/flarum_import.rb:32:in `execute'
16: from script/import_scripts/flarum_import.rb:101:in `import_posts'
15: from /home/ubuntu/discourse/script/import_scripts/base.rb:916:in `batches'
14: from /home/ubuntu/discourse/script/import_scripts/base.rb:916:in `loop'
13: from /home/ubuntu/discourse/script/import_scripts/base.rb:917:in `block in batches'
12: from script/import_scripts/flarum_import.rb:122:in `block in import_posts'
11: from /home/ubuntu/discourse/script/import_scripts/base.rb:224:in `all_records_exist?'
10: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activerecord-7.0.3.1/lib/active_record/transactions.rb:209:in `transaction'
9: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activerecord-7.0.3.1/lib/active_record/connection_adapters/abstract/database_statements.rb:316:in `transaction'
8: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activerecord-7.0.3.1/lib/active_record/connection_adapters/abstract/transaction.rb:317:in `within_new_transaction'
7: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
6: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
5: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/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 /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
3: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/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 /home/ubuntu/discourse/script/import_scripts/base.rb:231:in `block in all_records_exist?'
1: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/pg.rb:56:in `exec'
/home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/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)=(53) already exists.
20: from script/import_scripts/flarum_import.rb:162:in `<main>'
19: from /home/ubuntu/discourse/script/import_scripts/base.rb:47:in `perform'
18: from script/import_scripts/flarum_import.rb:32:in `execute'
17: from script/import_scripts/flarum_import.rb:101:in `import_posts'
16: from /home/ubuntu/discourse/script/import_scripts/base.rb:916:in `batches'
15: from /home/ubuntu/discourse/script/import_scripts/base.rb:916:in `loop'
14: from /home/ubuntu/discourse/script/import_scripts/base.rb:917:in `block in batches'
13: from script/import_scripts/flarum_import.rb:122:in `block in import_posts'
12: from /home/ubuntu/discourse/script/import_scripts/base.rb:224:in `all_records_exist?'
11: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activerecord-7.0.3.1/lib/active_record/transactions.rb:209:in `transaction'
10: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activerecord-7.0.3.1/lib/active_record/connection_adapters/abstract/database_statements.rb:316:in `transaction'
9: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activerecord-7.0.3.1/lib/active_record/connection_adapters/abstract/transaction.rb:317:in `within_new_transaction'
8: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
7: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
6: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/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 /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
4: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/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 /home/ubuntu/discourse/script/import_scripts/base.rb:243:in `block in all_records_exist?'
2: from /home/ubuntu/discourse/script/import_scripts/base.rb:243:in `ensure in block in all_records_exist?'
1: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/pg.rb:56:in `exec'
/home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/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)