Discourse Retort

リタートプラグインが原因で Discourse を更新できませんでした。

表示されたデータベース移行エラーは次のとおりです。

一意インデックス "index_post_details_on_post_id_and_key_ccnew_ccnew" を作成できませんでした。 DETAIL: Key (post_id, key)=(30297, +1|retort) は重複しています。

このスクリプトを独自の移行コードのベースとして使用しました。以下に私が実行した手順を示します。

  • Discourse を再び機能させるために、テンプレートの .yml ファイルの「version」を、Discourse リポジトリの約 2 週間前のコミットにオーバーライドする必要がありました。
  • 反応プラグインを追加して再構築し、サイトを復旧させました。
  • リタートと同じ反応セットで反応プラグインを構成しました。いいねと解釈される可能性のある反応は使用していません。
  • @mcdanlj のスクリプトを少し変更して、次の手順で使用しました(すべてのリタートを移行したかったため、リタートと反応の間に 1 対 1 のマッピングがすでにありました)。
  • ./launcher enter app を実行します。
  • rails c を実行します。
  • 次のコードを貼り付けます(Rails コンソールはコードを不正確な行変更でエコーバックするようです。二重の行変更を追加しましたが、出力は実際には変更されませんでした。ただし、次のコードで構文エラーが発生した場合は、各行の後に 1 行追加してください)。
def migrateRetortToReactions()
  retort = "retort".freeze
  emojiType = "emoji".freeze
  usermap = Hash.new { |hash, username| hash[username] = User.find_by_username(username) }
  postmap = Hash.new { |hash, post_id| hash[post_id] = Post.find(post_id) }
  likeType = PostActionType.where(name_key: "like").pluck(:id).first
  PostDetail.where(extra: retort).each do |pd|
    begin
      p = postmap[pd.post_id]
    rescue
      # PostDetail が削除と一致しない
      $stderr.puts sprintf("投稿が見つかりませんでした %d: %s / %s", pd.post_id, pd.key, pd.value)
      next
    end

    emoji = pd.key.split('|').first
    users = JSON.parse(pd.value)
    users.each do |user|
      u = usermap[user]
      next if u.nil? # ユーザー名が変更されたか、削除されたユーザーが孤立したリタートを残す
      e = emoji
      r = DiscourseReactions::Reaction.where(post_id: p.id, reaction_type: emojiType, reaction_value: e).first_or_create
      ru = DiscourseReactions::ReactionUser.where(user_id: u.id, post_id: p.id).first
      next unless ru.nil?
      $stderr.puts sprintf("リタート %s をユーザー %s の投稿 %s のリアクション %s に変換中", emoji, e, user, p.url)
      DiscourseReactions::ReactionUser.create(reaction_id: r.id, user_id: u.id, post_id: p.id, created_at: pd.created_at)
    end
  end
end
  • この時点で、念のためサイトのバックアップを作成しました。
  • 次に migrateRetortToReactions を実行します。これには時間がかかるはずです。私の場合、問題は見られず、遭遇しませんでした。コンソールを実行すると、変更されたすべてのオブジェクトが表示されるため、q を押して終了します。
  • これで、サイトのデータが正しく移行されているはずです。
  • 最後のステップとして、PostDetail.where(extra: "retort").destroy_all を実行して、リタートデータを削除する必要があります。
  • これで、最新の Discourse バージョンで、リタートプラグインなしでサイトを再構築できるようになりました。

全体として、移行はそれほど難しくはありませんでしたが、かなり恐ろしいものでした。前述のように、同じユーザーが投稿に「いいね」と「リタート」の両方を行っていた場合、これは「いいね」をリアクションで上書きします。

「いいね!」 6