リビルド中にエラーを引き起こすプラグイン

本日、Discourseのインストールを2.9.0.beta9から2.9.0.beta10にアップグレードしようとしましたが、ひどく失敗しました。

  1. 最初の試みはコンソールで行いました。
cd /var/discourse
sudo git pull
sudo ./launcher rebuild app

これは最終的に、ログの途中で以下のメッセージとともに中断しました。

PG::InvalidParameterValue: ERROR:  cannot extract elements from a scalar
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/pg.rb:110:in `exec'

古いイメージ(まだ残っていました)を起動することで、フォーラムを簡単に復元できました。

  1. 2番目の試みはWebコンソール(/admin/upgrade)経由で行いました。しかし、これも最終的に同じ種類のエラー「ERROR: cannot extract elements from a scalar」で詰まってしまいました。アップグレードパネルに戻ると、すべてのコンポーネントが正常に更新されたと表示されていました。しかし、コンテナを再起動した後、サーバーはHTTP 500エラーを発生させました:frowning_face:

  2. 別のマシンにクリーンインストールし、ゼロから始めました。beta10バージョンをインストールできましたが、バックアップから復元しようとすると、まったく同じエラーが発生しました!

どなたか助けていただける方はいらっしゃいますか?

それが原因で遅延が発生しているクエリを見つけました

INSERT INTO question_answer_votes (post_id, user_id, created_at)
	SELECT
	  X.post_id AS post_id,
	  (X.value->>'user_id')::int AS user_id,
	  (X.value->>'created_at')::timestamp AS created_at
	FROM (
	  SELECT
	    post_id,
	    jsonb_array_elements(value::jsonb) AS value
	  FROM post_custom_fields WHERE name = 'vote_history'
	) AS X
	WHERE (X.value->>'action') != 'destroy'
	ORDER BY (X.value->>'created_at')::timestamp DESC
	ON CONFLICT DO NOTHING

私の理解が正しければ、これはpsql関数 jsonb_array_elements が配列を期待しているのに NULL 値を受け取るために発生します。

これに関する報告がいくつかあります。

以前にPavilion Question/Answerプラグインがインストールされていたことが原因かもしれません。

誰かに詳しく見てもらえるか確認します。:+1:

このプラグインを使用しています: https://github.com/angusmcleod/discourse-question-answer

  • これは Pavilion Question and Answer プラグインに関連しているようです。
  • これは discourse/discourse-upvotes プラグインからのフォークです。
「いいね!」 1

確認ですが、app.yml にはどのプラグインがありますか?

「いいね!」 1

見たサイトには、エンコードが何度も繰り返されて使用不能になった文字列を持つ、そのようなカスタム投稿フィールドがたくさんありました。

いくつかの解決策(複雑な順):

  • プラグインの使用をやめる(そしておそらく新しいアップボートに切り替える)
  • すべて削除する
  • 不良なものを削除する
  • それらのフィールドを編集して、データを有効なJSON文字列に戻す。

見たサイトには、何年も前の不正なデータがありました。これは、何年も前に存在したバグが、今になって発見されたようです。

壊れたJSON文字列を修正するコードを書くことは可能かもしれませんが、10分ではその方法を見つけることができませんでした。

例については Question Answer Plugin - #301 by pfaffman を参照してください。

「いいね!」 2

私もそう思いましたが、Angusのフォークで簡単に確認したところ、データ移行は行われていないようです。 https://github.com/angusmcleod/discourse-question-answer/compare/main...discourse:discourse-upvotes:main

これは、あなたが言ったように、古いQ&A投稿からのデータ汚染のように感じます。また、この移行は2021年11月のものであるにもかかわらず、これが今になって現れるのは面白いです。JayJayが新しいプラグインに切り替えるのが今だからでしょうか?いずれにせよ、その移行をもう一度確認します。

「いいね!」 1
          - git clone https://github.com/discourse/docker_manager.git
          - git clone https://github.com/discourse/discourse-solved.git
          - git clone https://github.com/unfoldingWord-dev/discourse-mermaid.git
          - git clone https://github.com/angusmcleod/discourse-question-answer.git
          - git clone https://github.com/discourse/discourse-checklist.git
          - git clone https://github.com/discourse/discourse-cakeday.git
          - git clone https://github.com/discourse/discourse-canned-replies.git
          - git clone https://github.com/discourse/discourse-footnote.git
          - git clone https://github.com/discourse/discourse-staff-notes.git
          - git clone https://github.com/discourse/discourse-graphviz.git
          - git clone https://github.com/discourse/discourse-assign.git
          - git clone https://github.com/discourse/discourse-voting.git
          - git clone https://github.com/discourse/discourse-yearly-review.git
          - git clone https://github.com/discourse/discourse-saved-searches.git

「いいね!」 1

@nat 新しいプラグインには全く切り替えるつもりはありません。これまで使用してきたプラグインのセットで運用を続けます。

少なくとも毎月アップデートを実行しているので、バージョン間に大きなギャップがあるわけではありません。

「いいね!」 2

質問と回答の問題とは別に、ちょっとした「FYI」として、定型返信の代替機能も追加されました。

また、公式のMermaidテーマコンポーネントも追加されたと思います。

「いいね!」 1

ありがとうございます。元の問題が解決したら、それも確認します :smile:

「いいね!」 1

プラグインを削除した場合、バックアップを復元しても問題のあるクエリは実行されたままになります。
そのため、プラグインと、そのプラグインが使用するテーブルとクエリの両方を削除する必要があります。
関係するテーブルをどのように特定すればよいでしょうか?

プラグインの行をコメントアウトし、再構築して確認しましたか?

「いいね!」 2

それを今試してみます。バックアップの一部である dump.sql ファイルを確認しましたが、question_answer_* テーブルに関する言及は一切ありません。これで希望が持てます…

「いいね!」 1

スクラッチシステムで成功しました!

  • プラグインを無効化
  • sudo ./launcher rebuild app
  • バックアップを復元

ライブシステムで作業します。進捗を報告します。

「いいね!」 1

破損したデータは PostCustmField テーブルにあります。ただし、プラグインがない場合は、それらのデータを新しいテーブルに移行しようとしません。

問題は移行自体ではなく、過去のある時点でデータが破損したことです。長年気づかれないまま壊れていました。おそらく、新しいアップボートごとにさらに破損したのだと思います。妥当な修正策は、破損したデータを無視することかもしれません(カスタムフィールドの名前を変更するなどして破損マークを付けるなど)。そうすれば、将来の移行でそれを無視でき、必要であれば手動で修正できるようになります。

「いいね!」 2

ライブでも成功しました。プラグインを無効にしたところ、問題なく動作しました。
なぜもっと早くこの問題に遭遇しなかったのか、まだ疑問に思っています。前述したように、毎月定期的にすべてのシステムを更新しているので、もっと早くこの問題に気づくはずでした。

Discourse DBに自分で接続して、post_custom_fieldsテーブルに何があるか確認するにはどうすればよいですか?

@Jaap-Jan_Swijnenburg 問題が発生したとのこと、申し訳ありません。

その点については、残念ながら同意できません :slight_smile:

古いQnAプラグインは、標準のDiscourseカスタムフィールドの型キャストを使用していました。これは、そのフィールドをJSONにキャストするように設計されています。しかし、このケースのように、それが機能しない場合があります。そのため、Discourseカスタムフィールドを扱う際には(特に古いコードやデータの場合)、フォーマットチェックを組み込む必要があります。Upvotesプラグインも同様のことを行う必要があると考えられます。それが、まさに現在のエラーの原因となっています。

データエクスプローラープラグインを使用して確認できます。

ええ、私はほとんどあなたに委ねており、私たちは本当に同意していると思います。データが破損していなければ、移行は機能するというのが真実だと思います。データが破損している場合は、現在よりも穏やかに失敗すべきであるという点では同意します。

はい、しかしデータはおそらく何年も前に破損していたのでしょう(私が知っているサイトではそうです)、しかしそれは壊滅的に失敗しなかったので、あなたは気づきませんでした。私はそれが期待どおりにアップボートを管理していなかったと確信していますが、誰も気づきませんでした。

railsから、次のようなことをします。

./launcher enter app
rails c

次に、次のようなことを行います。

all_votes=PostCustomField.where(name: "vote_history")
likely_broken_votes=PostCustomField.where(name: "vote_history").where("value like '\'%'")

IDとデータだけを確認します。

all_votes.pluck(:id,:value)

1つのpcfを取得します。

pcf=PostCustomField.find(1234)

修正します。

pcf.value='the stuff you really want in it'
pcf.save

ここで何が起こっているかというと、次のとおりです。

  1. 一部のユーザーは、app.yml ファイルに、リポジトリ URL に私の個人 GitHub ユーザー名が含まれた、非常に古いバージョンの質問回答プラグインをアプリに入れています。

  2. 私は数年前に QnA プラグインを paviliondev に譲渡しました。GitHub はリポジトリ URL を譲渡時にリダイレクトするため、私の個人ユーザー名が含まれた古い URL は機能し続けました。

  3. さらに数年後、Pavilion は Question Answer Plugin を Discourse に譲渡しました。Discourse は当初 discourse-question-answer という名前を維持していました。

  4. 数か月前、私は Discourse にホストされているプラグインの、まだ discourse-question-answer と呼ばれていた頃のフォークを作成しました。

  5. 私の個人 GitHub アカウントが含まれた QnA プラグインへの非常に古いリンクを持っていた人々は、現在、Discourse にホストされている、大幅に更新された discourse-question-answer の私の新しいフォークをクローンしていました。つまり、非常に古いリンクが、新しいプラグインのフォークを指すようになっていたのです。長年経過していましたが、これは予見すべきでした。申し訳ありません。そのフォークは削除しました。

  6. Discourse は discourse-question-answer の名前を discourse-upvotes に変更しました。この名前の変更は、@Jaap-Jan_Swijnenburg さんのケースには実質的な影響はありませんでしたが、あなたが予期せずそのリポジトリのフォークをクローンしている理由です。

  7. discourse/discourse-upvotes (旧 discourse-question-answer) の移行では、post_custom_fieldsvalue 列が JSON として型セーフであることを想定しています。

  8. プラグインが angusmcleod/discourse-question-answer だった頃(数年前)にプラグインによって作成された古いデータは、discourse/discourseHasCustomFields コンサーンによって有効な JSON として保存されていませんでした。推測ですが、このデータは、4年前に JSON 型チェックが追加される前 に追加された可能性が高いです。(エッジケースでは、JSON として登録されたカスタムフィールドに無効な JSON が含まれる可能性があります。)

したがって、

  1. (数年前から更新されていない)angusmcleod/discourse-question-answer の URL を app.yml に持つ人々が Discourse を更新すると、新しいバージョンのプラグインの移行がクローンされ、移行が実行され、潜在的にこのエラーが発生します。

これにはいくつかの解決策があります。

  1. @Jaap-Jan_Swijnenburg さん、あなたのケースでは、私の古い QnA プラグインへの参照を削除するだけで、サイトを再構築できるようになります。それだけです。すでに実行されたようです :+1:

  2. discourse/discourse-upvotes プラグインの移行を更新して、post_custom_fieldsvalue 列の非 JSON 値を処理できるようにすることができます。

2 は、古いバージョンの QnA プラグインから discourse-upvotes に切り替えたい人々の場合にも対応できることに注意してください。その場合、移行が実行され、post_custom_fieldsvalue 列のエントリが無効な JSON でない限り失敗します。

「いいね!」 5