アップグレードエラー - rake db:migrate theme_field_id のインデックス

最新のリリースノート (3.2.0.beta1)で、以前は見かけなかったdiscourse-aiプラグインに気づいたので、このプラグインを追加してDiscourseインスタンスをアップグレードしようとしました。

タイトルで述べたように、現在ブートストラップ中にエラーが発生しており、rake db:migratetheme_field_idに一意インデックスを作成できません。しかし、その時点に至るまでの詳細は以下の通りです…

初回のアップグレード試行 (patch-package エラー)

分割コンテナインストールを実行しているので、以下の手順を実行しました。

  • web_only.ymlを編集して、新しいdiscourse-aiプラグインを追加しました。

    例: プラグインフックに1行追加
    ## Plugins go here
    ## see https://meta.discourse.org/t/19157 for details
    hooks:
      after_code:
        - exec:
            cd: $home/plugins
            cmd:
              - sudo -E -u discourse git clone https://github.com/discourse/docker_manager.git
              - sudo -E -u discourse git clone https://github.com/discourse/discourse-voting.git
              - sudo -E -u discourse git clone https://github.com/discourse/discourse-ai.git
    
  • ./launcher bootstrap web_onlyを実行しました。

patch-packageが見つからないというメッセージでエラーが発生しました。

Git Pull → ブートストラップ (pg-vector エラー)

再試行する前に、最新のランチャーアップデートがあることを確認しておくと良いだろうと考えました。

  • 最新のランチャー関連アップデートがあることを確認するためにgit pullを実行しました。
  • 再度./launcher bootstrap web_onlyを実行しました。

今回はpg-vectorに関連するエラーメッセージが表示されました。

:page_facing_up: discourse-ai ありのブートストラップからのログスニペット

discourse-aiプラグインを再度検討する際に記録するために、PostgreSQLのバージョンをメモしておきました。

  • web_only:
    • クライアント: psql (PostgreSQL) 13.10 (Debian 13.10-1.pgdg110+1)
  • data:
    • サーバー: PostgreSQL 13.9 (Debian 13.9-1.pgdg110+1)

discourse-ai プラグインを削除 → ブートストラップ

そして、web_only.ymlファイルからdiscourse-aiプラグインを削除し、再度ブートストラップを実行しました。

驚いたことに、まだエラーが発生していましたが、今回はrake db:migrateindex_javascript_caches_on_theme_field_idという一意インデックスを作成できず、「Key (theme_field_id)=(3) is duplicated.」という詳細が表示されるようでした。

:page_facing_up: discourse-ai なしのブートストラップからのログスニペット

皆さんの助けを? :folded_hands:

そこで、コミュニティから洞察を得るためにここに助けを求めに来ました。誰かがこれを見たことがあるかもしれないので、さらに深く掘り下げる前に一時停止して意見を聞くのが良いと思いました。

参考までに、3.2.0.beta1-dev (993ed10cf0 ~ 8月9日) がインストールされています。

これに関連しているとは思えませんが、今年の初めにホストマシンを移行したことも言及しておいても害はないと思います…ただし、それ以降、管理UIを通じていくつかのDiscourseアップデートを実行しています。

移行アプローチ

記憶している限りでは、これはソースインスタンスを最新のDiscourseバージョンにアップグレードし、新しいホストにDiscourseをインストールし、ソースをフリーズし、ソースでDiscourseバックアップを実行し、ホスト間で画像などをrsyncし、新しいホストでバックアップを復元するというものでした。

重複インデックスエラーについては、データベースで行うよりも、restart web_only してUIから処理する方がはるかに簡単だと思います。ただし、theme_field_id でエラーが発生したのは初めてです。

ログの rake aborted! のすぐ上の行には、discourse-votingdiscourse-topic-voting になったと記載されています。プラグインセクションのリンクを現在のものに更新してみて、それが役立つかどうか試してみてはどうでしょうか?

重複IDを持つリソースが何を参照しているのか、明確にしていただけますか? theme_field_id が何を指しているのかよくわかりませんでした。

参考までに、web_only コンテナをシャットダウンしていませんでした。通常、停止時間を最小限に抑えるために、まずコンテナをブートストラップします。

試してみます。GitHubが舞台裏で静かにリダイレクトしていると思うので、これは役立たないと思いますが、Discourse側では単なる警告だと思います。 :slight_smile:

データエクスプローラーがインストールされた稼働中のサイトがあれば、このクエリを使用してそれが何を指しているのかを確認できると思います。

SELECT *
FROM theme_fields
WHERE id = 3
「いいね!」 1

そのプラグインは知りませんでした。便利ですね!私はそれをインストールしていませんが、データコンテナに入力してクエリを実行することはできます。

それは素晴らしい手がかりです!エラーメッセージを正しく読んでいるのであれば、theme_fields テーブルに関するものではないと思います。なぜなら、その特定のテーブルには theme_field_id がないからです。ソースコードは確認していませんが、add_index() の最初の引数はテーブル名で、2番目の引数はカラムだと推測します。

それを踏まえると、javascript_caches テーブルのようです。

== 20230817174049 EnsureJavascriptCacheIsUniquePerTheme: migrating ===========
-- remove_index(:javascript_caches, :theme_id)
   -> 0.0208s
-- add_index(:javascript_caches, :theme_id, {:unique=>true})
   -> 0.0079s
-- remove_index(:javascript_caches, :theme_field_id)
   -> 0.0026s
-- add_index(:javascript_caches, :theme_field_id, {:unique=>true})

それで、そのテーブルの構造を確認したところ、theme_field_id カラムがありました。

discourse=# \d javascript_caches
                                          Table "public.javascript_caches"
     Column     |            Type             | Collation | Nullable |                    Default
----------------+-----------------------------+-----------+----------+-----------------------------------------------
 id             | bigint                      |           | not null | nextval('javascript_caches_id_seq'::regclass)
 theme_field_id | bigint                      |           |          |
 digest         | character varying           |           |          |
 content        | text                        |           | not null |
 created_at     | timestamp without time zone |           | not null |
 updated_at     | timestamp without time zone |           | not null |
 theme_id       | bigint                      |           |          |
 source_map     | text                        |           |          |
Indexes:
    "javascript_caches_pkey" PRIMARY KEY, btree (id)
    "index_javascript_caches_on_digest" btree (digest)
    "index_javascript_caches_on_theme_field_id" btree (theme_field_id)
    "index_javascript_caches_on_theme_id" btree (theme_id)
Check constraints:
    "enforce_theme_or_theme_field" CHECK (theme_id IS NOT NULL AND theme_field_id IS NULL OR theme_id IS NULL AND theme_field_id IS NOT NULL)
Foreign-key constraints:
    "fk_rails_58f94aecc4" FOREIGN KEY (theme_id) REFERENCES themes(id) ON DELETE CASCADE
    "fk_rails_ed33506dbd" FOREIGN KEY (theme_field_id) REFERENCES theme_fields(id) ON DELETE CASCADE

そのテーブルをクエリすることができました(コンテンツフィールドは読み取れるように短縮しました)。重複があることがわかります。しかし、これらの重複が何を意味するのかはわかりません。

discourse=# select id, theme_field_id, digest, substring(content from 1 for 64) as content_64, created_at, updated_at, theme_id, substring(source_map from 1 for 64) as source_64 from javascript_caches where theme_field_id = 3;
 id | theme_field_id |                  digest                  |                            content_64                            |         created_at         |         updated_at         | theme_id |                            source_64
----+----------------+------------------------------------------+------------------------------------------------------------------+----------------------------+----------------------------+----------+------------------------------------------------------------------
  1 |              3 | d0b6ec642d5649064ff0501cadc775a9217b16e0 | "define"in window&&define("discourse/theme-3/initializers/theme- | 2019-02-25 01:26:56.606537 | 2023-08-18 20:47:19.596923 |          | {"version":3,"sources":["discourse/initializers/theme-field-3-co
  2 |              3 | 7fd74ecf4448afccdbcd9ccde87acddb4ec6f514 | "define"in window&&define("discourse/theme-3/initializers/theme- | 2019-02-25 01:26:58.228209 | 2023-08-18 20:50:41.049209 |          | {"version":3,"sources":["discourse/initializers/theme-field-3-co

コンテンツが見覚えがあったので、Customize → Theme → My Theme → Common → Head に移動し、マイナーな変更を加えて保存しました。すると、エントリの1つが更新され、もう1つは古いままになっていることがわかりました。

discourse=# select id, theme_field_id, digest, substring(content from 1 for 64) as content_64, created_at, updated_at, theme_id, substring(source_map from 1 for 64) as source_64 from javascript_caches where theme_field_id = 3;
 id | theme_field_id |                  digest                  |                            content_64                            |         created_at         |         updated_at         | theme_id |                            source_64
----+----------------+------------------------------------------+------------------------------------------------------------------+----------------------------+----------------------------+----------+------------------------------------------------------------------
  2 |              3 | 7fd74ecf4448afccdbcd9ccde87acddb4ec6f514 | "define"in window&&define("discourse/theme-3/initializers/theme- | 2019-02-25 01:26:58.228209 | 2023-08-18 20:50:41.049209 |          | {"version":3,"sources":["discourse/initializers/theme-field-3-co
  1 |              3 | 7f4132b1f9ced1b90b8f8fc24812cc11e81fea8d | "define"in window&&define("discourse/theme-3/initializers/theme- | 2019-02-25 01:26:56.606537 | 2023-09-13 21:56:56.312263 |          | {"version":3,"sources":["discourse/initializers/theme-field-3-co
(2 rows)

ここでも、これらの重複が何を意味するのか、古い方を削除しても安全なのか、あるいはこれをクリーンアップできる「キャッシュの再構築」のような他の方法があるのかはわかりません。

正直なところ、これまでのところ 0/2 なので、この件についてはあまり良い情報源ではないかもしれません。:slight_smile:

index_tags_on_name に関して同様のことが発生した過去のトピックがいくつかありますが、役に立つでしょうか?例えば。

「いいね!」 1

データコンテナを再構築してください。ai プラグインには、まだ持っていない拡張機能が必要です。

ご協力ありがとうございます!おかげで正しい方向へ進めたようです。:star_struck:

pg_dumpでテーブルのバックアップを取り、古い重複エントリを削除したところ、ブートストラップは正常に完了しました。:+1:

確認ありがとうございます!データコンテナを更新するか、pgvectorをインストールする必要があるだろうと考えていました。ダウンタイムを避けたくて、それを控えていました。

discourse-aiのスレッドによると、PG15が間もなくリリースされるようなので、もう少し待つかもしれません。

pgvectorの依存関係は、Embeddings機能のためのものかもしれませんが、私はそれを使用する予定はありませんでした。しかし、残念ながらすべてがバンドルされているようです。私は主にOpenAI / ChatGPTの魔法のような書き換え機能で遊びたかっただけなので、おそらく次の大きなデータコンテナアップデートまで待つもう一つの理由です。:slight_smile:

「いいね!」 1

待っても構いませんが、シングルコンテナを使用している人(セルフホスティング者の大多数)は、アップグレードのたびに Postgre をアップグレードしている可能性が高いので、ダウンタイムが数分長くなること以外に待つ理由はあまりありません。データベースの再構築後、web_only コンテナを再構築(または破棄して起動)する必要がある場合があります。

「いいね!」 1

それが主な理由です。たとえ数分であっても、クリティカルでなければ最小限に抑えたいです。

そういえば、ダウンタイムの可能性を考えると、ベータプラグインの使用は控えるべきかもしれませんね。:stuck_out_tongue:

「ゼロダウンタイム」アップグレードに関するいくつかの議論を軽く追ってきましたが、最近の歴史を美化して見ているだけかもしれませんが、過去1年間ほとんどのアップデートで /admin/upgrade を使用できたように感じているので、当面はよりクリティカルなプロジェクトに集中しており、ゼロダウンタイムアプローチへの関心を失っていました。

1月に大きなホストに移行したときは、「ゼロダウンタイム」であり、ユーザーはサイトのコンテンツにアクセスし続けることができましたが、移行中に読み取り専用になった短い期間がありました。次の大きな data アップグレード中にダウンタイムを最小限に抑えたいのであれば、同様のアプローチをメジャーな data コンテナのアップグレードに使用できると思います。

追伸:長年にわたり、コミュニティでのあなたの投稿をたくさん読んできました。コミュニティをサポートするためのあなたのすべての努力に感謝します! :star2:

本当にそうですね!「必要に応じて再構築」しているクライアントのアップグレードはしばらく行っていません。あなたのようなサイトでは、私のダッシュボードが再構築を行い、新しいコンテナが起動した後(既存のコンテナでそれらのマイグレーションが初回実行しないように設定されている場合)にアップグレード後のマイグレーションを実行します。

「いいね!」 1